Partial refactor

This commit is contained in:
2026-03-16 18:35:19 -04:00
parent 14b1647c47
commit 95e374682b
93 changed files with 345 additions and 331 deletions

View 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.

View 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>

View 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>

View File

@@ -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;
}
}

View File

@@ -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 );
}
}

View File

@@ -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( ", " ) ) + "]";
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}

View File

@@ -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 );
}
}

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author BananaPuncher714
*
*/
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.executor;

View File

@@ -0,0 +1,6 @@
/**
* Classes for building complex command trees.
*
* @author BananaPuncher714
*/
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command;

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}

View File

@@ -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 ] );
}
}

View File

@@ -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 ] );
}
}

View File

@@ -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 ];
}
}

View File

@@ -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 ] );
}
}

View File

@@ -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 ];
}
}

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author BananaPuncher714
*
*/
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator;

View File

@@ -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 );
}

View File

@@ -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 );
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author BananaPuncher714
*
*/
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment.command.validator.sender;

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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 + "'" );
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -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() );
}
}
}

View File

@@ -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;
}
}

View File

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

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 >();
}

View File

@@ -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
}
}

View File

@@ -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;
}

View File

@@ -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() );
}
}

View 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