Partial refactor
This commit is contained in:
3
plugin/environment/README.md
Normal file
3
plugin/environment/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# MC-Mesh Environment Plugin
|
||||
This plugin aims to provide a comprehensive physics enabled environment
|
||||
in Minecraft using BulletJME and the MC-Mesh core algorithm.
|
||||
253
plugin/environment/dependency-reduced-pom.xml
Normal file
253
plugin/environment/dependency-reduced-pom.xml
Normal file
@@ -0,0 +1,253 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>mc-mesh-master</artifactId>
|
||||
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>mc-mesh-plugin</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.14.1</version>
|
||||
<configuration>
|
||||
<release>21</release>
|
||||
</configuration>
|
||||
</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>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.21.10-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jline</artifactId>
|
||||
<groupId>org.jline</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>log4j-iostreams</artifactId>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>asm-commons</artifactId>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<groupId>com.github.stephenc.jcip</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>msal4j</artifactId>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>authlib</artifactId>
|
||||
<groupId>com.mojang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>brigadier</artifactId>
|
||||
<groupId>com.mojang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>datafixerupper</artifactId>
|
||||
<groupId>com.mojang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jtracy</artifactId>
|
||||
<groupId>com.mojang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>com.mojang</groupId>
|
||||
</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>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<groupId>commons-io</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-codec</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-codec-http</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-common</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-resolver</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-transport-classes-epoll</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-transport-native-unix-common</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>fastutil</artifactId>
|
||||
<groupId>it.unimi.dsi</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jna</artifactId>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>accessors-smart</artifactId>
|
||||
<groupId>net.minidev</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>json-smart</artifactId>
|
||||
<groupId>net.minidev</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jopt-simple</artifactId>
|
||||
<groupId>net.sf.jopt-simple</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>log4j-slf4j2-impl</artifactId>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>lz4-java</artifactId>
|
||||
<groupId>org.lz4</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<groupId>commons-lang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<groupId>org.xerial</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<groupId>com.mysql</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>maven-resolver-provider</artifactId>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>maven-resolver-connector-basic</artifactId>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>maven-resolver-transport-http</artifactId>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
84
plugin/environment/pom.xml
Normal file
84
plugin/environment/pom.xml
Normal file
@@ -0,0 +1,84 @@
|
||||
<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-environment</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.21.10-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.stephengold</groupId>
|
||||
<artifactId>Minie</artifactId>
|
||||
<version>9.0.3+mt</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scijava</groupId>
|
||||
<artifactId>native-lib-loader</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
|
||||
<artifactId>mc-mesh-core-algorithm</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
|
||||
<artifactId>mc-mesh-core-base</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.14.1</version>
|
||||
<configuration>
|
||||
<release>21</release>
|
||||
</configuration>
|
||||
</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>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.permissions.Permission;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.BukkitUtil;
|
||||
|
||||
public class CommandBase {
|
||||
protected PluginCommand command;
|
||||
|
||||
public CommandBase( String command ) {
|
||||
this.command = BukkitUtil.constructCommand( command );
|
||||
}
|
||||
|
||||
public CommandBase setPermission( String permission ) {
|
||||
command.setPermission( permission );
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBase setDescription( String description ) {
|
||||
command.setDescription( description );
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBase addAliases( String... aliases ) {
|
||||
Set< String > aliasSet = new HashSet< String >( command.getAliases() );
|
||||
for ( String alias : aliases ) {
|
||||
aliasSet.add( alias );
|
||||
}
|
||||
command.setAliases( new ArrayList< String >( aliasSet ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBase addAliases( Collection< String > aliases ) {
|
||||
Set< String > aliasSet = new HashSet< String >( command.getAliases() );
|
||||
aliasSet.addAll( aliases );
|
||||
command.setAliases( new ArrayList< String >( aliasSet ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBase setPermission( Permission permission ) {
|
||||
return setPermission( permission.toString() );
|
||||
}
|
||||
|
||||
public CommandBase setSubCommand( SubCommand subCommand ) {
|
||||
subCommand.applyTo( command );
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginCommand build() {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor.CommandExecutable;
|
||||
|
||||
public class CommandOption {
|
||||
protected CommandExecutable exe;
|
||||
protected String[] args;
|
||||
protected CommandParameters parameter;
|
||||
|
||||
public CommandOption( CommandExecutable exe, String[] args, CommandParameters parameter ) {
|
||||
this.exe = exe;
|
||||
this.args = args;
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
public int getArgumentSize() {
|
||||
return args.length;
|
||||
}
|
||||
|
||||
public void execute( CommandSender sender ) {
|
||||
exe.execute( sender, args, parameter );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.primitives.Primitives;
|
||||
|
||||
public class CommandParameters {
|
||||
protected List< Object > parameters = new ArrayList< Object >();
|
||||
|
||||
public CommandParameters() {
|
||||
}
|
||||
|
||||
public CommandParameters( CommandParameters copy ) {
|
||||
parameters.addAll( copy.parameters );
|
||||
}
|
||||
|
||||
public void add( Object object ) {
|
||||
parameters.add( object );
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
public < T > T get( Class < T > clazz, int index ) {
|
||||
clazz = Primitives.wrap( clazz );
|
||||
if ( index < 0 || index >= parameters.size() ) {
|
||||
return null;
|
||||
}
|
||||
Object obj = parameters.get( index );
|
||||
if ( obj != null && clazz.isInstance( obj ) ) {
|
||||
return clazz.cast( obj );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public < T > T getLast( Class< T > clazz ) {
|
||||
clazz = Primitives.wrap( clazz );
|
||||
for ( int i = parameters.size() - 1; i >= 0; i-- ) {
|
||||
Object obj = parameters.get( i );
|
||||
if ( obj != null && clazz.isInstance( obj ) ) {
|
||||
return clazz.cast( obj );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public < T > T getFirst( Class< T > clazz ) {
|
||||
clazz = Primitives.wrap( clazz );
|
||||
for ( int i = 0; i < parameters.size(); i++ ) {
|
||||
Object obj = parameters.get( i );
|
||||
if ( obj != null && clazz.isInstance( obj ) ) {
|
||||
return clazz.cast( obj );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CommandParameters[" + parameters.stream().map( Object::toString ).collect( Collectors.joining( ", " ) ) + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandResult {
|
||||
protected List< CommandOption > options = new ArrayList< CommandOption >();
|
||||
|
||||
public void add( CommandOption option ) {
|
||||
options.add( option );
|
||||
}
|
||||
|
||||
public void addAll( Collection< CommandOption > options ) {
|
||||
this.options.addAll( options );
|
||||
}
|
||||
|
||||
public void add( CommandResult result ) {
|
||||
this.options.addAll( result.getOptions() );
|
||||
}
|
||||
|
||||
public List< CommandOption > getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void execute( CommandSender sender ) {
|
||||
CommandOption lowest = null;
|
||||
for ( CommandOption option : options ) {
|
||||
if ( lowest == null || option.getArgumentSize() < lowest.getArgumentSize() ) {
|
||||
lowest = option;
|
||||
}
|
||||
}
|
||||
if ( lowest != null ) {
|
||||
lowest.execute( sender );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;
|
||||
|
||||
public class SplitCommand {
|
||||
protected String[] input;
|
||||
protected String[] arguments;
|
||||
|
||||
public SplitCommand( String[] input, String[] arguments ) {
|
||||
this.input = input;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public String[] getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public void setInput( String[] input ) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public String[] getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public void setArguments( String[] arguments ) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.util.StringUtil;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor.CommandExecutable;
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.InputValidator;
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.InputValidatorString;
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender.SenderValidator;
|
||||
|
||||
/**
|
||||
* A build and run command framework for automatic tab completions and easy branching.
|
||||
*
|
||||
* @author BananaPuncher714
|
||||
*/
|
||||
public class SubCommand {
|
||||
protected List< SubCommand > subCommands = new ArrayList< SubCommand >();
|
||||
|
||||
protected InputValidator< ? > validator;
|
||||
protected Set< SenderValidator > senderValidators = new HashSet< SenderValidator >();
|
||||
protected CommandExecutable whenUnknown;
|
||||
protected CommandExecutable whenNone;
|
||||
|
||||
/**
|
||||
* Accept anything as a valid input
|
||||
*/
|
||||
public SubCommand() {
|
||||
}
|
||||
|
||||
// Helped constructor, really belongs in a factory.
|
||||
/**
|
||||
* Create a SubCommand with the string as the input validator.
|
||||
*
|
||||
* @param command
|
||||
* The subcommand value.
|
||||
*/
|
||||
public SubCommand( String command ) {
|
||||
this( new InputValidatorString( command ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SubCommand with the input validator provided.
|
||||
*
|
||||
* @param validator
|
||||
* Can be null.
|
||||
*/
|
||||
public SubCommand( InputValidator< ? > validator ) {
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
public SubCommand add( SubCommand builder ) {
|
||||
subCommands.add( builder );
|
||||
return this;
|
||||
}
|
||||
|
||||
public SubCommand addSenderValidator( SenderValidator validator ) {
|
||||
senderValidators.add( validator );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ran when the arguments provided don't match any SubCommands registered.
|
||||
*
|
||||
* @param executable
|
||||
* An executable where the arguments will start with the unknown subcommand.
|
||||
* @return
|
||||
* Builder pattern return.
|
||||
*/
|
||||
public SubCommand whenUnknown( CommandExecutable executable ) {
|
||||
this.whenUnknown = executable;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Naming by jetp250
|
||||
/**
|
||||
* Ran when there are no arguments provided, or if the executable for when unknown is not set.
|
||||
*
|
||||
* @param executable
|
||||
* If null, nothing will happen.
|
||||
* @return
|
||||
* Builder pattern return.
|
||||
*/
|
||||
public SubCommand defaultTo( CommandExecutable executable ) {
|
||||
this.whenNone = executable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean matches( CommandSender sender ) {
|
||||
for ( SenderValidator validator : senderValidators ) {
|
||||
if ( !validator.isValid( sender ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean matches( CommandSender sender, String input[], String[] args ) {
|
||||
return ( validator == null ? true : validator.isValid( sender, input, args ) ) && matches( sender );
|
||||
}
|
||||
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
return validator == null ? null : validator.getTabCompletes( sender, input );
|
||||
}
|
||||
|
||||
public List< SubCommand > getSubCommands() {
|
||||
return subCommands;
|
||||
}
|
||||
|
||||
public InputValidator< ? > getInputValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
public Set< SenderValidator > getSenderValidators() {
|
||||
return senderValidators;
|
||||
}
|
||||
|
||||
public CommandResult submit( CommandSender sender, String[] command, String[] args, CommandParameters parameter ) {
|
||||
CommandResult result = new CommandResult();
|
||||
parameter = new CommandParameters( parameter );
|
||||
if ( validator != null ) {
|
||||
parameter.add( validator.get( sender, command ) );
|
||||
} else {
|
||||
parameter.add( null );
|
||||
}
|
||||
if ( args.length > 0 ) {
|
||||
boolean found = false;
|
||||
for ( SubCommand subCommand : subCommands ) {
|
||||
SplitCommand split = split( args, subCommand.getInputValidator().getArgumentCount() );
|
||||
String[] input = split.getInput();
|
||||
String[] newArgs = split.getArguments();
|
||||
if ( subCommand.matches( sender, input, newArgs ) ) {
|
||||
found = true;
|
||||
|
||||
result.add( subCommand.submit( sender, input, newArgs, parameter ) );
|
||||
}
|
||||
}
|
||||
if ( !found ) {
|
||||
if ( whenUnknown != null ) {
|
||||
result.add( new CommandOption( whenUnknown, args, parameter ) );
|
||||
} else if ( whenNone != null ) {
|
||||
result.add( new CommandOption( whenNone, args, parameter ) );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( whenNone != null ) {
|
||||
result.add( new CommandOption( whenNone, args, parameter ) );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection< String > getTabCompletions( CommandSender sender, String[] args ) {
|
||||
Set< String > tabs = new HashSet< String >();
|
||||
if ( args.length > 0 ) {
|
||||
for ( SubCommand subCommand : subCommands ) {
|
||||
if ( subCommand.matches( sender ) ) {
|
||||
SplitCommand split = split( args, subCommand.getInputValidator().getArgumentCount() );
|
||||
String[] input = split.getInput();
|
||||
String[] newArgs = split.getArguments();
|
||||
// Check if the subcommand matches the argument, and if it has subcommands of its own
|
||||
if ( subCommand.matches( sender, input, newArgs ) && !subCommand.getSubCommands().isEmpty() ) {
|
||||
tabs.addAll( subCommand.getTabCompletions( sender, newArgs ) );
|
||||
} else if ( newArgs.length == 0 ) {
|
||||
// If not, and this is the last argument, add all possible tab completes
|
||||
// This allows for "recommendations"
|
||||
Collection< String > completions = subCommand.getTabCompletes( sender, input );
|
||||
if ( completions != null ) {
|
||||
tabs.addAll( completions );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
public SubCommand applyTo( PluginCommand command ) {
|
||||
command.setExecutor( this::onCommand );
|
||||
command.setTabCompleter( this::onTabComplete );
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean onCommand( CommandSender sender, Command command, String arg2, String[] args ) {
|
||||
CommandParameters parameters = new CommandParameters();
|
||||
if ( matches( sender ) ) {
|
||||
String[] commandArr = new String[ args.length + 1 ];
|
||||
|
||||
commandArr[ 0 ] = command.getName();
|
||||
for ( int i = 1; i < commandArr.length; i++ ) {
|
||||
commandArr[ i ] = args[ i - 1 ];
|
||||
}
|
||||
|
||||
SplitCommand split = split( commandArr, validator.getArgumentCount() );
|
||||
submit( sender, split.getInput(), split.getArguments(), parameters ).execute( sender );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List< String > onTabComplete( CommandSender sender, Command command, String arg2, String[] args ) {
|
||||
List< String > completions = new ArrayList< String >();
|
||||
String[] commandArr = new String[ args.length + 1 ];
|
||||
|
||||
commandArr[ 0 ] = command.getName();
|
||||
for ( int i = 1; i < commandArr.length; i++ ) {
|
||||
commandArr[ i ] = args[ i - 1 ];
|
||||
}
|
||||
|
||||
SplitCommand split = split( commandArr, validator.getArgumentCount() );
|
||||
StringUtil.copyPartialMatches( args[ args.length - 1 ], getTabCompletions( sender, split.getArguments() ), completions );
|
||||
Collections.sort( completions );
|
||||
return completions;
|
||||
}
|
||||
|
||||
protected static SplitCommand split( String[] command, int inputSize ) {
|
||||
String[] input = command.length > 0 ? Arrays.copyOfRange( command, 0, Math.min( inputSize, command.length ) ) : new String[ 0 ];
|
||||
String[] args = command.length > inputSize ? Arrays.copyOfRange( command, inputSize, command.length ) : new String[ 0 ];
|
||||
|
||||
return new SplitCommand( input, args );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.CommandParameters;
|
||||
|
||||
public interface CommandExecutable {
|
||||
void execute( CommandSender sender, String[] args, CommandParameters params );
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.CommandParameters;
|
||||
|
||||
public class CommandExecutableMessage implements CommandExecutable {
|
||||
protected String message;
|
||||
|
||||
public CommandExecutableMessage( String message ) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute( CommandSender sender, String[] args, CommandParameters params ) {
|
||||
sender.sendMessage( message );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author BananaPuncher714
|
||||
*
|
||||
*/
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor;
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Classes for building complex command trees.
|
||||
*
|
||||
* @author BananaPuncher714
|
||||
*/
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public interface InputValidator< T > {
|
||||
Collection< String > getTabCompletes( CommandSender sender, String[] input );
|
||||
boolean isValid( CommandSender sender, String[] input, String[] args );
|
||||
T get( CommandSender sender, String[] input );
|
||||
default int getArgumentCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class InputValidatorArguments implements InputValidator< Void > {
|
||||
protected int min;
|
||||
protected int max;
|
||||
|
||||
public InputValidatorArguments( int amount ) {
|
||||
this.min = amount;
|
||||
this.max = amount;
|
||||
}
|
||||
|
||||
public InputValidatorArguments( int min, int max ) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String input[], String[] args ) {
|
||||
int len = args.length;
|
||||
return len >= min && len <= max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get( CommandSender sender, String input[] ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class InputValidatorBoolean implements InputValidator< Boolean > {
|
||||
protected Set< String > trueVals = new HashSet< String >();
|
||||
protected Set< String > falseVals = new HashSet< String >();
|
||||
|
||||
public InputValidatorBoolean( String[] trueVal, String[] falseVal ) {
|
||||
for ( String str : trueVal ) {
|
||||
trueVals.add( str.toLowerCase() );
|
||||
}
|
||||
|
||||
for ( String str : falseVal ) {
|
||||
falseVals.add( str.toLowerCase() );
|
||||
}
|
||||
}
|
||||
|
||||
public InputValidatorBoolean() {
|
||||
trueVals.add( "true" );
|
||||
falseVals.add( "false" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
Set< String > combined = new HashSet< String >( trueVals );
|
||||
combined.addAll( falseVals );
|
||||
return combined;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String input[], String[] args ) {
|
||||
String lowercase = input[ 0 ].toLowerCase();
|
||||
return trueVals.contains( lowercase ) || falseVals.contains( lowercase );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean get( CommandSender sender, String input[] ) {
|
||||
String lowercase = input[ 0 ].toLowerCase();
|
||||
return trueVals.contains( lowercase );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class InputValidatorChain< T > implements InputValidator< T > {
|
||||
protected InputValidator< T > primaryValidator;
|
||||
protected List< InputValidator< ? > > validators = new ArrayList< InputValidator< ? > >();
|
||||
|
||||
public InputValidatorChain( InputValidator< T > primaryValidator ) {
|
||||
this.primaryValidator = primaryValidator;
|
||||
}
|
||||
|
||||
public InputValidatorChain< T > addValidator( InputValidator< ? > validator ) {
|
||||
validators.add( validator );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
return primaryValidator.getTabCompletes( sender, input );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String input[], String[] args ) {
|
||||
if ( !primaryValidator.isValid( sender, input, args ) ) {
|
||||
return false;
|
||||
}
|
||||
for ( InputValidator< ? > validator : validators ) {
|
||||
if ( !validator.isValid( sender, input, args ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get( CommandSender sender, String input[] ) {
|
||||
return primaryValidator.get( sender, input );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class InputValidatorDouble implements InputValidator< Double > {
|
||||
protected double min = Integer.MIN_VALUE;
|
||||
protected double max = Integer.MAX_VALUE;
|
||||
|
||||
public InputValidatorDouble() {
|
||||
}
|
||||
|
||||
public InputValidatorDouble( double min, double max ) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String[] input, String[] args ) {
|
||||
try {
|
||||
double i = Double.valueOf( input[ 0 ] );
|
||||
return i >= min && i <= max;
|
||||
} catch ( Exception exception ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double get( CommandSender sender, String[] input ) {
|
||||
return Double.parseDouble( input[ 0 ] );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class InputValidatorInt implements InputValidator< Integer > {
|
||||
protected int min = Integer.MIN_VALUE;
|
||||
protected int max = Integer.MAX_VALUE;
|
||||
|
||||
public InputValidatorInt() {
|
||||
}
|
||||
|
||||
public InputValidatorInt( int min, int max ) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String input[], String[] args ) {
|
||||
try {
|
||||
int i = Integer.valueOf( input[ 0 ] );
|
||||
return i >= min && i <= max;
|
||||
} catch ( Exception exception ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get( CommandSender sender, String input[] ) {
|
||||
return Integer.parseInt( input[ 0 ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class InputValidatorPattern implements InputValidator< String > {
|
||||
protected String pattern;
|
||||
|
||||
public InputValidatorPattern( String pattern ) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String input[], String[] args ) {
|
||||
return input[ 0 ].matches( pattern );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get( CommandSender sender, String input[] ) {
|
||||
return input[ 0 ];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class InputValidatorPlayer implements InputValidator< Player > {
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
Set< String > playerNames = new HashSet< String >();
|
||||
for ( Player player : Bukkit.getOnlinePlayers() ) {
|
||||
playerNames.add( player.getName() );
|
||||
}
|
||||
return playerNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String input[], String[] args ) {
|
||||
return Bukkit.getPlayerExact( input[ 0 ] ) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player get( CommandSender sender, String input[] ) {
|
||||
return Bukkit.getPlayerExact( input[ 0 ] );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class InputValidatorString implements InputValidator< String > {
|
||||
protected Set< String > values = new HashSet< String >();
|
||||
|
||||
public InputValidatorString( String value ) {
|
||||
values.add( value.toLowerCase() );
|
||||
}
|
||||
|
||||
public InputValidatorString( String... values ) {
|
||||
Validate.isTrue( values.length > 0, "Must provide at least 1 argument!" );
|
||||
for ( String str : values ) {
|
||||
this.values.add( str.toLowerCase() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection< String > getTabCompletes( CommandSender sender, String[] input ) {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender, String input[], String[] args ) {
|
||||
return values.contains( input[ 0 ].toLowerCase() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get( CommandSender sender, String input[] ) {
|
||||
return input[ 0 ];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author BananaPuncher714
|
||||
*
|
||||
*/
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public interface SenderValidator {
|
||||
boolean isValid( CommandSender sender );
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SenderValidatorNotPlayer implements SenderValidator {
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender ) {
|
||||
return !( sender instanceof Player );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class SenderValidatorPermission implements SenderValidator {
|
||||
protected Set< String > permissions = new HashSet< String >();
|
||||
|
||||
public SenderValidatorPermission( String... permissions ) {
|
||||
for ( String permission : permissions ) {
|
||||
this.permissions.add( permission );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender ) {
|
||||
for ( String permission : permissions ) {
|
||||
if ( sender.hasPermission( permission ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SenderValidatorPlayer implements SenderValidator {
|
||||
@Override
|
||||
public boolean isValid( CommandSender sender ) {
|
||||
return sender instanceof Player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author BananaPuncher714
|
||||
*
|
||||
*/
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender;
|
||||
@@ -0,0 +1,34 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Big/little endian binary writer
|
||||
*/
|
||||
public class BinaryWriter {
|
||||
protected final ByteArrayOutputStream buffer;
|
||||
|
||||
public BinaryWriter() {
|
||||
buffer = new ByteArrayOutputStream();
|
||||
}
|
||||
|
||||
public BinaryWriter( final int startSize ) {
|
||||
buffer = new ByteArrayOutputStream( startSize );
|
||||
}
|
||||
|
||||
public void write( final long val, final int length ) {
|
||||
for ( int i = length - 1; i >= 0; i-- ) {
|
||||
write( ( byte ) ( ( val >> ( i << 3 ) ) & 0xFFL ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void write( final int val ) {
|
||||
write( val, 4 );
|
||||
}
|
||||
|
||||
public void write( final short val ) {
|
||||
write( val, 2 );
|
||||
}
|
||||
|
||||
public void write( final double val ) {
|
||||
final byte[] bytes = new byte[ 8 ];
|
||||
ByteBuffer.wrap( bytes ).putDouble( val );
|
||||
write( bytes );
|
||||
}
|
||||
|
||||
public void writeLittle( final long val, final int length ) {
|
||||
for ( int i = 0; i < length; i++ ) {
|
||||
write( ( byte ) ( ( val >> ( i << 3 ) ) & 0xFFL ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void write( final long[] a, final int length ) {
|
||||
for ( long l : a ) {
|
||||
write( l, length );
|
||||
}
|
||||
}
|
||||
|
||||
public void write( final byte b ) {
|
||||
buffer.write( b );
|
||||
}
|
||||
|
||||
public void write( String str, final int length ) {
|
||||
final byte[] bytes = str.getBytes();
|
||||
final byte[] res = new byte[ length ];
|
||||
for ( int i = 0; i < bytes.length && i < length; ++i ) {
|
||||
res[ i ] = bytes[ i ];
|
||||
}
|
||||
|
||||
write( res );
|
||||
}
|
||||
|
||||
public void write( final byte[] a ) {
|
||||
buffer.write( a, 0, a.length );
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginLoader;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.SimplePluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.McMeshEnvironment;
|
||||
|
||||
public class BukkitUtil {
|
||||
private static Constructor< PluginCommand > PLUGINCOMMAND_CONSTRUCTOR;
|
||||
private static Field SIMPLEPLUGINMANAGER_FILEASSOCIATIONS;
|
||||
private static Method JAVAPLUGINLOADER_GETCLASS_1;
|
||||
private static Method JAVAPLUGINLOADER_GETCLASS_2;
|
||||
private static Method JAVAPLUGINLOADER_SETCLASS;
|
||||
private static Method JAVAPLUGINLOADER_REMOVECLASS_1;
|
||||
private static Method JAVAPLUGINLOADER_REMOVECLASS_2;
|
||||
|
||||
static {
|
||||
try {
|
||||
PLUGINCOMMAND_CONSTRUCTOR = PluginCommand.class.getDeclaredConstructor( String.class, Plugin.class );
|
||||
PLUGINCOMMAND_CONSTRUCTOR.setAccessible( true );
|
||||
SIMPLEPLUGINMANAGER_FILEASSOCIATIONS = SimplePluginManager.class.getDeclaredField( "fileAssociations" );
|
||||
SIMPLEPLUGINMANAGER_FILEASSOCIATIONS.setAccessible( true );
|
||||
JAVAPLUGINLOADER_SETCLASS = JavaPluginLoader.class.getDeclaredMethod( "setClass", String.class, Class.class );
|
||||
JAVAPLUGINLOADER_SETCLASS.setAccessible( true );
|
||||
} catch ( NoSuchMethodException | SecurityException | NoSuchFieldException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
JAVAPLUGINLOADER_GETCLASS_1 = JavaPluginLoader.class.getDeclaredMethod( "getClassByName", String.class );
|
||||
JAVAPLUGINLOADER_GETCLASS_1.setAccessible( true );
|
||||
} catch ( NoSuchMethodException | SecurityException e ) {
|
||||
try {
|
||||
JAVAPLUGINLOADER_GETCLASS_2 = JavaPluginLoader.class.getDeclaredMethod( "getClassByName", String.class, boolean.class, PluginDescriptionFile.class );
|
||||
JAVAPLUGINLOADER_GETCLASS_2.setAccessible( true );
|
||||
} catch ( NoSuchMethodException | SecurityException e1 ) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
JAVAPLUGINLOADER_REMOVECLASS_1 = JavaPluginLoader.class.getDeclaredMethod( "removeClass", String.class );
|
||||
JAVAPLUGINLOADER_REMOVECLASS_1.setAccessible( true );
|
||||
} catch ( NoSuchMethodException | SecurityException e ) {
|
||||
try {
|
||||
JAVAPLUGINLOADER_REMOVECLASS_2 = JavaPluginLoader.class.getDeclaredMethod( "removeClass", Class.class );
|
||||
JAVAPLUGINLOADER_REMOVECLASS_2.setAccessible( true );
|
||||
} catch ( NoSuchMethodException | SecurityException e1 ) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static PluginCommand constructCommand( String id ) {
|
||||
PluginCommand command = null;
|
||||
try {
|
||||
command = PLUGINCOMMAND_CONSTRUCTOR.newInstance( id, JavaPlugin.getPlugin( McMeshEnvironment.class ) );
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call an event synchronously, on the main thread
|
||||
*/
|
||||
public static void callEventSync( Event event ) {
|
||||
if ( Bukkit.getServer().isPrimaryThread() ) {
|
||||
Bukkit.getPluginManager().callEvent( event );
|
||||
} else {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask( JavaPlugin.getPlugin( McMeshEnvironment.class ), () -> { callEventSync( event ); } );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the plugin given is loaded
|
||||
*
|
||||
* @param id
|
||||
* case sensitive plugin id
|
||||
* @return
|
||||
* If the plugin is loaded and enabled
|
||||
*/
|
||||
public static boolean isPluginLoaded( String id ) {
|
||||
return Bukkit.getPluginManager().isPluginEnabled( id );
|
||||
}
|
||||
|
||||
public static Class< ? > getClassByName( String name ) {
|
||||
PluginManager manager = Bukkit.getPluginManager();
|
||||
if ( manager instanceof SimplePluginManager ) {
|
||||
SimplePluginManager sManager = ( SimplePluginManager ) manager;
|
||||
try {
|
||||
Map< Pattern, PluginLoader > associations = ( Map< Pattern, PluginLoader > ) SIMPLEPLUGINMANAGER_FILEASSOCIATIONS.get( sManager );
|
||||
for ( PluginLoader loader : associations.values() ) {
|
||||
if ( loader instanceof JavaPluginLoader ) {
|
||||
if ( JAVAPLUGINLOADER_GETCLASS_1 != null ) {
|
||||
return ( Class< ? > ) JAVAPLUGINLOADER_GETCLASS_1.invoke( loader, name );
|
||||
} else {
|
||||
return ( Class< ? > ) JAVAPLUGINLOADER_GETCLASS_2.invoke( loader, name, true, JavaPlugin.getPlugin( MiniePlugin.class ).getDescription() );
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( IllegalArgumentException | IllegalAccessException | InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void setClassToJavaPluginLoader( String name, Class< ? > clazz ) {
|
||||
PluginManager manager = Bukkit.getPluginManager();
|
||||
if ( manager instanceof SimplePluginManager ) {
|
||||
SimplePluginManager sManager = ( SimplePluginManager ) manager;
|
||||
try {
|
||||
Map< Pattern, PluginLoader > associations = ( Map< Pattern, PluginLoader > ) SIMPLEPLUGINMANAGER_FILEASSOCIATIONS.get( sManager );
|
||||
for ( PluginLoader loader : associations.values() ) {
|
||||
if ( loader instanceof JavaPluginLoader ) {
|
||||
JAVAPLUGINLOADER_SETCLASS.invoke( loader, name, clazz );
|
||||
}
|
||||
}
|
||||
} catch ( IllegalArgumentException | IllegalAccessException | InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean removeClassFromJavaPluginLoader( Class clazz ) {
|
||||
if ( JAVAPLUGINLOADER_REMOVECLASS_2 != null ) {
|
||||
PluginManager manager = Bukkit.getPluginManager();
|
||||
if ( manager instanceof SimplePluginManager ) {
|
||||
SimplePluginManager sManager = ( SimplePluginManager ) manager;
|
||||
try {
|
||||
Map< Pattern, PluginLoader > associations = ( Map< Pattern, PluginLoader > ) SIMPLEPLUGINMANAGER_FILEASSOCIATIONS.get( sManager );
|
||||
for ( PluginLoader loader : associations.values() ) {
|
||||
if ( loader instanceof JavaPluginLoader ) {
|
||||
JAVAPLUGINLOADER_REMOVECLASS_2.invoke( loader, clazz );
|
||||
}
|
||||
}
|
||||
} catch ( IllegalArgumentException | IllegalAccessException | InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean removeClassFromJavaPluginLoader( String name ) {
|
||||
if ( JAVAPLUGINLOADER_REMOVECLASS_1 != null ) {
|
||||
PluginManager manager = Bukkit.getPluginManager();
|
||||
if ( manager instanceof SimplePluginManager ) {
|
||||
SimplePluginManager sManager = ( SimplePluginManager ) manager;
|
||||
try {
|
||||
Map< Pattern, PluginLoader > associations = ( Map< Pattern, PluginLoader > ) SIMPLEPLUGINMANAGER_FILEASSOCIATIONS.get( sManager );
|
||||
for ( PluginLoader loader : associations.values() ) {
|
||||
if ( loader instanceof JavaPluginLoader ) {
|
||||
JAVAPLUGINLOADER_REMOVECLASS_1.invoke( loader, name );
|
||||
}
|
||||
}
|
||||
} catch ( IllegalArgumentException | IllegalAccessException | InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkMesh;
|
||||
|
||||
public class ChunkMeshUtil {
|
||||
public static byte[] serialize( final ChunkMesh mesh ) {
|
||||
final BinaryWriter writer = new BinaryWriter();
|
||||
|
||||
// Header
|
||||
writer.write( "cmesh1", 16 );
|
||||
|
||||
// How many chunk meshes are we providing
|
||||
writer.write( 1, 4 );
|
||||
|
||||
mesh.writeTo( writer );
|
||||
|
||||
return writer.toByteArray();
|
||||
}
|
||||
|
||||
public static ChunkMesh deserialize( final byte[] data ) {
|
||||
final ByteBuffer reader = ByteBuffer.wrap( data );
|
||||
|
||||
final byte[] headerArr = new byte[ 16 ];
|
||||
reader.get( headerArr );
|
||||
final String header = new String( headerArr ).trim();
|
||||
if ( header.equals( "cmesh1" ) ) {
|
||||
// This is how many chunk meshes this data contains
|
||||
final int amount = reader.getInt();
|
||||
|
||||
if ( amount > 1 ) {
|
||||
// Some data is getting discarded...
|
||||
}
|
||||
|
||||
return ChunkMesh.readFrom( reader );
|
||||
}
|
||||
|
||||
throw new IllegalStateException( "Cannot read invalid header: '" + header + "'" );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
/**
|
||||
* Simple file management including YAML updaters
|
||||
*
|
||||
* @author BananaPuncher714
|
||||
*/
|
||||
public final class FileUtil {
|
||||
public static void saveAndUpdate( InputStream stream, File output, boolean trim ) {
|
||||
if ( !output.exists() ) {
|
||||
saveToFile( stream, output, false );
|
||||
}
|
||||
updateConfigFromFile( output, stream, trim );
|
||||
}
|
||||
|
||||
public static void saveToFile( InputStream stream, File output, boolean force ) {
|
||||
if ( force && output.exists() ) {
|
||||
output.delete();
|
||||
}
|
||||
if ( !output.exists() ) {
|
||||
output.getParentFile().mkdirs();
|
||||
try ( OutputStream outStream = new FileOutputStream( output ) ) {
|
||||
byte[] buffer = new byte[ stream.available() ];
|
||||
|
||||
int len;
|
||||
while ( ( len = stream.read( buffer ) ) > 0) {
|
||||
outStream.write( buffer, 0, len );
|
||||
}
|
||||
stream.close();
|
||||
} catch ( FileNotFoundException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( IOException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateConfigFromFile( File toUpdate, InputStream toCopy ) {
|
||||
updateConfigFromFile( toUpdate, toCopy, false );
|
||||
}
|
||||
|
||||
public static void updateConfigFromFile( File toUpdate, InputStream toCopy, boolean trim ) {
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration( new InputStreamReader( toCopy ) );
|
||||
FileConfiguration old = YamlConfiguration.loadConfiguration( toUpdate );
|
||||
|
||||
for ( String key : config.getKeys( true ) ) {
|
||||
if ( !old.contains( key ) ) {
|
||||
old.set( key, config.get( key ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( trim ) {
|
||||
for ( String key : old.getKeys( true ) ) {
|
||||
if ( !config.contains( key ) ) {
|
||||
old.set( key, null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
old.save( toUpdate );
|
||||
} catch ( Exception exception ) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean move( File original, File dest, boolean force ) {
|
||||
if ( dest.exists() ) {
|
||||
if ( !force ) {
|
||||
return false;
|
||||
} else {
|
||||
recursiveDelete( dest );
|
||||
}
|
||||
}
|
||||
dest.getParentFile().mkdirs();
|
||||
original.renameTo( dest );
|
||||
recursiveDelete( original );
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void recursiveDelete( File file ) {
|
||||
if ( !file.exists() ) {
|
||||
return;
|
||||
}
|
||||
if ( file.isDirectory() ) {
|
||||
for ( File lower : file.listFiles() ) {
|
||||
recursiveDelete( lower );
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
public static < T extends Serializable > T readObject( File file ) throws IOException, ClassNotFoundException {
|
||||
if ( !file.exists() ) {
|
||||
return null;
|
||||
}
|
||||
T head = null;
|
||||
FileInputStream fis = new FileInputStream( file );
|
||||
ObjectInputStream ois = new ObjectInputStream( fis );
|
||||
|
||||
head = ( T ) ois.readObject();
|
||||
|
||||
ois.close();
|
||||
fis.close();
|
||||
return head;
|
||||
}
|
||||
|
||||
public static void writeObject( Serializable object, File file ) {
|
||||
file.getParentFile().mkdirs();
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream( file );
|
||||
ObjectOutputStream oos = new ObjectOutputStream( fos );
|
||||
|
||||
oos.writeObject( object );
|
||||
|
||||
oos.close();
|
||||
fos.close();
|
||||
} catch ( Exception exception ) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static File getImageFile( File dir, String prefix ) {
|
||||
File image = new File( dir + "/" + prefix + ".png" );
|
||||
for ( File file : dir.listFiles() ) {
|
||||
String fileName = file.getName();
|
||||
if ( fileName.equalsIgnoreCase( prefix + ".gif" ) ) {
|
||||
return file;
|
||||
} else if ( fileName.equalsIgnoreCase( prefix + ".png" ) || fileName.equalsIgnoreCase( prefix + ".jpg" ) || fileName.equalsIgnoreCase( prefix + ".jpeg" ) || fileName.equalsIgnoreCase( prefix + ".bmp" ) ) {
|
||||
image = file;
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
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() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.bukkit.util.BoundingBox;
|
||||
|
||||
public class Aabb implements Serializable {
|
||||
private static final long serialVersionUID = 6518512405568765913L;
|
||||
|
||||
public final int minX;
|
||||
public final int minY;
|
||||
public final int minZ;
|
||||
public final int maxX;
|
||||
public final int maxY;
|
||||
public final int maxZ;
|
||||
|
||||
public final int width;
|
||||
public final int depth;
|
||||
public final int height;
|
||||
|
||||
public Aabb( final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ ) {
|
||||
this.minX = minX;
|
||||
this.minY = minY;
|
||||
this.minZ = minZ;
|
||||
this.maxX = maxX;
|
||||
this.maxY = maxY;
|
||||
this.maxZ = maxZ;
|
||||
|
||||
this.width = maxX - minX;
|
||||
this.depth = maxZ - minZ;
|
||||
this.height = maxY - minY;
|
||||
}
|
||||
|
||||
public Aabb( final BoundingBox box ) {
|
||||
this.minX = ( int ) box.getMinX();
|
||||
this.maxX = ( int ) box.getMaxX();
|
||||
this.minY = ( int ) box.getMinY();
|
||||
this.maxY = ( int ) box.getMaxY();
|
||||
this.minZ = ( int ) box.getMinZ();
|
||||
this.maxZ = ( int ) box.getMaxZ();
|
||||
|
||||
this.width = maxX - minX;
|
||||
this.depth = maxZ - minZ;
|
||||
this.height = maxY - minY;
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
return width * depth * height;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
public enum BlockDataType {
|
||||
NONE, COMPLEX, SOLID
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.BinaryWriter;
|
||||
|
||||
public class BlockDataTypeSet {
|
||||
private static final int BLOCK_SIZE;
|
||||
private static final BitSet[] SETS;
|
||||
|
||||
static {
|
||||
final int length = BlockDataType.values().length;
|
||||
BLOCK_SIZE = 32 - Integer.numberOfLeadingZeros( length );
|
||||
SETS = new BitSet[ length ];
|
||||
|
||||
// Perhaps not the fastest, since it sets each bit in N time
|
||||
for ( int i = 0; i < length; ++i ) {
|
||||
final BitSet set = new BitSet();
|
||||
for ( int j = 0; j < BLOCK_SIZE; ++j ) {
|
||||
set.set( j, ( ( i >> j ) & 1 ) == 1 );
|
||||
}
|
||||
SETS[ i ] = set;
|
||||
}
|
||||
}
|
||||
|
||||
protected BitSet buffer;
|
||||
|
||||
public BlockDataTypeSet( final byte[] arr ) {
|
||||
buffer = BitSet.valueOf( arr );
|
||||
}
|
||||
|
||||
public BlockDataTypeSet( final int size ) {
|
||||
buffer = new BitSet( size * BLOCK_SIZE );
|
||||
}
|
||||
|
||||
public void set( final int index, final BlockDataType type ) {
|
||||
final BitSet set = SETS[ type.ordinal() ];
|
||||
for ( int i = 0; i < BLOCK_SIZE; ++i ) {
|
||||
buffer.set( ( index * BLOCK_SIZE ) + i, set.get( i ) );
|
||||
}
|
||||
}
|
||||
|
||||
public BlockDataType get( final int index ) {
|
||||
final int bufferIndex = index * BLOCK_SIZE;
|
||||
int ord = 0;
|
||||
for ( int i = buffer.nextSetBit( bufferIndex ); i >= bufferIndex && i < bufferIndex + BLOCK_SIZE; i = buffer.nextSetBit( i + 1 ) ) {
|
||||
ord |= 1 << ( i - bufferIndex );
|
||||
}
|
||||
return BlockDataType.values()[ ord ];
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* Represents a Bukkit chunk's location.
|
||||
*
|
||||
* @author BananaPuncher714
|
||||
*/
|
||||
public class ChunkLocation implements Comparable< ChunkLocation > {
|
||||
private int x, z;
|
||||
private String worldName;
|
||||
private World world;
|
||||
|
||||
/**
|
||||
* Construct a ChunkLocation from a Location.
|
||||
*
|
||||
* @param location
|
||||
* Cannot be null.
|
||||
*/
|
||||
public ChunkLocation( Location location ) {
|
||||
Validate.notNull( location );
|
||||
world = location.getWorld();
|
||||
worldName = world.getName();
|
||||
x = location.getBlockX() >> 4;
|
||||
z = location.getBlockZ() >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a ChunkLocation.
|
||||
*
|
||||
* @param location
|
||||
* Cannot be null.
|
||||
*/
|
||||
public ChunkLocation( ChunkLocation location ) {
|
||||
Validate.notNull( location );
|
||||
x = location.x;
|
||||
z = location.z;
|
||||
worldName = location.worldName;
|
||||
world = location.world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ChunkLocation from chunk coordinates.
|
||||
*
|
||||
* @param world
|
||||
* Cannot be null.
|
||||
* @param x
|
||||
* Chunk coordinate x value.
|
||||
* @param z
|
||||
* Chunk coordinate z value.
|
||||
*/
|
||||
public ChunkLocation( World world, int x, int z ) {
|
||||
Validate.notNull( world );
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.worldName = world.getName();
|
||||
this.world = world;
|
||||
|
||||
}
|
||||
|
||||
public ChunkLocation( String world, int x, int z ) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.worldName = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ChunkLocation from a Bukkit chunk.
|
||||
*
|
||||
* @param chunk
|
||||
* Cannot be null.
|
||||
*/
|
||||
public ChunkLocation( Chunk chunk ) {
|
||||
Validate.notNull( chunk );
|
||||
world = chunk.getWorld();
|
||||
worldName = world.getName();
|
||||
x = chunk.getX();
|
||||
z = chunk.getZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ChunkLocation from a ChunkSnapshot.
|
||||
*
|
||||
* @param snapshot
|
||||
* Cannot be null. The world will not be cached, only the world name.
|
||||
*/
|
||||
public ChunkLocation( ChunkSnapshot snapshot ) {
|
||||
Validate.notNull( snapshot );
|
||||
worldName = snapshot.getWorldName();
|
||||
x = snapshot.getX();
|
||||
z = snapshot.getZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the x coordinate.
|
||||
*
|
||||
* @return
|
||||
* Chunk coordinate x value.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the x coordinate.
|
||||
*
|
||||
* @param x
|
||||
* Chunk coordinate x value.
|
||||
*/
|
||||
public ChunkLocation setX( int x ) {
|
||||
this.x = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the z coordinate.
|
||||
*
|
||||
* @return
|
||||
* Chunk coordinate z value.
|
||||
*/
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the z coordinate.
|
||||
*
|
||||
* @param z
|
||||
* Chunk coordinate z value.
|
||||
*/
|
||||
public ChunkLocation setZ( int z ) {
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add coordinates from current coordinates.
|
||||
*
|
||||
* @param x
|
||||
* Chunk x coordinate value.
|
||||
* @param z
|
||||
* Chunk z coordinate value.
|
||||
* @return
|
||||
* This location.
|
||||
*/
|
||||
public ChunkLocation add( int x, int z ) {
|
||||
this.x += x;
|
||||
this.z += z;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract coordinates from current coordinates.
|
||||
*
|
||||
* @param x
|
||||
* Chunk x coordinate value.
|
||||
* @param z
|
||||
* Chunk z coordinate value.
|
||||
* @return
|
||||
* This location.
|
||||
*/
|
||||
public ChunkLocation subtract( int x, int z ) {
|
||||
this.x -= x;
|
||||
this.z -= z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the world.
|
||||
*
|
||||
* @return
|
||||
* A non-null world, will fetch and cache the world if not cached already.
|
||||
*/
|
||||
public World getWorld() {
|
||||
if ( world == null ) {
|
||||
world = Bukkit.getWorld( worldName );
|
||||
}
|
||||
return world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the world.
|
||||
*
|
||||
* @param world
|
||||
* Cannot be null.
|
||||
*/
|
||||
public void setWorld( World world ) {
|
||||
Validate.notNull( world );
|
||||
this.world = world;
|
||||
this.worldName = world.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the chunk this location represents.
|
||||
*
|
||||
* @return
|
||||
* May load the chunk.
|
||||
*/
|
||||
public Chunk getChunk() {
|
||||
return world.getChunkAt( x, z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the chunk that this location represents is loaded.
|
||||
*
|
||||
* @return
|
||||
* If the chunk is loaded. Does not load the chunk.
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return getWorld().isChunkLoaded( x, z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the chunk that this location represents.
|
||||
*/
|
||||
public void load() {
|
||||
getWorld().loadChunk( x, z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this chunk exists.
|
||||
*
|
||||
* @return
|
||||
* Checks if the chunk exists, does not have to be loaded.
|
||||
*/
|
||||
public boolean exists() {
|
||||
return getWorld().loadChunk( x, z, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ( ( worldName == null ) ? 0 : worldName.hashCode() );
|
||||
result = prime * result + x;
|
||||
result = prime * result + z;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ( this == obj ) {
|
||||
return true;
|
||||
}
|
||||
if ( obj == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( getClass() != obj.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ChunkLocation other = ( ChunkLocation ) obj;
|
||||
|
||||
if ( worldName == null ) {
|
||||
if ( other.worldName != null ) {
|
||||
return false;
|
||||
}
|
||||
} else if ( !worldName.equals( other.worldName ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( x != other.x ) {
|
||||
return false;
|
||||
}
|
||||
if ( z != other.z ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChunkLocation{x:" + x + ",z:" + z + ",world:" + worldName + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( ChunkLocation o ) {
|
||||
final int worldCompare = worldName.compareTo( o.worldName );
|
||||
if ( worldCompare == 0 ) {
|
||||
if ( x == o.x ) {
|
||||
return Integer.compare( z, o.z );
|
||||
}
|
||||
return Integer.compare( x, o.x );
|
||||
}
|
||||
return worldCompare;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point;
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
|
||||
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.MinecraftPlane.PlaneAxis;
|
||||
import com.aaaaahhhhhhh.bananapuncher714.minietest.util.BinaryWriter;
|
||||
import com.jme3.bullet.collision.shapes.infos.IndexedMesh;
|
||||
import com.jme3.math.Vector3f;
|
||||
|
||||
public class ChunkMesh {
|
||||
// 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
|
||||
private int[] data;
|
||||
// The bounding boxes for each complex block, null if air or a cube
|
||||
private BoundingBox[][] boxes;
|
||||
// Stores which blocks are complex/simple/empty
|
||||
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
|
||||
private Aabb box;
|
||||
|
||||
public ChunkMesh( BoundingBox box ) {
|
||||
this.box = new Aabb( box );
|
||||
|
||||
final int volume = this.box.getVolume();
|
||||
data = new int[ volume ];
|
||||
boxes = new BoundingBox[ volume ][];
|
||||
blockTypes = new BlockDataTypeSet( volume );
|
||||
}
|
||||
|
||||
public ChunkMesh( Aabb box ) {
|
||||
this.box = box;
|
||||
|
||||
final int volume = this.box.getVolume();
|
||||
data = new int[ volume ];
|
||||
boxes = new BoundingBox[ volume ][];
|
||||
blockTypes = new BlockDataTypeSet( volume );
|
||||
}
|
||||
|
||||
public void setType( final int index, final BlockDataType type ) {
|
||||
blockTypes.set( index, type );
|
||||
}
|
||||
|
||||
public BlockDataType getType( final int index ) {
|
||||
return blockTypes.get( index );
|
||||
}
|
||||
|
||||
public void setData( final int index, final BlockData data ) {
|
||||
this.data[ index ] = data.getAsString().hashCode();
|
||||
}
|
||||
|
||||
public void setBoxes( final int index, final BoundingBox[] boxes ) {
|
||||
this.boxes[ index ] = boxes;
|
||||
}
|
||||
|
||||
public boolean isBlockAt( final int index, final BlockData data ) {
|
||||
return blockTypes.get( index ) == BlockDataType.COMPLEX && this.data[ index ] == data.getAsString().hashCode();
|
||||
}
|
||||
|
||||
public BoundingBox[] getBoxesAt( final int index ) {
|
||||
return boxes[ index ];
|
||||
}
|
||||
|
||||
public PlaneMesh getOrAdd( final MinecraftPlane plane ) {
|
||||
PlaneMesh results = planes.get( plane );
|
||||
if ( results == null ) {
|
||||
results = new PlaneMesh();
|
||||
planes.put( plane, results );
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
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 ) {
|
||||
if ( triangle.points.size() != 3 ) {
|
||||
throw new IllegalStateException( "Triangle does not have exactly 3 vertices!" );
|
||||
}
|
||||
|
||||
final int indexArrayStart = triangleIndex * 3;
|
||||
indexArray[ indexArrayStart ] = triangle.points.get( 0 ).index;
|
||||
indexArray[ indexArrayStart + 1 ] = triangle.points.get( 1 ).index;
|
||||
indexArray[ indexArrayStart + 2 ] = triangle.points.get( 2 ).index;
|
||||
|
||||
++triangleIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return new IndexedMesh( positionArray, indexArray );
|
||||
}
|
||||
|
||||
public void writeTo( final BinaryWriter writer ) {
|
||||
// Gather all vectors and map them to indices
|
||||
|
||||
|
||||
|
||||
// Write the bounding box
|
||||
writer.write( box.minX );
|
||||
writer.write( box.minY );
|
||||
writer.write( box.minZ );
|
||||
writer.write( box.maxX );
|
||||
writer.write( box.maxY );
|
||||
writer.write( box.maxZ );
|
||||
|
||||
// Write our data blocks
|
||||
for ( final int hash : data ) {
|
||||
writer.write( hash );
|
||||
}
|
||||
|
||||
// Write our bounding boxes
|
||||
for ( final BoundingBox[] boxArr : boxes ) {
|
||||
// Write how many boxes
|
||||
if ( boxArr == null ) {
|
||||
writer.write( ( int ) 0 );
|
||||
} else {
|
||||
writer.write( boxArr.length );
|
||||
|
||||
for ( final BoundingBox box : boxArr ) {
|
||||
writer.write( box.getMinX() );
|
||||
writer.write( box.getMinY() );
|
||||
writer.write( box.getMinZ() );
|
||||
writer.write( box.getMaxX() );
|
||||
writer.write( box.getMaxY() );
|
||||
writer.write( box.getMaxZ() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write our block types
|
||||
final byte[] blockTypeBuf = blockTypes.toByteArray();
|
||||
writer.write( blockTypeBuf.length );
|
||||
writer.write( blockTypeBuf );
|
||||
|
||||
// Write our point references
|
||||
writer.write( pointReferences.size() );
|
||||
for ( final VectorReference ref : pointReferences ) {
|
||||
writer.write( ref.vector.getX() );
|
||||
writer.write( ref.vector.getY() );
|
||||
writer.write( ref.vector.getZ() );
|
||||
writer.write( ref.index );
|
||||
writer.write( ref.referenceCount );
|
||||
}
|
||||
|
||||
// Write our planes
|
||||
writer.write( planes.size() );
|
||||
for ( final Entry< MinecraftPlane, PlaneMesh > entry : planes.entrySet() ) {
|
||||
final MinecraftPlane plane = entry.getKey();
|
||||
writer.write( plane.normal.ordinal() );
|
||||
writer.write( plane.offset );
|
||||
|
||||
final PlaneMesh mesh = entry.getValue();
|
||||
|
||||
// Write each region
|
||||
writer.write( mesh.generatedRegions.size() );
|
||||
for ( final Polygon poly : mesh.generatedRegions ) {
|
||||
writer.write( poly.getPoints().size() );
|
||||
for ( final Point p : poly.getPoints() ) {
|
||||
writer.write( p.getX() );
|
||||
writer.write( p.getY() );
|
||||
}
|
||||
}
|
||||
|
||||
// Write each triangle
|
||||
writer.write( mesh.completedPolygons.size() );
|
||||
for ( final IndexedPolygon poly : mesh.completedPolygons ) {
|
||||
writer.write( poly.points.size() );
|
||||
for ( final VectorReference ref : poly.points ) {
|
||||
writer.write( ref.index );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ChunkMesh readFrom( final ByteBuffer buffer ) {
|
||||
final Aabb box = new Aabb( buffer.getInt(), buffer.getInt(), buffer.getInt(), buffer.getInt(), buffer.getInt(), buffer.getInt() );
|
||||
|
||||
final ChunkMesh mesh = new ChunkMesh( box );
|
||||
|
||||
final int size = box.getVolume();
|
||||
|
||||
buffer.asIntBuffer().get( mesh.data );
|
||||
buffer.position( buffer.position() + ( mesh.data.length << 2 ) );
|
||||
|
||||
// Read our boxes
|
||||
for ( int i = 0; i < size; ++i ) {
|
||||
final int boxCount = buffer.getInt();
|
||||
if ( boxCount > 0 ) {
|
||||
final BoundingBox[] boxes = new BoundingBox[ boxCount ];
|
||||
for ( int j = 0; j < boxCount; ++j ) {
|
||||
boxes[ j ] = new BoundingBox( buffer.getDouble(), buffer.getDouble(), buffer.getDouble(), buffer.getDouble(), buffer.getDouble(), buffer.getDouble() );
|
||||
}
|
||||
mesh.boxes[ i ] = boxes;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the block types
|
||||
final int blockTypeBufSize = buffer.getInt();
|
||||
final byte[] bitSet = new byte[ blockTypeBufSize ];
|
||||
buffer.get( bitSet );
|
||||
mesh.blockTypes = new BlockDataTypeSet( bitSet );
|
||||
|
||||
// Read the plane references
|
||||
final int pointCount = buffer.getInt();
|
||||
final VectorReference[] references = new VectorReference[ pointCount ];
|
||||
for ( int i = 0; i < pointCount; ++i ) {
|
||||
final VectorReference reference = new VectorReference( new Vector( buffer.getDouble(), buffer.getDouble(), buffer.getDouble() ) );
|
||||
reference.index = buffer.getInt();
|
||||
reference.referenceCount = buffer.getInt();
|
||||
references[ reference.index ] = reference;
|
||||
mesh.pointReferences.add( reference );
|
||||
}
|
||||
|
||||
// Get the planes
|
||||
final int planeCount = buffer.getInt();
|
||||
for ( int i = 0; i < planeCount; ++i ) {
|
||||
final MinecraftPlane plane = new MinecraftPlane( PlaneAxis.values()[ buffer.getInt() ], buffer.getDouble() );
|
||||
|
||||
final PlaneMesh planeMesh = new PlaneMesh();
|
||||
planeMesh.generatedRegions = new ArrayDeque< Polygon >();
|
||||
planeMesh.completedPolygons = new ArrayDeque< IndexedPolygon >();
|
||||
final int regionCount = buffer.getInt();
|
||||
for ( int j = 0; j < regionCount; ++j ) {
|
||||
final int vertexCount = buffer.getInt();
|
||||
|
||||
final List< Point > points = new ArrayList< Point >();
|
||||
for ( int k = 0; k < vertexCount; ++k ) {
|
||||
points.add( new Point( buffer.getDouble(), buffer.getDouble() ) );
|
||||
}
|
||||
|
||||
planeMesh.generatedRegions.add( new Polygon( points ) );
|
||||
}
|
||||
|
||||
final int triangleCount = buffer.getInt();
|
||||
for ( int j = 0; j < triangleCount; ++j ) {
|
||||
final int vertexCount = buffer.getInt();
|
||||
|
||||
final IndexedPolygon triangle = new IndexedPolygon();
|
||||
for ( int k = 0; k < vertexCount; ++k ) {
|
||||
triangle.points.add( references[ buffer.getInt() ] );
|
||||
}
|
||||
|
||||
planeMesh.completedPolygons.add( triangle );
|
||||
}
|
||||
|
||||
mesh.planes.put( plane, planeMesh );
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IndexedPolygon {
|
||||
public List< VectorReference > points = new ArrayList< VectorReference >();
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point;
|
||||
|
||||
public class MinecraftPlane implements Comparable< MinecraftPlane > {
|
||||
public final PlaneAxis normal;
|
||||
public final double offset;
|
||||
|
||||
public MinecraftPlane( final PlaneAxis axis, final double offset ) {
|
||||
this.normal = axis;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public Vector convert( final Point point ) {
|
||||
switch ( normal ) {
|
||||
case X:
|
||||
return new Vector( offset, point.getX(), point.getY() );
|
||||
case Y:
|
||||
return new Vector( point.getX(), offset, point.getY() );
|
||||
case Z:
|
||||
return new Vector( point.getX(), point.getY(), offset );
|
||||
}
|
||||
|
||||
throw new IllegalStateException( "No normal set!" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( final MinecraftPlane o ) {
|
||||
if ( normal == o.normal ) {
|
||||
return Double.compare( offset, o.offset );
|
||||
}
|
||||
return normal.compareTo( o.normal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((normal == null) ? 0 : normal.hashCode());
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(offset);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MinecraftPlane other = (MinecraftPlane) obj;
|
||||
if (normal != other.normal)
|
||||
return false;
|
||||
if (Double.doubleToLongBits(offset) != Double.doubleToLongBits(other.offset))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MinecraftPlane{axis=" + normal + ",offset=" + offset + "}";
|
||||
}
|
||||
|
||||
public static enum PlaneAxis {
|
||||
X, Y, Z
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class VectorReference implements Comparable< VectorReference > {
|
||||
public Vector vector;
|
||||
public int referenceCount = 0;
|
||||
public int index = 0;
|
||||
|
||||
public VectorReference( final Vector vector ) {
|
||||
this.vector = vector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( final VectorReference o ) {
|
||||
final Vector oVec = o.vector;
|
||||
|
||||
if ( vector.getX() == oVec.getX() ) {
|
||||
if ( vector.getY() == oVec.getY() ) {
|
||||
if ( vector.getZ() == oVec.getZ() ) {
|
||||
return 0;
|
||||
}
|
||||
return Double.compare( vector.getZ(), oVec.getZ() );
|
||||
}
|
||||
return Double.compare( vector.getY(), oVec.getY() );
|
||||
}
|
||||
return Double.compare( vector.getX(), oVec.getX() );
|
||||
}
|
||||
}
|
||||
14
plugin/environment/src/main/resources/plugin.yml
Normal file
14
plugin/environment/src/main/resources/plugin.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
name: MC-Mesh-Environment
|
||||
main: com.aaaaahhhhhhh.bananapuncher714.minietest.MiniePlugin
|
||||
version: 0.0.1
|
||||
description: BulletJME and MC-Mesh integration
|
||||
author: BananaPuncher714
|
||||
api-version: 1.13
|
||||
#libraries:
|
||||
#- com.github.stephengold:Minie:7.5.0
|
||||
|
||||
commands:
|
||||
minie:
|
||||
description: Main Minie command
|
||||
aliases: []
|
||||
permission: minie
|
||||
Reference in New Issue
Block a user