Compare commits

..

4 Commits

61 changed files with 3989 additions and 2346 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
target target
.settings .settings
data data
bin

View File

@@ -65,7 +65,6 @@ public class MeshTest {
// Now that we have a bunch of bounding boxes, do whatever // Now that we have a bunch of bounding boxes, do whatever
MeshBuilder builder = new MeshBuilder(); MeshBuilder builder = new MeshBuilder();
int i = 0;
for ( AABB box : boxes ) { for ( AABB box : boxes ) {
for ( Facet facet : generateFacetsFor( box ) ) { for ( Facet facet : generateFacetsFor( box ) ) {
builder.addFacet( facet ); builder.addFacet( facet );

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent> <parent>
<artifactId>mc-mesh-master</artifactId> <artifactId>mc-mesh-plugin</artifactId>
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId> <groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
<version>1.0.0</version> <version>0.0.1</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>mc-mesh-plugin</artifactId> <artifactId>mc-mesh-plugin-environment</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<build> <build>
<plugins> <plugins>
@@ -29,25 +29,13 @@
<release>21</release> <release>21</release>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.aaaaahhhhhhh.bananapuncher714.minietest.MeshingTest6</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId> <artifactId>spigot</artifactId>
<version>1.21.10-R0.1-SNAPSHOT</version> <version>1.21.11-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@@ -67,25 +55,17 @@
<groupId>org.ow2.asm</groupId> <groupId>org.ow2.asm</groupId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<artifactId>jackson-annotations</artifactId> <artifactId>lz4-java</artifactId>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>at.yawk.lz4</groupId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<artifactId>jackson-core</artifactId> <artifactId>azure-json</artifactId>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.azure</groupId>
</exclusion>
<exclusion>
<artifactId>jackson-databind</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<artifactId>oshi-core</artifactId> <artifactId>oshi-core</artifactId>
<groupId>com.github.oshi</groupId> <groupId>com.github.oshi</groupId>
</exclusion> </exclusion>
<exclusion>
<artifactId>jcip-annotations</artifactId>
<groupId>com.github.stephenc.jcip</groupId>
</exclusion>
<exclusion> <exclusion>
<artifactId>msal4j</artifactId> <artifactId>msal4j</artifactId>
<groupId>com.microsoft.azure</groupId> <groupId>com.microsoft.azure</groupId>
@@ -110,22 +90,6 @@
<artifactId>logging</artifactId> <artifactId>logging</artifactId>
<groupId>com.mojang</groupId> <groupId>com.mojang</groupId>
</exclusion> </exclusion>
<exclusion>
<artifactId>content-type</artifactId>
<groupId>com.nimbusds</groupId>
</exclusion>
<exclusion>
<artifactId>lang-tag</artifactId>
<groupId>com.nimbusds</groupId>
</exclusion>
<exclusion>
<artifactId>nimbus-jose-jwt</artifactId>
<groupId>com.nimbusds</groupId>
</exclusion>
<exclusion>
<artifactId>oauth2-oidc-sdk</artifactId>
<groupId>com.nimbusds</groupId>
</exclusion>
<exclusion> <exclusion>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
@@ -135,7 +99,11 @@
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<artifactId>netty-codec</artifactId> <artifactId>netty-codec-base</artifactId>
<groupId>io.netty</groupId>
</exclusion>
<exclusion>
<artifactId>netty-codec-compression</artifactId>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
</exclusion> </exclusion>
<exclusion> <exclusion>
@@ -162,6 +130,10 @@
<artifactId>netty-transport-classes-epoll</artifactId> <artifactId>netty-transport-classes-epoll</artifactId>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
</exclusion> </exclusion>
<exclusion>
<artifactId>netty-transport-classes-kqueue</artifactId>
<groupId>io.netty</groupId>
</exclusion>
<exclusion> <exclusion>
<artifactId>netty-transport-native-epoll</artifactId> <artifactId>netty-transport-native-epoll</artifactId>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
@@ -170,6 +142,14 @@
<artifactId>netty-transport-native-epoll</artifactId> <artifactId>netty-transport-native-epoll</artifactId>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
</exclusion> </exclusion>
<exclusion>
<artifactId>netty-transport-native-kqueue</artifactId>
<groupId>io.netty</groupId>
</exclusion>
<exclusion>
<artifactId>netty-transport-native-kqueue</artifactId>
<groupId>io.netty</groupId>
</exclusion>
<exclusion> <exclusion>
<artifactId>netty-transport-native-unix-common</artifactId> <artifactId>netty-transport-native-unix-common</artifactId>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
@@ -186,14 +166,6 @@
<artifactId>jna-platform</artifactId> <artifactId>jna-platform</artifactId>
<groupId>net.java.dev.jna</groupId> <groupId>net.java.dev.jna</groupId>
</exclusion> </exclusion>
<exclusion>
<artifactId>accessors-smart</artifactId>
<groupId>net.minidev</groupId>
</exclusion>
<exclusion>
<artifactId>json-smart</artifactId>
<groupId>net.minidev</groupId>
</exclusion>
<exclusion> <exclusion>
<artifactId>jopt-simple</artifactId> <artifactId>jopt-simple</artifactId>
<groupId>net.sf.jopt-simple</groupId> <groupId>net.sf.jopt-simple</groupId>
@@ -215,8 +187,8 @@
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<artifactId>lz4-java</artifactId> <artifactId>jspecify</artifactId>
<groupId>org.lz4</groupId> <groupId>org.jspecify</groupId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>

View File

@@ -14,7 +14,7 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId> <artifactId>spigot</artifactId>
<version>1.21.10-R0.1-SNAPSHOT</version> <version>1.21.11-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -66,19 +66,6 @@
<release>21</release> <release>21</release>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.aaaaahhhhhhh.bananapuncher714.minietest.MeshingTest6</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command; package com.aaaaahhhhhhh.bananapuncher714.mesh.command;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -8,7 +8,7 @@ import java.util.Set;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.permissions.Permission; import org.bukkit.permissions.Permission;
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.BukkitUtil; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.BukkitUtil;
public class CommandBase { public class CommandBase {
protected PluginCommand command; protected PluginCommand command;

View File

@@ -1,8 +1,8 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command; package com.aaaaahhhhhhh.bananapuncher714.mesh.command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor.CommandExecutable; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor.CommandExecutable;
public class CommandOption { public class CommandOption {
protected CommandExecutable exe; protected CommandExecutable exe;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command; package com.aaaaahhhhhhh.bananapuncher714.mesh.command;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command; package com.aaaaahhhhhhh.bananapuncher714.mesh.command;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command; package com.aaaaahhhhhhh.bananapuncher714.mesh.command;
public class SplitCommand { public class SplitCommand {
protected String[] input; protected String[] input;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command; package com.aaaaahhhhhhh.bananapuncher714.mesh.command;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -13,10 +13,10 @@ import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.util.StringUtil; import org.bukkit.util.StringUtil;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor.CommandExecutable; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor.CommandExecutable;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.InputValidator; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidator;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.InputValidatorString; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidatorString;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender.SenderValidator; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender.SenderValidator;
/** /**
* A build and run command framework for automatic tab completions and easy branching. * A build and run command framework for automatic tab completions and easy branching.

View File

@@ -1,8 +1,8 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.CommandParameters; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.CommandParameters;
public interface CommandExecutable { public interface CommandExecutable {
void execute( CommandSender sender, String[] args, CommandParameters params ); void execute( CommandSender sender, String[] args, CommandParameters params );

View File

@@ -1,8 +1,8 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.CommandParameters; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.CommandParameters;
public class CommandExecutableMessage implements CommandExecutable { public class CommandExecutableMessage implements CommandExecutable {
protected String message; protected String message;

View File

@@ -5,4 +5,4 @@
* @author BananaPuncher714 * @author BananaPuncher714
* *
*/ */
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor;

View File

@@ -3,4 +3,4 @@
* *
* @author BananaPuncher714 * @author BananaPuncher714
*/ */
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command; package com.aaaaahhhhhhh.bananapuncher714.mesh.command;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;

View File

@@ -5,4 +5,4 @@
* @author BananaPuncher714 * @author BananaPuncher714
* *
*/ */
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;

View File

@@ -5,4 +5,4 @@
* @author BananaPuncher714 * @author BananaPuncher714
* *
*/ */
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender; package com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender;

View File

@@ -0,0 +1,10 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkMesh;
public interface EnvironmentHandler {
public void onMeshLoad( ChunkLocation location, ChunkMesh mesh );
public void onMeshUnload( ChunkLocation location, ChunkMesh mesh );
public void onMeshUpdate( ChunkLocation location, ChunkMesh mesh );
}

View File

@@ -1,34 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment;
import java.io.File;
import org.bukkit.plugin.java.JavaPlugin;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.FileUtil;
public class McMeshEnvironment extends JavaPlugin {
@Override
public void onEnable() {
FileUtil.saveToFile( getResource( "native/windows/x86_64/bulletjme.dll" ), new File( getDataFolder() + "/lib", "bulletjme.dll" ), false );
FileUtil.saveToFile( getResource( "native/osx/x86_64/libbulletjme.dylib" ), new File( getDataFolder() + "/lib", "libbulletjme.dylib" ), false );
FileUtil.saveToFile( getResource( "native/linux/x86_64/libbulletjme.so" ), new File( getDataFolder() + "/lib", "libbulletjme.so" ), false );
if ( !loadNativeLibraries() ) {
getLogger().severe( "Unable to load Bullet JME native libraries! Disabling plugin" );
Bukkit.getPluginManager().disablePlugin( this );
return;
}
}
private final boolean loadNativeLibraries() {
if ( SystemUtils.IS_OS_MAC ) {
System.load( new File( getDataFolder() + "/lib", "libbulletjme.dylib" ).getAbsolutePath() );
} else if ( SystemUtils.IS_OS_LINUX ) {
System.load( new File( getDataFolder() + "/lib", "libbulletjme.so" ).getAbsolutePath() );
} else if ( SystemUtils.IS_OS_WINDOWS ) {
System.load( new File( getDataFolder() + "/lib", "bulletjme.dll" ).getAbsolutePath() );
} else {
return false;
}
return true;
}
}

View File

@@ -1,8 +1,9 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects; package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.io.Serializable; import java.io.Serializable;
import org.bukkit.util.BoundingBox; import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
public class Aabb implements Serializable { public class Aabb implements Serializable {
private static final long serialVersionUID = 6518512405568765913L; private static final long serialVersionUID = 6518512405568765913L;
@@ -18,6 +19,10 @@ public class Aabb implements Serializable {
public final int depth; public final int depth;
public final int height; public final int height;
public Aabb( Vector min, Vector max ) {
this( min.getBlockX(), min.getBlockY(), min.getBlockZ(), max.getBlockX(), max.getBlockY(), max.getBlockZ() );
}
public Aabb( final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ ) { public Aabb( final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ ) {
this.minX = minX; this.minX = minX;
this.minY = minY; this.minY = minY;
@@ -47,4 +52,12 @@ public class Aabb implements Serializable {
public int getVolume() { public int getVolume() {
return width * depth * height; return width * depth * height;
} }
public Vector getMinimumCorner() {
return new Vector( minX, minY, minZ );
}
public Vector getMaximumCorner() {
return new Vector( maxX, maxY, maxZ );
}
} }

View File

@@ -0,0 +1,62 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import org.bukkit.util.Vector;
import com.jme3.bullet.collision.shapes.infos.IndexedMesh;
import com.jme3.math.Vector3f;
public abstract class AbstractMesh {
// References to every point used by at least one planemesh
public TreeSet< VectorReference > pointReferences = new TreeSet< VectorReference >();
// Map of meshes to each plane
// TODO Allow for non axis-aligned planes
public Map< MinecraftPlane, PlaneMesh > planes = new TreeMap< MinecraftPlane, PlaneMesh >();
public abstract Vector getMinimumCorner();
public abstract Vector getMaximumCorner();
public abstract BlockDataInformation getBlockDataInformationFor( Vector position );
public abstract void setBlockDataInformationFor( BlockDataInformation information, Vector position );
public IndexedMesh toIndexedMesh() {
final Vector3f[] positionArray = new Vector3f[ pointReferences.size() ];
int vertexIndex = 0;
for ( final VectorReference ref : pointReferences ) {
final Vector vector = ref.vector;
positionArray[ vertexIndex ] = new Vector3f( ( float ) vector.getX(), ( float ) vector.getY(), ( float ) vector.getZ() );
ref.index = vertexIndex;
++vertexIndex;
}
final int totalTriangleCount = planes.values().stream().mapToInt( m -> m.completedPolygons.size() ).sum();
int triangleIndex = 0;
final int[] indexArray = new int[ totalTriangleCount * 3 ];
for ( final PlaneMesh mesh : planes.values() ) {
for ( final IndexedPolygon triangle : mesh.completedPolygons ) {
Collection< VectorReference > refs = triangle.getPoints();
if ( refs.size() != 3 ) {
throw new IllegalStateException( "Triangle does not have exactly 3 vertices!" );
}
final int indexArrayStart = triangleIndex * 3;
Iterator< VectorReference > it = refs.iterator();
indexArray[ indexArrayStart ] = it.next().index;
indexArray[ indexArrayStart + 1 ] = it.next().index;
indexArray[ indexArrayStart + 2 ] = it.next().index;
++triangleIndex;
}
}
return new IndexedMesh( positionArray, indexArray );
}
}

View File

@@ -0,0 +1,25 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BoundingBox;
public class BlockDataInformation {
// If the block is complex/simple/empty
public BlockDataType type;
// Hashcode of the current block's blockdata so we can check if it changed
public final int blockDataHash;
// The bounding boxes for each complex block, null if air or a cube
public BoundingBox[] boundingBoxes;
public BlockDataInformation( int hash ) {
blockDataHash = hash;
}
public BlockDataInformation( BlockData data ) {
blockDataHash = data.hashCode();
}
public boolean isBlockData( BlockData data ) {
return blockDataHash == data.hashCode();
}
}

View File

@@ -0,0 +1,5 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
public enum BlockDataType {
NONE, COMPLEX, SOLID
}

View File

@@ -1,9 +1,7 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects; package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.util.BitSet; import java.util.BitSet;
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.BinaryWriter;
public class BlockDataTypeSet { public class BlockDataTypeSet {
private static final int BLOCK_SIZE; private static final int BLOCK_SIZE;
private static final BitSet[] SETS; private static final BitSet[] SETS;

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects; package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;

View File

@@ -1,28 +1,25 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects; package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.Collection;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.TreeSet;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.util.BoundingBox; import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.Point;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.MinecraftPlane.PlaneAxis; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.MinecraftPlane.PlaneAxis;
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.BinaryWriter; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.BinaryWriter;
import com.jme3.bullet.collision.shapes.infos.IndexedMesh; import com.jme3.bullet.collision.shapes.infos.IndexedMesh;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
public class ChunkMesh { public class ChunkMesh extends AbstractMesh {
// TODO Public for now while I figure out how to organize the stuff properly // TODO Public for now while I figure out how to organize the stuff properly
// Hashcode of the current block's blockdata so we can check if it changed // Hashcode of the current block's blockdata so we can check if it changed
@@ -31,11 +28,6 @@ public class ChunkMesh {
private BoundingBox[][] boxes; private BoundingBox[][] boxes;
// Stores which blocks are complex/simple/empty // Stores which blocks are complex/simple/empty
private BlockDataTypeSet blockTypes; private BlockDataTypeSet blockTypes;
// References to every point used by at least one planemesh
public TreeSet< VectorReference > pointReferences = new TreeSet< VectorReference >();
// Map of meshes to each plane
// TODO Allow for non axis-aligned planes
public Map< MinecraftPlane, PlaneMesh > planes = new TreeMap< MinecraftPlane, PlaneMesh >();
// Bounding box of this mesh // Bounding box of this mesh
private Aabb box; private Aabb box;
@@ -90,6 +82,37 @@ public class ChunkMesh {
return results; return results;
} }
@Override
public Vector getMinimumCorner() {
return box.getMinimumCorner();
}
@Override
public Vector getMaximumCorner() {
return box.getMaximumCorner();
}
@Override
public BlockDataInformation getBlockDataInformationFor( Vector position ) {
final int index = position.getBlockX() + ( position.getBlockZ() << 4 ) + ( position.getBlockY() << 8 );
BlockDataInformation information = new BlockDataInformation( data[ index ] );
information.type = getType( index );
information.boundingBoxes = getBoxesAt( index );
return information;
}
@Override
public void setBlockDataInformationFor( BlockDataInformation information, Vector position ) {
final int index = position.getBlockX() + ( position.getBlockZ() << 4 ) + ( position.getBlockY() << 8 );
data[ index ] = information.blockDataHash;
setType( index, information.type );
setBoxes( index, information.boundingBoxes );
}
@Override
public IndexedMesh toIndexedMesh() { public IndexedMesh toIndexedMesh() {
final Vector3f[] positionArray = new Vector3f[ pointReferences.size() ]; final Vector3f[] positionArray = new Vector3f[ pointReferences.size() ];
int vertexIndex = 0; int vertexIndex = 0;
@@ -108,14 +131,16 @@ public class ChunkMesh {
final int[] indexArray = new int[ totalTriangleCount * 3 ]; final int[] indexArray = new int[ totalTriangleCount * 3 ];
for ( final PlaneMesh mesh : planes.values() ) { for ( final PlaneMesh mesh : planes.values() ) {
for ( final IndexedPolygon triangle : mesh.completedPolygons ) { for ( final IndexedPolygon triangle : mesh.completedPolygons ) {
if ( triangle.points.size() != 3 ) { Collection< VectorReference > refs = triangle.getPoints();
if ( refs.size() != 3 ) {
throw new IllegalStateException( "Triangle does not have exactly 3 vertices!" ); throw new IllegalStateException( "Triangle does not have exactly 3 vertices!" );
} }
final int indexArrayStart = triangleIndex * 3; final int indexArrayStart = triangleIndex * 3;
indexArray[ indexArrayStart ] = triangle.points.get( 0 ).index; Iterator< VectorReference > it = refs.iterator();
indexArray[ indexArrayStart + 1 ] = triangle.points.get( 1 ).index; indexArray[ indexArrayStart ] = it.next().index;
indexArray[ indexArrayStart + 2 ] = triangle.points.get( 2 ).index; indexArray[ indexArrayStart + 1 ] = it.next().index;
indexArray[ indexArrayStart + 2 ] = it.next().index;
++triangleIndex; ++triangleIndex;
} }
@@ -198,8 +223,8 @@ public class ChunkMesh {
// Write each triangle // Write each triangle
writer.write( mesh.completedPolygons.size() ); writer.write( mesh.completedPolygons.size() );
for ( final IndexedPolygon poly : mesh.completedPolygons ) { for ( final IndexedPolygon poly : mesh.completedPolygons ) {
writer.write( poly.points.size() ); writer.write( poly.getPointCount() );
for ( final VectorReference ref : poly.points ) { for ( final VectorReference ref : poly.getPoints() ) {
writer.write( ref.index ); writer.write( ref.index );
} }
} }
@@ -252,7 +277,7 @@ public class ChunkMesh {
final PlaneMesh planeMesh = new PlaneMesh(); final PlaneMesh planeMesh = new PlaneMesh();
planeMesh.generatedRegions = new ArrayDeque< Polygon >(); planeMesh.generatedRegions = new ArrayDeque< Polygon >();
planeMesh.completedPolygons = new ArrayDeque< IndexedPolygon >(); planeMesh.completedPolygons = new ArrayDeque< IndexedTriangle >();
final int regionCount = buffer.getInt(); final int regionCount = buffer.getInt();
for ( int j = 0; j < regionCount; ++j ) { for ( int j = 0; j < regionCount; ++j ) {
final int vertexCount = buffer.getInt(); final int vertexCount = buffer.getInt();
@@ -269,9 +294,22 @@ public class ChunkMesh {
for ( int j = 0; j < triangleCount; ++j ) { for ( int j = 0; j < triangleCount; ++j ) {
final int vertexCount = buffer.getInt(); final int vertexCount = buffer.getInt();
final IndexedPolygon triangle = new IndexedPolygon(); final IndexedTriangle triangle = new IndexedTriangle();
for ( int k = 0; k < vertexCount; ++k ) { for ( int k = 0; k < vertexCount; ++k ) {
triangle.points.add( references[ buffer.getInt() ] ); switch ( k ) {
case 0:
triangle.setPoint1( references[ buffer.getInt() ] );
break;
case 1:
triangle.setPoint2( references[ buffer.getInt() ] );
break;
case 2:
triangle.setPoint3( references[ buffer.getInt() ] );
break;
default:
// Discard
buffer.getInt();
}
} }
planeMesh.completedPolygons.add( triangle ); planeMesh.completedPolygons.add( triangle );

View File

@@ -0,0 +1,19 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class IndexedNGon implements IndexedPolygon {
List< VectorReference > points = new ArrayList< VectorReference >();
@Override
public Collection< VectorReference > getPoints() {
return points;
}
@Override
public int getPointCount() {
return points.size();
}
}

View File

@@ -0,0 +1,11 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.util.Collection;
/*
* Represents a polygon with associated vector references
*/
public abstract interface IndexedPolygon {
public Collection< VectorReference > getPoints();
public int getPointCount();
}

View File

@@ -0,0 +1,44 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.util.Collection;
import java.util.List;
public class IndexedTriangle implements IndexedPolygon {
private VectorReference p1;
private VectorReference p2;
private VectorReference p3;
public VectorReference getPoint1() {
return p1;
}
public VectorReference getPoint2() {
return p2;
}
public VectorReference getPoint3() {
return p3;
}
public void setPoint1( VectorReference p1 ) {
this.p1 = p1;
}
public void setPoint2( VectorReference p2 ) {
this.p2 = p2;
}
public void setPoint3( VectorReference p3 ) {
this.p3 = p3;
}
@Override
public Collection< VectorReference > getPoints() {
return List.of( p1, p2, p3 );
}
@Override
public int getPointCount() {
return 3;
}
}

View File

@@ -1,10 +1,8 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects; package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.io.Serializable;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.Point;
public class MinecraftPlane implements Comparable< MinecraftPlane > { public class MinecraftPlane implements Comparable< MinecraftPlane > {
public final PlaneAxis normal; public final PlaneAxis normal;

View File

@@ -0,0 +1,10 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.util.Collection;
import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.Polygon;
public class PlaneMesh {
public Collection< Polygon > generatedRegions;
public Collection< IndexedTriangle > completedPolygons;
}

View File

@@ -0,0 +1,38 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.util.Vector;
public class SparseMesh extends AbstractMesh {
private Map< Vector, BlockDataInformation > data = new HashMap< Vector, BlockDataInformation >();
// Bounding box of this mesh
private Vector min, max;
public SparseMesh( Vector min, Vector max ) {
this.min = min.clone();
this.max = max.clone();
}
@Override
public Vector getMinimumCorner() {
return min;
}
@Override
public Vector getMaximumCorner() {
return max;
}
@Override
public BlockDataInformation getBlockDataInformationFor( Vector position ) {
return data.get( position.toBlockVector() );
}
@Override
public void setBlockDataInformationFor( BlockDataInformation information, Vector position ) {
data.put( position, information );
}
}

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects; package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;

View File

@@ -18,7 +18,7 @@ import org.bukkit.plugin.SimplePluginManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader; import org.bukkit.plugin.java.JavaPluginLoader;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.McMeshEnvironment; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.McMeshEnvironmentPlugin;
public class BukkitUtil { public class BukkitUtil {
private static Constructor< PluginCommand > PLUGINCOMMAND_CONSTRUCTOR; private static Constructor< PluginCommand > PLUGINCOMMAND_CONSTRUCTOR;
@@ -69,7 +69,7 @@ public class BukkitUtil {
public static PluginCommand constructCommand( String id ) { public static PluginCommand constructCommand( String id ) {
PluginCommand command = null; PluginCommand command = null;
try { try {
command = PLUGINCOMMAND_CONSTRUCTOR.newInstance( id, JavaPlugin.getPlugin( McMeshEnvironment.class ) ); command = PLUGINCOMMAND_CONSTRUCTOR.newInstance( id, JavaPlugin.getPlugin( McMeshEnvironmentPlugin.class ) );
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
@@ -84,7 +84,7 @@ public class BukkitUtil {
if ( Bukkit.getServer().isPrimaryThread() ) { if ( Bukkit.getServer().isPrimaryThread() ) {
Bukkit.getPluginManager().callEvent( event ); Bukkit.getPluginManager().callEvent( event );
} else { } else {
Bukkit.getScheduler().scheduleSyncDelayedTask( JavaPlugin.getPlugin( McMeshEnvironment.class ), () -> { callEventSync( event ); } ); Bukkit.getScheduler().scheduleSyncDelayedTask( JavaPlugin.getPlugin( McMeshEnvironmentPlugin.class ), () -> { callEventSync( event ); } );
} }
} }
@@ -111,7 +111,7 @@ public class BukkitUtil {
if ( JAVAPLUGINLOADER_GETCLASS_1 != null ) { if ( JAVAPLUGINLOADER_GETCLASS_1 != null ) {
return ( Class< ? > ) JAVAPLUGINLOADER_GETCLASS_1.invoke( loader, name ); return ( Class< ? > ) JAVAPLUGINLOADER_GETCLASS_1.invoke( loader, name );
} else { } else {
return ( Class< ? > ) JAVAPLUGINLOADER_GETCLASS_2.invoke( loader, name, true, JavaPlugin.getPlugin( MiniePlugin.class ).getDescription() ); return ( Class< ? > ) JAVAPLUGINLOADER_GETCLASS_2.invoke( loader, name, true, JavaPlugin.getPlugin( McMeshEnvironmentPlugin.class ).getDescription() );
} }
} }
} }

View File

@@ -2,7 +2,7 @@ package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkMesh; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkMesh;
public class ChunkMeshUtil { public class ChunkMeshUtil {
public static byte[] serialize( final ChunkMesh mesh ) { public static byte[] serialize( final ChunkMesh mesh ) {

View File

@@ -0,0 +1,59 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util;
import org.bukkit.Location;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_21_R7.CraftWorld;
import org.bukkit.craftbukkit.v1_21_R7.block.data.CraftBlockData;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import net.minecraft.core.BlockPosition;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.shapes.VoxelShapeCollision;
public class NmsUtil {
// 1.21.5
public static VoxelShape getShape( BlockData blockData, Location location, BlockShapeType type ) {
final CraftBlockData data = ( CraftBlockData ) blockData;
WorldServer server = null;
BlockPosition pos = null;
if ( location != null ) {
server = ( ( CraftWorld ) location.getWorld() ).getHandle();
pos = new BlockPosition( location.getBlockX(), location.getBlockY(), location.getBlockZ() );
}
switch ( type ) {
default:
case SHAPE:
return data.getState().f( server, pos );
case COLLISION_SHAPE:
return data.getState().g( server, pos );
case VISUAL_SHAPE:
return data.getState().c( server, pos, VoxelShapeCollision.a() );
case INTERACTION_SHAPE:
return data.getState().i( server, pos );
case BLOCK_SUPPORT_SHAPE:
return data.getState().h( server, pos );
}
}
public static BoundingBox[] convertFrom( final VoxelShape shape ) {
return convertFrom( shape, new Vector() );
}
public static BoundingBox[] convertFrom( final VoxelShape shape, final Vector offset ) {
return shape.e().stream()
.map( aabb -> { return new BoundingBox( aabb.a, aabb.b, aabb.c, aabb.d, aabb.e, aabb.f ).shift( offset ); } )
.toArray( BoundingBox[]::new );
}
public enum BlockShapeType {
SHAPE,
COLLISION_SHAPE,
VISUAL_SHAPE,
INTERACTION_SHAPE,
BLOCK_SUPPORT_SHAPE
}
}

View File

@@ -1,51 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.ReentrantLock;
import org.bukkit.Chunk;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkMesh;
public class ChunkMeshCache {
final File directory;
Map< ChunkLocation, ChunkMesh > meshes = new TreeMap< ChunkLocation, ChunkMesh >();
Collection< ChunkLocation > shouldRemove = new HashSet< ChunkLocation >();
ReentrantLock lock = new ReentrantLock();
public ChunkMeshCache( final File directory ) {
this.directory = directory;
}
public void onChunkLoad( final Chunk chunk ) {
final ChunkLocation location = new ChunkLocation( chunk );
// Unqueue this chunk for removal if it's queued
shouldRemove.remove( location );
// TODO Add a ticket
chunk.addPluginChunkTicket( null );
// Does the mesh map contain the current location?
{
// If not, then load or mesh the chunk
// Emit a chunk mesh complete event
}
}
public void saveAndRemove( final ChunkLocation location ) {
lock.lock();
meshes.remove( location );
lock.unlock();
}
public void saveAndRemoveAll() {
lock.unlock();
}
}

View File

@@ -1,37 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.PlaneCollisionShape;
import com.jme3.bullet.objects.PhysicsBody;
import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.math.Plane;
import com.jme3.math.Vector3f;
public class MinieTest {
public static void main( String[] args ) {
System.loadLibrary( "bulletjme" );
System.out.println( "Testing a simple PhysicsSpace" );
PhysicsSpace space = new PhysicsSpace( BroadphaseType.DBVT );
PlaneCollisionShape plane = new PlaneCollisionShape( new Plane( new Vector3f( 0, 1, 0 ), 0 ) );
PhysicsRigidBody planeBody = new PhysicsRigidBody( plane, PhysicsBody.massForStatic );
planeBody.setPhysicsLocation( new Vector3f( 0, 0, 0 ) );
BoxCollisionShape box = new BoxCollisionShape( 0.5f );
PhysicsRigidBody rigid = new PhysicsRigidBody( box, 1f );
rigid.setPhysicsLocation( new Vector3f( 0f, 100f, 0f ) );
space.addCollisionObject( rigid );
space.addCollisionObject( planeBody );
for ( float i = 0; i < 9.6; i += 1 / 256.0 ) {
space.update( i );
Vector3f loc = rigid.getPhysicsLocation();
System.out.println( i + "\t: " + loc.getX() + ", " + loc.getY() + ", " + loc.getZ() );
}
}
}

View File

@@ -1,5 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
public enum BlockDataType {
NONE, COMPLEX, SOLID
}

View File

@@ -1,8 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
import java.util.ArrayList;
import java.util.List;
public class IndexedPolygon {
public List< VectorReference > points = new ArrayList< VectorReference >();
}

View File

@@ -1,10 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
import java.util.Collection;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
public class PlaneMesh {
public Collection< Polygon > generatedRegions;
public Collection< IndexedPolygon > completedPolygons;
}

View File

@@ -1,14 +1,7 @@
name: MC-Mesh-Environment name: Mc-Mesh-Environment
main: com.aaaaahhhhhhh.bananapuncher714.minietest.MiniePlugin main: com.aaaaahhhhhhh.bananapuncher714.mesh.environment.McMeshEnvironmentPlugin
version: 0.0.1 version: 0.0.1
description: BulletJME and MC-Mesh integration description: BulletJME and MC-Mesh integration
author: BananaPuncher714 author: BananaPuncher714
api-version: 1.13 api-version: 1.13
#libraries: load: STARTUP
#- com.github.stephengold:Minie:7.5.0
commands:
minie:
description: Main Minie command
aliases: []
permission: minie

40
plugin/physics/pom.xml Normal file
View File

@@ -0,0 +1,40 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
<artifactId>mc-mesh-plugin</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>mc-mesh-plugin-physics</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.21.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
<artifactId>mc-mesh-plugin-environment</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.1</version>
<configuration>
<release>21</release>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,22 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.physics;
import org.bukkit.entity.Display;
import org.bukkit.util.Vector;
class AuxiliaryDisplayStruct {
Display display;
Vector offset;
Vector scale;
AuxiliaryDisplayStruct( Display display, Vector offset ) {
this.display = display;
this.offset = offset.clone();
this.scale = new Vector( 1, 1, 1 );
}
AuxiliaryDisplayStruct setScale( Vector scale ) {
this.scale = scale.clone();
return this;
}
}

View File

@@ -0,0 +1,347 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.physics;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.BlockDisplay;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Transformation;
import org.bukkit.util.Vector;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.CommandParameters;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.SubCommand;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor.CommandExecutableMessage;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidatorDouble;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidatorInt;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender.SenderValidatorPlayer;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.EnvironmentHandler;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.McMeshEnvironmentPlugin;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkMesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.NmsUtil;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.NmsUtil.BlockShapeType;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.CompoundCollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.collision.shapes.infos.IndexedMesh;
import com.jme3.bullet.objects.PhysicsBody;
import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
public class McMeshPhysicsPlugin extends JavaPlugin {
private static final int TIME_STEPS = 10;
private static final float SIMULATION_SPEED = 1f;
private PhysicsSpace space;
private boolean paused = false;
private boolean teleportOnDeactivate = false;
private Map< PhysicsCollisionObject, AuxiliaryDisplayStruct > linkedDisplays = new HashMap< PhysicsCollisionObject, AuxiliaryDisplayStruct >();
private Set< PhysicsCollisionObject > active = new HashSet< PhysicsCollisionObject >();
private Map< ChunkLocation, PhysicsRigidBody > chunks = new HashMap< ChunkLocation, PhysicsRigidBody >();
@Override
public void onEnable() {
registerCommands();
space = new PhysicsSpace( BroadphaseType.DBVT );
space.setAccuracy( 1f / ( TIME_STEPS * 20f ) );
JavaPlugin.getPlugin( McMeshEnvironmentPlugin.class ).registerHandler( new EnvironmentHandler() {
@Override
public void onMeshLoad( ChunkLocation location, ChunkMesh mesh ) {
if ( !location.getWorld().getName().equalsIgnoreCase( "world" ) ) {
return;
}
// Now, create a physics object from the chunk mesh
final IndexedMesh nativeMesh = mesh.toIndexedMesh();
// Enable quantized AABB compression... hopefully that doesn't mess with the accuracy or anything...
final MeshCollisionShape meshCollision = new MeshCollisionShape( true, nativeMesh );
// Create a rigid body
PhysicsRigidBody rigid = new PhysicsRigidBody( meshCollision, PhysicsBody.massForStatic );
rigid.setPhysicsLocation( new Vector3f( location.getX() << 4, location.getWorld().getMinHeight(), location.getZ() << 4 ) );
rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) );
rigid.setKinematic( false );
Bukkit.getScheduler().runTask( McMeshPhysicsPlugin.this, () -> {
space.addCollisionObject( rigid );
PhysicsRigidBody old = chunks.put( location, rigid );
if ( old != null ) {
space.remove( old );
}
} );
}
@Override
public void onMeshUnload( ChunkLocation location, ChunkMesh mesh ) {
if ( !location.getWorld().getName().equalsIgnoreCase( "world" ) ) {
return;
}
space.removeCollisionObject( chunks.remove( location ) );
}
@Override
public void onMeshUpdate( ChunkLocation location, ChunkMesh mesh ) {
if ( !location.getWorld().getName().equalsIgnoreCase( "world" ) ) {
return;
}
// Now, create a physics object from the chunk mesh
final IndexedMesh nativeMesh = mesh.toIndexedMesh();
// Enable quantized AABB compression... hopefully that doesn't mess with the accuracy or anything...
final MeshCollisionShape meshCollision = new MeshCollisionShape( true, nativeMesh );
// Create a rigid body
PhysicsRigidBody rigid = new PhysicsRigidBody( meshCollision, PhysicsBody.massForStatic );
rigid.setPhysicsLocation( new Vector3f( location.getX() << 4, location.getWorld().getMinHeight(), location.getZ() << 4 ) );
rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) );
rigid.setKinematic( false );
Bukkit.getScheduler().runTask( McMeshPhysicsPlugin.this, () -> {
space.addCollisionObject( rigid );
PhysicsRigidBody old = chunks.put( location, rigid );
if ( old != null ) {
space.remove( old );
}
} );
space.activateAll( true );
}
} );
Bukkit.getScheduler().runTaskTimer( this, () -> {
if ( !paused ) {
// Update the real world with the physics space objects
space.distributeEvents();
space.update( SIMULATION_SPEED / 20f, TIME_STEPS );
for ( Iterator< Entry< PhysicsCollisionObject, AuxiliaryDisplayStruct > > it = linkedDisplays.entrySet().iterator(); it.hasNext(); ) {
Entry< PhysicsCollisionObject, AuxiliaryDisplayStruct > entry = it.next();
PhysicsCollisionObject obj = entry.getKey();
AuxiliaryDisplayStruct disp = entry.getValue();
if ( !disp.display.isValid() ) {
it.remove();
space.removeCollisionObject( obj );
continue;
}
Location displayLocation = disp.display.getLocation();
// Do not calculate for this object if it is inactive
if ( !obj.isActive() ) {
if ( teleportOnDeactivate && active.remove( obj ) ) {
// Newly deactivated object, teleport the display to the actual position to prevent the translation from getting too large
Transformation currentTransformation = disp.display.getTransformation();
org.joml.Vector3f trans = currentTransformation.getTranslation();
displayLocation.add( trans.x(), trans.y(), trans.z() );
disp.display.teleport( displayLocation );
Transformation newTrans = new Transformation( new org.joml.Vector3f( 0, 0, 0 ), currentTransformation.getLeftRotation(), currentTransformation.getScale(), currentTransformation.getRightRotation() );
disp.display.setInterpolationDelay( 0 );
disp.display.setInterpolationDuration( 0 );
disp.display.setTransformation( newTrans );
}
continue;
} else {
active.add( obj );
}
Vector3f location = obj.getPhysicsLocation();
Quaternion rotation = new Quaternion();
obj.getPhysicsRotation( rotation );
Vector offsetVec = disp.offset;
Vector scale = disp.scale;
Matrix4f transformRot = new Matrix4f();
transformRot.set( new Quaternionf( rotation.getX(), rotation.getY(), rotation.getZ(), rotation.getW() ) );
transformRot.mul( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, - ( float ) offsetVec.getX(), - ( float ) offsetVec.getY(), - ( float ) offsetVec.getZ(), 1 );
transformRot.mul( ( float ) scale.getX(), 0, 0, 0, 0, ( float ) scale.getY(), 0, 0, 0, 0, ( float ) scale.getZ(), 0, 0, 0, 0, 1 );
Matrix4f transMat = new Matrix4f( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ( float ) ( location.getX() - displayLocation.getX() ), ( float ) ( location.getY() - displayLocation.getY() ), ( float ) ( location.getZ() - displayLocation.getZ() ), 1 );
disp.display.setInterpolationDelay( 0 );
disp.display.setInterpolationDuration( 2 );
disp.display.setTransformationMatrix( transMat.mul( transformRot ) );
}
}
}, 0, 1 );
}
private void registerCommands() {
new SubCommand( "minie" )
.addSenderValidator( new SenderValidatorPlayer() )
.add( new SubCommand( "spawn" )
.add( new SubCommand( new InputValidatorDouble( 0.01, 100 ) )
.defaultTo( this::spawnBlock ) )
.defaultTo( this::spawnBlock ) )
.add( new SubCommand( "toggle" )
.defaultTo( ( sender, args, params ) -> {
paused = !paused;
} ) )
.add( new SubCommand( "teleport" )
.defaultTo( ( sender, args, params ) -> {
teleportOnDeactivate = !teleportOnDeactivate;
} ) )
.add( new SubCommand( "impulse" )
.add( new SubCommand( new InputValidatorInt() )
.defaultTo( ( sender, args, params ) -> {
Player player = ( Player ) sender;
Location loc = player.getLocation();
impulse( new Vector3f( ( float ) loc.getX(), ( float ) loc.getY(), ( float ) loc.getZ() ), params.getLast( int.class ) );
} ) )
.defaultTo( ( sender, args, params ) -> {
Player player = ( Player ) sender;
Location loc = player.getLocation();
impulse( new Vector3f( ( float ) loc.getX(), ( float ) loc.getY(), ( float ) loc.getZ() ), 15f );
} ) )
.defaultTo( new CommandExecutableMessage( "An argument must be provided" ) )
.whenUnknown( new CommandExecutableMessage( "Unknown argument" ) )
.applyTo( getCommand( "minie" ) );
}
private void impulse( Vector3f location, float power ) {
PhysicsRigidBody rigid = new PhysicsRigidBody( new SphereCollisionShape( 20 ), 1f );
rigid.setPhysicsLocation( location );
space.contactTest( rigid, new PhysicsCollisionListener() {
@Override
public void collision( PhysicsCollisionEvent event ) {
if ( event.getObjectB() instanceof PhysicsRigidBody ) {
PhysicsRigidBody objB = ( PhysicsRigidBody ) event.getObjectB();
Vector3f rLoc = objB.getPhysicsLocation();
Vector3f to = rLoc.subtract( ( float ) location.getX(), ( float ) location.getY(), ( float ) location.getZ() );
float distSq = to.lengthSquared();
if ( distSq != 0 ) {
if ( power / distSq > 1 ) {
objB.applyCentralImpulse( to.normalize().mult( power / distSq ) );
}
}
}
}
} );
}
private void spawnBlock( final CommandSender sender, final String[] args, final CommandParameters params ) {
Player player = ( Player ) sender;
Location loc = player.getLocation();
// Optional scale
double scale = 1;
if ( params.size() > 2 ) {
scale = params.getFirst( double.class );
}
loc.setPitch( 0 );
loc.setDirection( new Vector( 0, 0, 0 ) );
BlockData displayData;
ItemStack item = player.getInventory().getItemInMainHand();
if ( item != null && item.getType() != Material.AIR && item.getType().isBlock() ) {
displayData = item.getType().createBlockData();
} else {
displayData = Material.TNT.createBlockData();
}
BoundingBox[] boxes = NmsUtil.convertFrom( NmsUtil.getShape( displayData, null, BlockShapeType.SHAPE ) );
Vector blockCenter = calculateCenter( boxes );
CollisionShape box;
if ( boxes.length == 0 ) {
player.sendMessage( "No bounding box detected! Wrong method?" );
return;
}
if ( boxes.length == 1 ) {
Vector min = boxes[ 0 ].getMin();
Vector center = boxes[ 0 ].getCenter().subtract( min );
box = new BoxCollisionShape( ( float ) center.getX(), ( float ) center.getY(), ( float ) center.getZ() );
} else {
CompoundCollisionShape compound = new CompoundCollisionShape();
for ( BoundingBox aabb : boxes ) {
Vector min = aabb.getMin();
Vector center = aabb.getCenter();
Vector half = center.clone().subtract( min );
center.subtract( blockCenter );
CollisionShape subShape = new BoxCollisionShape( ( float ) half.getX(), ( float ) half.getY(), ( float ) half.getZ() );
compound.addChildShape( subShape, ( float ) center.getX(), ( float ) center.getY(), ( float ) center.getZ() );
}
box = compound;
}
box.setScale( ( float ) scale );
PhysicsRigidBody rigid = new PhysicsRigidBody( box, 1f );
// Since the center of the rigid body and the box shape are different, we need to offset the location
rigid.setPhysicsLocation( new Vector3f( ( float ) ( loc.getX() + blockCenter.getX() ), ( float ) ( loc.getY() + blockCenter.getY() ), ( float ) ( loc.getZ() + blockCenter.getZ() ) ) );
// Convert the display direction vector to a quaternion
rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) );
rigid.setMass( rigid.getMass() * ( float ) ( scale * scale ) );
space.addCollisionObject( rigid );
// Create the display
BlockDisplay display = loc.getWorld().spawn( loc, BlockDisplay.class, d -> {
d.setBlock( displayData );
d.setViewRange( 1000 );
} );
linkedDisplays.put( rigid, new AuxiliaryDisplayStruct( display, blockCenter.multiply( scale ) ).setScale( new Vector( scale, scale, scale ) ) );
player.sendMessage( "Created display" );
}
private static Vector calculateCenter( BoundingBox[] boxes ) {
Vector center = new Vector( 0, 0, 0 );
// TODO Throw error, probably
if ( boxes.length == 0 ) {
return center;
}
double totalVolume = 0;
for ( BoundingBox box : boxes ) {
Vector mid = box.getCenter();
center.add( mid.multiply( box.getVolume() ) );
totalVolume += box.getVolume();
}
return center.multiply( 1 / totalVolume );
}
}

View File

@@ -1,10 +1,9 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest; package com.aaaaahhhhhhh.bananapuncher714.mesh.physics;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
@@ -20,7 +19,6 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.logging.Level; import java.util.logging.Level;
@@ -37,8 +35,8 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v1_21_R6.CraftWorld; import org.bukkit.craftbukkit.v1_21_R7.CraftWorld;
import org.bukkit.craftbukkit.v1_21_R6.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_21_R7.block.data.CraftBlockData;
import org.bukkit.entity.BlockDisplay; import org.bukkit.entity.BlockDisplay;
import org.bukkit.entity.Display; import org.bukkit.entity.Display;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -57,30 +55,33 @@ import org.bukkit.util.Vector;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.Mesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.Point;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionRuleWinding; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.region.simple.RegionRuleWinding;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.region.simple.RegionSimple;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple.GluWindingRule; import com.aaaaahhhhhhh.bananapuncher714.mesh.algorithm.region.simple.RegionSimple.GluWindingRule;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.CommandParameters; import com.aaaaahhhhhhh.bananapuncher714.mesh.base.Facet;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.SubCommand; import com.aaaaahhhhhhh.bananapuncher714.mesh.base.MeshBuilder;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor.CommandExecutableMessage; import com.aaaaahhhhhhh.bananapuncher714.mesh.base.Plane;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.InputValidatorDouble; import com.aaaaahhhhhhh.bananapuncher714.mesh.base.Vector3d;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.InputValidatorInt; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.CommandParameters;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender.SenderValidatorPlayer; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.SubCommand;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.BlockDataType; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor.CommandExecutableMessage;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidatorDouble;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkMesh; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidatorInt;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.IndexedPolygon; import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender.SenderValidatorPlayer;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.MinecraftPlane; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.BlockDataType;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.MinecraftPlane.PlaneAxis; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.PlaneMesh; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkMesh;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.VectorReference; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.IndexedPolygon;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Facet; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.IndexedTriangle;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.MeshBuilder; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.MinecraftPlane;
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.ChunkMeshUtil; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.PlaneMesh;
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.FileUtil; import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.VectorReference;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.MinecraftPlane.PlaneAxis;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.ChunkMeshUtil;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.FileUtil;
import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.PhysicsSpace.BroadphaseType; import com.jme3.bullet.PhysicsSpace.BroadphaseType;
import com.jme3.bullet.RotationOrder; import com.jme3.bullet.RotationOrder;
@@ -101,7 +102,6 @@ import com.jme3.bullet.joints.motors.MotorParam;
import com.jme3.bullet.objects.PhysicsBody; import com.jme3.bullet.objects.PhysicsBody;
import com.jme3.bullet.objects.PhysicsRigidBody; import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.math.Matrix3f; import com.jme3.math.Matrix3f;
import com.jme3.math.Plane;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
@@ -153,7 +153,7 @@ public class MiniePlugin extends JavaPlugin {
PhysicsRigidBody.logger2.setLevel( Level.WARNING ); PhysicsRigidBody.logger2.setLevel( Level.WARNING );
space = new PhysicsSpace( BroadphaseType.DBVT ); space = new PhysicsSpace( BroadphaseType.DBVT );
PlaneCollisionShape plane = new PlaneCollisionShape( new Plane( new Vector3f( 0, 1, 0 ), 0 ) ); PlaneCollisionShape plane = new PlaneCollisionShape( new com.jme3.math.Plane( new Vector3f( 0, 1, 0 ), 0 ) );
planeBody = new PhysicsRigidBody( plane, PhysicsBody.massForStatic ); planeBody = new PhysicsRigidBody( plane, PhysicsBody.massForStatic );
planeBody.setPhysicsLocation( new Vector3f( 0, 128, 0 ) ); planeBody.setPhysicsLocation( new Vector3f( 0, 128, 0 ) );
// space.addCollisionObject( planeBody ); // space.addCollisionObject( planeBody );
@@ -829,61 +829,61 @@ public class MiniePlugin extends JavaPlugin {
// Check each face // Check each face
if ( y == 0 || types[ index - 256 ] != BlockVoxelType.SOLID ) { if ( y == 0 || types[ index - 256 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z ) ); facet.points.add( new Vector3d( x, y, z ) );
facet.points.add( new Vector( x, y, z + 1 ) ); facet.points.add( new Vector3d( x, y, z + 1 ) );
facet.points.add( new Vector( x + 1, y, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y, z + 1 ) );
facet.points.add( new Vector( x + 1, y, z ) ); facet.points.add( new Vector3d( x + 1, y, z ) );
facet.normal = new Vector( 0, -1, 0 ); facet.normal = new Vector3d( 0, -1, 0 );
facets.add( facet ); facets.add( facet );
} }
if ( y == worldHeight - 1 || types[ index + 256 ] != BlockVoxelType.SOLID ) { if ( y == worldHeight - 1 || types[ index + 256 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y + 1, z ) ); facet.points.add( new Vector3d( x, y + 1, z ) );
facet.points.add( new Vector( x, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z ) ); facet.points.add( new Vector3d( x + 1, y + 1, z ) );
facet.normal = new Vector( 0, 1, 0 ); facet.normal = new Vector3d( 0, 1, 0 );
facets.add( facet ); facets.add( facet );
} }
if ( z == 0 || types[ index - 16 ] != BlockVoxelType.SOLID ) { if ( z == 0 || types[ index - 16 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z ) ); facet.points.add( new Vector3d( x, y, z ) );
facet.points.add( new Vector( x, y + 1, z ) ); facet.points.add( new Vector3d( x, y + 1, z ) );
facet.points.add( new Vector( x + 1, y + 1, z ) ); facet.points.add( new Vector3d( x + 1, y + 1, z ) );
facet.points.add( new Vector( x + 1, y, z ) ); facet.points.add( new Vector3d( x + 1, y, z ) );
facet.normal = new Vector( 0, 0, -1 ); facet.normal = new Vector3d( 0, 0, -1 );
facets.add( facet ); facets.add( facet );
} }
if ( z == 15 || types[ index + 16 ] != BlockVoxelType.SOLID ) { if ( z == 15 || types[ index + 16 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z + 1 ) ); facet.points.add( new Vector3d( x, y, z + 1 ) );
facet.points.add( new Vector( x, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y, z + 1 ) );
facet.normal = new Vector( 0, 0, 1 ); facet.normal = new Vector3d( 0, 0, 1 );
facets.add( facet ); facets.add( facet );
} }
if ( x == 0 || types[ index - 1 ] != BlockVoxelType.SOLID ) { if ( x == 0 || types[ index - 1 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z ) ); facet.points.add( new Vector3d( x, y, z ) );
facet.points.add( new Vector( x, y, z + 1 ) ); facet.points.add( new Vector3d( x, y, z + 1 ) );
facet.points.add( new Vector( x, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x, y + 1, z + 1 ) );
facet.points.add( new Vector( x, y + 1, z ) ); facet.points.add( new Vector3d( x, y + 1, z ) );
facet.normal = new Vector( -1, 0, 0 ); facet.normal = new Vector3d( -1, 0, 0 );
facets.add( facet ); facets.add( facet );
} }
if ( x == 15 || types[ index + 1 ] != BlockVoxelType.SOLID ) { if ( x == 15 || types[ index + 1 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x + 1, y, z ) ); facet.points.add( new Vector3d( x + 1, y, z ) );
facet.points.add( new Vector( x + 1, y, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z ) ); facet.points.add( new Vector3d( x + 1, y + 1, z ) );
facet.normal = new Vector( 1, 0, 0 ); facet.normal = new Vector3d( 1, 0, 0 );
facets.add( facet ); facets.add( facet );
} }
} }
@@ -945,61 +945,61 @@ public class MiniePlugin extends JavaPlugin {
// Check each face // Check each face
if ( y == 0 || types[ index - 256 ] != BlockVoxelType.SOLID ) { if ( y == 0 || types[ index - 256 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z ) ); facet.points.add( new Vector3d( x, y, z ) );
facet.points.add( new Vector( x, y, z + 1 ) ); facet.points.add( new Vector3d( x, y, z + 1 ) );
facet.points.add( new Vector( x + 1, y, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y, z + 1 ) );
facet.points.add( new Vector( x + 1, y, z ) ); facet.points.add( new Vector3d( x + 1, y, z ) );
facet.normal = new Vector( 0, -1, 0 ); facet.normal = new Vector3d( 0, -1, 0 );
facets.add( facet ); facets.add( facet );
} }
if ( y == worldHeight - 1 || types[ index + 256 ] != BlockVoxelType.SOLID ) { if ( y == worldHeight - 1 || types[ index + 256 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y + 1, z ) ); facet.points.add( new Vector3d( x, y + 1, z ) );
facet.points.add( new Vector( x, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z ) ); facet.points.add( new Vector3d( x + 1, y + 1, z ) );
facet.normal = new Vector( 0, 1, 0 ); facet.normal = new Vector3d( 0, 1, 0 );
facets.add( facet ); facets.add( facet );
} }
if ( z == 0 || types[ index - 16 ] != BlockVoxelType.SOLID ) { if ( z == 0 || types[ index - 16 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z ) ); facet.points.add( new Vector3d( x, y, z ) );
facet.points.add( new Vector( x, y + 1, z ) ); facet.points.add( new Vector3d( x, y + 1, z ) );
facet.points.add( new Vector( x + 1, y + 1, z ) ); facet.points.add( new Vector3d( x + 1, y + 1, z ) );
facet.points.add( new Vector( x + 1, y, z ) ); facet.points.add( new Vector3d( x + 1, y, z ) );
facet.normal = new Vector( 0, 0, -1 ); facet.normal = new Vector3d( 0, 0, -1 );
facets.add( facet ); facets.add( facet );
} }
if ( z == 15 || types[ index + 16 ] != BlockVoxelType.SOLID ) { if ( z == 15 || types[ index + 16 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z + 1 ) ); facet.points.add( new Vector3d( x, y, z + 1 ) );
facet.points.add( new Vector( x, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y, z + 1 ) );
facet.normal = new Vector( 0, 0, 1 ); facet.normal = new Vector3d( 0, 0, 1 );
facets.add( facet ); facets.add( facet );
} }
if ( x == 0 || types[ index - 1 ] != BlockVoxelType.SOLID ) { if ( x == 0 || types[ index - 1 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x, y, z ) ); facet.points.add( new Vector3d( x, y, z ) );
facet.points.add( new Vector( x, y, z + 1 ) ); facet.points.add( new Vector3d( x, y, z + 1 ) );
facet.points.add( new Vector( x, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x, y + 1, z + 1 ) );
facet.points.add( new Vector( x, y + 1, z ) ); facet.points.add( new Vector3d( x, y + 1, z ) );
facet.normal = new Vector( -1, 0, 0 ); facet.normal = new Vector3d( -1, 0, 0 );
facets.add( facet ); facets.add( facet );
} }
if ( x == 15 || types[ index + 1 ] != BlockVoxelType.SOLID ) { if ( x == 15 || types[ index + 1 ] != BlockVoxelType.SOLID ) {
Facet facet = new Facet(); Facet facet = new Facet();
facet.points.add( new Vector( x + 1, y, z ) ); facet.points.add( new Vector3d( x + 1, y, z ) );
facet.points.add( new Vector( x + 1, y, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z + 1 ) ); facet.points.add( new Vector3d( x + 1, y + 1, z + 1 ) );
facet.points.add( new Vector( x + 1, y + 1, z ) ); facet.points.add( new Vector3d( x + 1, y + 1, z ) );
facet.normal = new Vector( 1, 0, 0 ); facet.normal = new Vector3d( 1, 0, 0 );
facets.add( facet ); facets.add( facet );
} }
} }
@@ -1046,12 +1046,12 @@ public class MiniePlugin extends JavaPlugin {
} }
final Triangle triangle = new Triangle(); final Triangle triangle = new Triangle();
for ( final Vector vec : facet.points ) { for ( final Vector3d vec : facet.points ) {
VectorRef ref = null; VectorRef ref = null;
for ( final Entry< Vector, VectorRef > entry : vertices.entrySet() ) { for ( final Entry< Vector, VectorRef > entry : vertices.entrySet() ) {
final Vector existingVec = entry.getKey(); final Vector existingVec = entry.getKey();
if ( existingVec.distanceSquared( vec ) < 1e-8 ) { if ( existingVec.distanceSquared( new Vector( vec.getX(), vec.getY(), vec.getZ() ) ) < 1e-8 ) {
ref = entry.getValue(); ref = entry.getValue();
break; break;
} }
@@ -1059,7 +1059,7 @@ public class MiniePlugin extends JavaPlugin {
if ( ref == null ) { if ( ref == null ) {
ref = new VectorRef(); ref = new VectorRef();
vertices.put( vec, ref ); vertices.put( new Vector( vec.getX(), vec.getY(), vec.getZ() ), ref );
} }
triangle.refs.add( ref ); triangle.refs.add( ref );
@@ -1314,9 +1314,9 @@ public class MiniePlugin extends JavaPlugin {
// Ignore any planes that are empty // Ignore any planes that are empty
if ( !tris.isEmpty() ) { if ( !tris.isEmpty() ) {
final PlaneMesh newMesh = new PlaneMesh(); final PlaneMesh newMesh = new PlaneMesh();
newMesh.completedPolygons = new ArrayList< IndexedPolygon >(); newMesh.completedPolygons = new ArrayList< IndexedTriangle >();
for ( final Polygon tri : tris ) { for ( final Polygon tri : tris ) {
final IndexedPolygon newPoly = new IndexedPolygon(); final IndexedTriangle newPoly = new IndexedTriangle();
for ( final Point point : tri.getPoints() ) { for ( final Point point : tri.getPoints() ) {
final Vector vert = plane.convert( point ); final Vector vert = plane.convert( point );
@@ -1343,7 +1343,7 @@ public class MiniePlugin extends JavaPlugin {
++ref.referenceCount; ++ref.referenceCount;
} }
newPoly.points.add( ref ); // newPoly.points.add( ref );
} }
newMesh.completedPolygons.add( newPoly ); newMesh.completedPolygons.add( newPoly );
} }
@@ -1537,7 +1537,7 @@ public class MiniePlugin extends JavaPlugin {
if ( planeMesh != null ) { if ( planeMesh != null ) {
// Reset all indexed polygons(triangles) for this plane // Reset all indexed polygons(triangles) for this plane
for ( final IndexedPolygon poly : planeMesh.completedPolygons ) { for ( final IndexedPolygon poly : planeMesh.completedPolygons ) {
poly.points.parallelStream().forEach( p -> --p.referenceCount ); // poly.points.parallelStream().forEach( p -> --p.referenceCount );
} }
// Add all polygons that were previously generated // Add all polygons that were previously generated
@@ -1564,9 +1564,9 @@ public class MiniePlugin extends JavaPlugin {
// Ignore any planes that are empty // Ignore any planes that are empty
if ( !tris.isEmpty() ) { if ( !tris.isEmpty() ) {
final PlaneMesh newMesh = new PlaneMesh(); final PlaneMesh newMesh = new PlaneMesh();
newMesh.completedPolygons = new ArrayList< IndexedPolygon >(); newMesh.completedPolygons = new ArrayList< IndexedTriangle >();
for ( final Polygon tri : tris ) { for ( final Polygon tri : tris ) {
final IndexedPolygon newPoly = new IndexedPolygon(); final IndexedTriangle newPoly = new IndexedTriangle();
for ( final Point point : tri.getPoints() ) { for ( final Point point : tri.getPoints() ) {
final Vector vert = plane.convert( point ); final Vector vert = plane.convert( point );
@@ -1592,7 +1592,7 @@ public class MiniePlugin extends JavaPlugin {
++ref.referenceCount; ++ref.referenceCount;
} }
newPoly.points.add( ref ); // newPoly.points.add( ref );
} }
newMesh.completedPolygons.add( newPoly ); newMesh.completedPolygons.add( newPoly );
} }
@@ -1668,12 +1668,12 @@ public class MiniePlugin extends JavaPlugin {
} }
final Triangle triangle = new Triangle(); final Triangle triangle = new Triangle();
for ( final Vector vec : facet.points ) { for ( final Vector3d vec : facet.points ) {
VectorRef ref = null; VectorRef ref = null;
for ( final Entry< Vector, VectorRef > entry : vertices.entrySet() ) { for ( final Entry< Vector, VectorRef > entry : vertices.entrySet() ) {
final Vector existingVec = entry.getKey(); final Vector existingVec = entry.getKey();
if ( existingVec.distanceSquared( vec ) < 1e-8 ) { if ( existingVec.distanceSquared( new Vector( vec.getX(), vec.getY(), vec.getZ() ) ) < 1e-8 ) {
ref = entry.getValue(); ref = entry.getValue();
break; break;
} }
@@ -1681,7 +1681,7 @@ public class MiniePlugin extends JavaPlugin {
if ( ref == null ) { if ( ref == null ) {
ref = new VectorRef(); ref = new VectorRef();
vertices.put( vec, ref ); vertices.put( new Vector( vec.getX(), vec.getY(), vec.getZ() ), ref );
} }
triangle.refs.add( ref ); triangle.refs.add( ref );
@@ -1766,10 +1766,10 @@ public class MiniePlugin extends JavaPlugin {
try ( FileWriter writer = new FileWriter( file ) ) { try ( FileWriter writer = new FileWriter( file ) ) {
for ( final Facet facet : facets ) { for ( final Facet facet : facets ) {
final Vector normal = facet.normal; final Vector3d normal = facet.normal;
writer.write( facet.points.size() + " " + normal.getX() + " " + normal.getY() + " " + normal.getZ() + "\n" ); writer.write( facet.points.size() + " " + normal.getX() + " " + normal.getY() + " " + normal.getZ() + "\n" );
for ( final Vector point : facet.points ) { for ( final Vector3d point : facet.points ) {
writer.write( point.getX() + " " + point.getY() + " " + point.getZ() + "\n" ); writer.write( point.getX() + " " + point.getY() + " " + point.getZ() + "\n" );
} }
} }
@@ -1850,7 +1850,7 @@ public class MiniePlugin extends JavaPlugin {
return true; return true;
} }
private static Collection< Polygon > process( final com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane plane ) { private static Collection< Polygon > process( final Plane plane ) {
final Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } ); final Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : plane.polygons ) { for ( Polygon poly : plane.polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE ); mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
@@ -1914,14 +1914,14 @@ public class MiniePlugin extends JavaPlugin {
private static List< Facet > generateFacetsFor( BoundingBox box ) { private static List< Facet > generateFacetsFor( BoundingBox box ) {
List< Facet > facets = new ArrayList< Facet >(); List< Facet > facets = new ArrayList< Facet >();
Vector p1 = new Vector( box.getMinX(), box.getMinY(), box.getMinZ() ); Vector3d p1 = new Vector3d( box.getMinX(), box.getMinY(), box.getMinZ() );
Vector p2 = new Vector( box.getMinX(), box.getMinY(), box.getMaxZ() ); Vector3d p2 = new Vector3d( box.getMinX(), box.getMinY(), box.getMaxZ() );
Vector p3 = new Vector( box.getMinX(), box.getMaxY(), box.getMinZ() ); Vector3d p3 = new Vector3d( box.getMinX(), box.getMaxY(), box.getMinZ() );
Vector p4 = new Vector( box.getMinX(), box.getMaxY(), box.getMaxZ() ); Vector3d p4 = new Vector3d( box.getMinX(), box.getMaxY(), box.getMaxZ() );
Vector p5 = new Vector( box.getMaxX(), box.getMinY(), box.getMinZ() ); Vector3d p5 = new Vector3d( box.getMaxX(), box.getMinY(), box.getMinZ() );
Vector p6 = new Vector( box.getMaxX(), box.getMinY(), box.getMaxZ() ); Vector3d p6 = new Vector3d( box.getMaxX(), box.getMinY(), box.getMaxZ() );
Vector p7 = new Vector( box.getMaxX(), box.getMaxY(), box.getMinZ() ); Vector3d p7 = new Vector3d( box.getMaxX(), box.getMaxY(), box.getMinZ() );
Vector p8 = new Vector( box.getMaxX(), box.getMaxY(), box.getMaxZ() ); Vector3d p8 = new Vector3d( box.getMaxX(), box.getMaxY(), box.getMaxZ() );
{ {
Facet facet = new Facet(); Facet facet = new Facet();
@@ -1929,7 +1929,7 @@ public class MiniePlugin extends JavaPlugin {
facet.points.add( p2 ); facet.points.add( p2 );
facet.points.add( p4 ); facet.points.add( p4 );
facet.points.add( p3 ); facet.points.add( p3 );
facet.normal = new Vector( -1, 0, 0 ); facet.normal = new Vector3d( -1, 0, 0 );
facets.add( facet ); facets.add( facet );
} }
@@ -1939,7 +1939,7 @@ public class MiniePlugin extends JavaPlugin {
facet.points.add( p6 ); facet.points.add( p6 );
facet.points.add( p8 ); facet.points.add( p8 );
facet.points.add( p7 ); facet.points.add( p7 );
facet.normal = new Vector( 1, 0, 0 ); facet.normal = new Vector3d( 1, 0, 0 );
facets.add( facet ); facets.add( facet );
} }
@@ -1949,7 +1949,7 @@ public class MiniePlugin extends JavaPlugin {
facet.points.add( p2 ); facet.points.add( p2 );
facet.points.add( p6 ); facet.points.add( p6 );
facet.points.add( p5 ); facet.points.add( p5 );
facet.normal = new Vector( 0, -1, 0 ); facet.normal = new Vector3d( 0, -1, 0 );
facets.add( facet ); facets.add( facet );
} }
@@ -1959,7 +1959,7 @@ public class MiniePlugin extends JavaPlugin {
facet.points.add( p4 ); facet.points.add( p4 );
facet.points.add( p8 ); facet.points.add( p8 );
facet.points.add( p7 ); facet.points.add( p7 );
facet.normal = new Vector( 0, 1, 0 ); facet.normal = new Vector3d( 0, 1, 0 );
facets.add( facet ); facets.add( facet );
} }
@@ -1969,7 +1969,7 @@ public class MiniePlugin extends JavaPlugin {
facet.points.add( p3 ); facet.points.add( p3 );
facet.points.add( p7 ); facet.points.add( p7 );
facet.points.add( p5 ); facet.points.add( p5 );
facet.normal = new Vector( 0, 0, -1 ); facet.normal = new Vector3d( 0, 0, -1 );
facets.add( facet ); facets.add( facet );
} }
@@ -1979,7 +1979,7 @@ public class MiniePlugin extends JavaPlugin {
facet.points.add( p4 ); facet.points.add( p4 );
facet.points.add( p8 ); facet.points.add( p8 );
facet.points.add( p6 ); facet.points.add( p6 );
facet.normal = new Vector( 0, 0, 1 ); facet.normal = new Vector3d( 0, 0, 1 );
facets.add( facet ); facets.add( facet );
} }

View File

@@ -0,0 +1,16 @@
name: MC-Mesh-Physics
main: com.aaaaahhhhhhh.bananapuncher714.mesh.physics.McMeshPhysicsPlugin
version: 0.0.1
description: BulletJME and MC-Mesh integration
author: BananaPuncher714
api-version: 1.13
depend: [ "Mc-Mesh-Environment" ]
load: STARTUP
#libraries:
#- com.github.stephengold:Minie:7.5.0
commands:
minie:
description: Main Minie command
aliases: []
permission: minie

View File

@@ -12,6 +12,7 @@
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>
<!-- <module>environment</module> --> <module>environment</module>
<module>physics</module>
</modules> </modules>
</project> </project>