Add most of code. Still missing some hint related stuff.

Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
This commit is contained in:
Glease committed 2021-05-17 03:02:24 +08:00
1 parent b5166dbd1c
commit dc12c4a1df
40 files changed
+4085

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
+20
View File
@@ -0,0 +1,20 @@
*.class
*.log
*.ctxt
.mtj.tmp/
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
hs_err_pid*
.gradle
**/build/
!src/**/build/
gradle-app.setting
!gradle-wrapper.jar
.gradletasknamecache
.idea/
run/
+56
View File
@@ -0,0 +1,56 @@
buildscript {
repositories {
mavenCentral()
maven {
name = "forge"
url = "https://files.minecraftforge.net/maven"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
}
}
apply plugin: 'forge'
version = modVersion
group= modGroup
archivesBaseName = modBaseName
sourceCompatibility = 1.8
targetCompatibility = 1.8
minecraft {
version = project.forgeVersion
}
dependencies {
}
processResources
{
inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
expand 'version':project.version, 'mcversion':project.minecraft.version
}
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
}
task deobfJar(type: Jar) {
from sourceSets.main.output
appendix = 'deobf'
}
artifacts {
archives deobfJar
}
+5
View File
@@ -0,0 +1,5 @@
modGroup = com.gtnewhorizon
modVersion = 1.0.0
modBaseName = StructureLib
forgeVersion = 1.7.10-10.13.4.1614-1.7.10
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
#Sat Jan 04 01:52:14 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
Vendored
+164
View File
@@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
Vendored
+90
View File
@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@@ -0,0 +1,18 @@
package com.gtnewhorizon.structurelib;
import com.gtnewhorizon.structurelib.proxy.CommonProxy;
import com.gtnewhorizon.structurelib.util.XSTR;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.SidedProxy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Mod(modid = StructureLib.MOD_ID, name = "StructureLib", version = "${version}", acceptableRemoteVersions = "*", canBeDeactivated = false)
public class StructureLib {
public static boolean DEBUG_MODE = true;
public static Logger LOGGER = LogManager.getLogger("StructureLib");
public static final String MOD_ID = "structurelib";
@SidedProxy(serverSide = "com.gtnewhorizon.structurelib.proxy.CommonProxy", clientSide = "com.gtnewhorizon.structurelib.proxy.ClientProxy")
public static CommonProxy proxy;
public static final XSTR RANDOM = new XSTR();
}
@@ -0,0 +1,183 @@
package com.gtnewhorizon.structurelib.alignment;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
import java.util.function.Function;
import static com.gtnewhorizon.structurelib.alignment.IAlignment.STATES_COUNT;
public class AlignmentLimits implements IAlignmentLimits {
protected final boolean[] validStates=new boolean[STATES_COUNT];
public AlignmentLimits() {
allowAll();
}
AlignmentLimits allowAll(){
Arrays.fill(validStates,true);
return this;
}
AlignmentLimits denyAll(){
Arrays.fill(validStates,false);
return this;
}
AlignmentLimits randomAll(Random random){
for (int i = 0; i < validStates.length; i++) {
validStates[i]=random.nextBoolean();
}
return this;
}
AlignmentLimits deny(ExtendedFacing... deny){
if(deny!=null){
for (ExtendedFacing extendedFacing : deny) {
validStates[extendedFacing.getIndex()]=false;
}
}
return this;
}
AlignmentLimits allow(ExtendedFacing... allow){
if(allow!=null){
for (ExtendedFacing extendedFacing : allow) {
validStates[extendedFacing.getIndex()]=false;
}
}
return this;
}
AlignmentLimits deny(ForgeDirection... deny){
if(deny!=null){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
for (ForgeDirection direction : deny) {
if (value.getDirection() == direction) {
validStates[value.getIndex()] = false;
break;
}
}
}
}
return this;
}
AlignmentLimits allow(ForgeDirection... allow){
if(allow!=null){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
for (ForgeDirection direction : allow) {
if (value.getDirection() == direction) {
validStates[value.getIndex()] = true;
break;
}
}
}
}
return this;
}
AlignmentLimits deny(Rotation... deny){
if(deny!=null){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
for (Rotation rotation : deny) {
if (value.getRotation() == rotation) {
validStates[value.getIndex()] = false;
break;
}
}
}
}
return this;
}
AlignmentLimits allow(Rotation... allow){
if(allow!=null){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
for (Rotation rotation : allow) {
if (value.getRotation() == rotation) {
validStates[value.getIndex()] = true;
break;
}
}
}
}
return this;
}
AlignmentLimits deny(Flip... deny){
if(deny!=null){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
for (Flip flip : deny) {
if (value.getFlip() == flip) {
validStates[value.getIndex()] = false;
break;
}
}
}
}
return this;
}
AlignmentLimits allow(Flip... allow){
if(allow!=null){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
for (Flip flip : allow) {
if (value.getFlip() == flip) {
validStates[value.getIndex()] = true;
break;
}
}
}
}
return this;
}
AlignmentLimits predicateApply(Function<ExtendedFacing,Optional<Boolean>> predicate){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
predicate.apply(value).ifPresent(bool->validStates[value.getIndex()]=bool);
}
return this;
}
AlignmentLimits ensureDuplicates(){
for (ExtendedFacing value : ExtendedFacing.VALUES) {
if(validStates[value.getIndex()]){
validStates[value.getDuplicate().getIndex()]=true;
}
}
return this;
}
/**
* Prefers rotation over flip, so both flip will get translated to opposite rotation and no flip
* @param flip the preferred flip to be used Horizontal or vertical
* @return this
*/
AlignmentLimits ensureNoDuplicates(Flip flip){
if(flip==Flip.BOTH||flip==Flip.NONE){
throw new IllegalArgumentException("Preffered Flip must be Horizontal or Vertical");
}
flip=flip.getOpposite();
for (ExtendedFacing value : ExtendedFacing.VALUES) {
if(validStates[value.getIndex()]){
if(value.getFlip()==Flip.BOTH || value.getFlip()==flip){
validStates[value.getIndex()]=false;
validStates[value.getDuplicate().getIndex()]=true;
}
}
}
return this;
}
@Override
public boolean isNewExtendedFacingValid(ForgeDirection direction, Rotation rotation, Flip flip) {
return validStates[IAlignment.getAlignmentIndex(direction,rotation,flip)];
}
}
@@ -0,0 +1,130 @@
package com.gtnewhorizon.structurelib.alignment;
import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import io.netty.buffer.ByteBuf;
import net.minecraft.nbt.NBTTagCompound;
public class AlignmentMessage implements IMessage {
int mPosX;
int mPosY;
int mPosZ;
int mPosD;
int mAlign;
public AlignmentMessage() {
}
@Override
public void fromBytes(ByteBuf pBuffer) {
NBTTagCompound tTag = ByteBufUtils.readTag(pBuffer);
mPosX = tTag.getInteger("posx");
mPosY = tTag.getInteger("posy");
mPosZ = tTag.getInteger("posz");
mPosD = tTag.getInteger("posd");
mAlign = tTag.getInteger("rotf");
}
@Override
public void toBytes(ByteBuf pBuffer) {
NBTTagCompound tFXTag = new NBTTagCompound();
tFXTag.setInteger("posx", mPosX);
tFXTag.setInteger("posy", mPosY);
tFXTag.setInteger("posz", mPosZ);
tFXTag.setInteger("posd", mPosD);
tFXTag.setInteger("rotf", mAlign);
ByteBufUtils.writeTag(pBuffer, tFXTag);
}
/*
private AlignmentMessage(GT_MetaTileEntity_MultiblockBase_EM metaTile) {
IGregTechTileEntity base=metaTile.getBaseMetaTileEntity();
mPosX=base.getXCoord();
mPosY=base.getYCoord();
mPosZ=base.getZCoord();
mPosD=base.getWorld().provider.dimensionId;
mAlign =metaTile.getExtendedFacing().getIndex();
}
private AlignmentMessage(World world, int x, int y, int z, IAlignment front) {
mPosX=x;
mPosY=y;
mPosZ=z;
mPosD=world.provider.dimensionId;
mAlign =front.getExtendedFacing().getIndex();
}
public static class AlignmentQuery extends AlignmentMessage {
public AlignmentQuery() {
}
public AlignmentQuery(GT_MetaTileEntity_MultiblockBase_EM metaTile) {
super(metaTile);
}
public AlignmentQuery(World world, int x, int y, int z, IAlignment front) {
super(world,x,y,z,front);
}
}
public static class AlignmentData extends AlignmentMessage {
public AlignmentData() {
}
private AlignmentData(AlignmentQuery query){
mPosX=query.mPosX;
mPosY=query.mPosY;
mPosZ=query.mPosZ;
mPosD=query.mPosD;
mAlign =query.mAlign;
}
public AlignmentData(GT_MetaTileEntity_MultiblockBase_EM metaTile) {
super(metaTile);
}
public AlignmentData(World world, int x, int y, int z, IAlignment front) {
super(world,x,y,z,front);
}
}
public static class ClientHandler extends AbstractClientMessageHandler<AlignmentData> {
@Override
public IMessage handleClientMessage(EntityPlayer pPlayer, AlignmentData pMessage, MessageContext pCtx) {
if(pPlayer.worldObj.provider.dimensionId==pMessage.mPosD){
TileEntity te=pPlayer.worldObj.getTileEntity(pMessage.mPosX,pMessage.mPosY,pMessage.mPosZ);
if(te instanceof IGregTechTileEntity){
IMetaTileEntity meta = ((IGregTechTileEntity) te).getMetaTileEntity();
if(meta instanceof IAlignment){
((IAlignment) meta).setExtendedFacing(ExtendedFacing.byIndex(pMessage.mAlign));
}
}else if (te instanceof IAlignment){
((IAlignment) te).setExtendedFacing(ExtendedFacing.byIndex(pMessage.mAlign));
}
}
return null;
}
}
public static class ServerHandler extends AbstractServerMessageHandler<AlignmentQuery> {
@Override
public IMessage handleServerMessage(EntityPlayer pPlayer, AlignmentQuery pMessage, MessageContext pCtx) {
World world= DimensionManager.getWorld(pMessage.mPosD);
if(world!=null) {
TileEntity te = world.getTileEntity(pMessage.mPosX, pMessage.mPosY, pMessage.mPosZ);
if (te instanceof IGregTechTileEntity) {
IMetaTileEntity meta = ((IGregTechTileEntity) te).getMetaTileEntity();
if (meta instanceof IAlignment) {
pMessage.mAlign =((IAlignment) meta).getExtendedFacing().getIndex();
return new AlignmentData(pMessage);
}
} else if (te instanceof IAlignment) {
pMessage.mAlign =((IAlignment) te).getExtendedFacing().getIndex();
return new AlignmentData(pMessage);
}
}
return null;
}
}
*/
}
@@ -0,0 +1,43 @@
package com.gtnewhorizon.structurelib.alignment;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
public class AlignmentUtility {
private AlignmentUtility(){
}
public static boolean handle(EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ){
TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
if(tTileEntity==null || aPlayer instanceof FakePlayer) {
return aPlayer instanceof EntityPlayerMP;
}
if (aPlayer instanceof EntityPlayerMP) {
/* TODO Make GT tile entity implement this interface and delegate all functionality to MTE
if (tTileEntity instanceof IGregTechTileEntity) {
IMetaTileEntity metaTE = ((IGregTechTileEntity) tTileEntity).getMetaTileEntity();
if (metaTE instanceof IAlignmentProvider) {
IAlignment alignment = ((IAlignmentProvider) metaTE).getAlignment();
if(aPlayer.isSneaking()){
alignment.toolSetFlip(null);
}else {
alignment.toolSetRotation(null);
}
return true;
}
} else */ if (tTileEntity instanceof IAlignmentProvider) {
IAlignment alignment = ((IAlignmentProvider) tTileEntity).getAlignment();
if(aPlayer.isSneaking()){
alignment.toolSetFlip(null);
}else {
alignment.toolSetRotation(null);
}
return true;
}
}
return false;
}
}
@@ -0,0 +1,185 @@
package com.gtnewhorizon.structurelib.alignment;
import com.gtnewhorizon.structurelib.alignment.enumerable.Direction;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
import net.minecraftforge.common.util.ForgeDirection;
public interface IAlignment extends IAlignmentLimits,IAlignmentProvider {
int DIRECTIONS_COUNT= Direction.VALUES.length;
int ROTATIONS_COUNT= Rotation.VALUES.length;
int FLIPS_COUNT= Flip.VALUES.length;
int STATES_COUNT = ExtendedFacing.VALUES.length;
ExtendedFacing getExtendedFacing();
void setExtendedFacing(ExtendedFacing alignment);
IAlignmentLimits getAlignmentLimits();
void setAlignmentLimits(IAlignmentLimits limits);
@Override
default IAlignment getAlignment(){
return this;
}
static int getAlignmentIndex(ForgeDirection direction, Rotation rotation, Flip flip){
return (direction.ordinal()*ROTATIONS_COUNT+rotation.getIndex())*FLIPS_COUNT+flip.getIndex();
}
default ForgeDirection getDirection(){
return getExtendedFacing().getDirection();
}
default void setDirection(ForgeDirection direction){
setExtendedFacing(getExtendedFacing().with(direction));
}
default Rotation getRotation(){
return getExtendedFacing().getRotation();
}
default void setRotation(Rotation rotation){
setExtendedFacing(getExtendedFacing().with(rotation));
}
default Flip getFlip(){
return getExtendedFacing().getFlip();
}
default void setFlip(Flip flip){
setExtendedFacing(getExtendedFacing().with(flip));
}
default boolean toolSetDirection(ForgeDirection direction){
if(direction==null || direction==ForgeDirection.UNKNOWN){
for (int i = 0,j=getDirection().ordinal()+1, valuesLength = Direction.VALUES.length; i < valuesLength; i++) {
if(toolSetDirection(Direction.VALUES[j%valuesLength].getForgeDirection())){
return true;
}
}
}else {
for (ExtendedFacing extendedFacing : ExtendedFacing.FOR_FACING.get(direction)) {
if(checkedSetExtendedFacing(extendedFacing)){
return true;
}
}
}
return false;
}
default boolean checkedSetDirection(ForgeDirection direction){
if (isNewDirectionValid(direction)){
setDirection(direction);
return true;
}
return false;
}
default boolean canSetToDirectionAny(ForgeDirection direction){
for (ExtendedFacing extendedFacing : ExtendedFacing.FOR_FACING.get(direction)) {
if(isNewExtendedFacingValid(extendedFacing)){
return true;
}
}
return false;
}
default boolean toolSetRotation(Rotation rotation) {
if(rotation==null){
int flips = Flip.VALUES.length;
int rotations = Rotation.VALUES.length;
for (int ii = 0,jj=getFlip().ordinal(); ii < flips; ii++) {
for (int i = 0,j=getRotation().ordinal()+1; i < rotations; i++) {
if(checkedSetExtendedFacing(ExtendedFacing.of(getDirection(),Rotation.VALUES[j%rotations],Flip.VALUES[jj%flips]))){
return true;
}
}
}
return false;
}else {
return checkedSetRotation(rotation);
}
}
default boolean checkedSetRotation(Rotation rotation){
if (isNewRotationValid(rotation)){
setRotation(rotation);
return true;
}
return false;
}
default boolean toolSetFlip(Flip flip){
if(flip==null){
for (int i = 0,j=getFlip().ordinal()+1, valuesLength = Flip.VALUES.length; i < valuesLength; i++) {
if(toolSetFlip(Flip.VALUES[j%valuesLength])){
return true;
}
}
return false;
}else {
return checkedSetFlip(flip);
}
}
default boolean checkedSetFlip(Flip flip){
if (isNewFlipValid(flip)){
setFlip(flip);
return true;
}
return false;
}
default boolean toolSetExtendedFacing(ExtendedFacing extendedFacing){
if(extendedFacing==null){
for (int i = 0,j=getExtendedFacing().ordinal()+1, valuesLength = ExtendedFacing.VALUES.length; i < valuesLength; i++) {
if(toolSetExtendedFacing(ExtendedFacing.VALUES[j%valuesLength])){
return true;
}
}
return false;
}else {
return checkedSetExtendedFacing(extendedFacing);
}
}
default boolean checkedSetExtendedFacing(ExtendedFacing alignment){
if (isNewExtendedFacingValid(alignment)){
setExtendedFacing(alignment);
return true;
}
return false;
}
default boolean isNewDirectionValid(ForgeDirection direction) {
return isNewExtendedFacingValid(direction,getRotation(),getFlip());
}
default boolean isNewRotationValid(Rotation rotation){
return isNewExtendedFacingValid(getDirection(),rotation,getFlip());
}
default boolean isNewFlipValid(Flip flip){
return isNewExtendedFacingValid(getDirection(),getRotation(),flip);
}
default boolean isExtendedFacingValid() {
return isNewExtendedFacingValid(getDirection(),getRotation(),getFlip());
}
@Override
default boolean isNewExtendedFacingValid(ForgeDirection direction, Rotation rotation, Flip flip){
return getAlignmentLimits().isNewExtendedFacingValid(direction, rotation, flip);
}
@Override
default boolean isNewExtendedFacingValid(ExtendedFacing alignment){
return getAlignmentLimits().isNewExtendedFacingValid(
alignment.getDirection(),
alignment.getRotation(),
alignment.getFlip());
}
}
@@ -0,0 +1,19 @@
package com.gtnewhorizon.structurelib.alignment;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
import net.minecraftforge.common.util.ForgeDirection;
public interface IAlignmentLimits {
IAlignmentLimits UNLIMITED= (direction, rotation, flip) -> true;
boolean isNewExtendedFacingValid(ForgeDirection direction, Rotation rotation, Flip flip);
default boolean isNewExtendedFacingValid(ExtendedFacing alignment){
return isNewExtendedFacingValid(
alignment.getDirection(),
alignment.getRotation(),
alignment.getFlip());
}
}
@@ -0,0 +1,5 @@
package com.gtnewhorizon.structurelib.alignment;
public interface IAlignmentProvider {
IAlignment getAlignment();
}
@@ -0,0 +1,84 @@
package com.gtnewhorizon.structurelib.alignment;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
import com.gtnewhorizon.structurelib.alignment.enumerable.Direction;
import net.minecraft.util.Vec3;
import net.minecraftforge.common.util.ForgeDirection;
import static java.lang.Math.abs;
public class IntegerAxisSwap {
private final Vec3Impl forFirstAxis;
private final Vec3Impl forSecondAxis;
private final Vec3Impl forThirdAxis;
public IntegerAxisSwap(ForgeDirection forFirstAxis, ForgeDirection forSecondAxis, ForgeDirection forThirdAxis) {
this.forFirstAxis = Direction.getAxisVector(forFirstAxis);
this.forSecondAxis = Direction.getAxisVector(forSecondAxis);
this.forThirdAxis = Direction.getAxisVector(forThirdAxis);
if(abs(this.forFirstAxis.get0())+abs(this.forSecondAxis.get0())+abs(this.forThirdAxis.get0())!=1 ||
abs(this.forFirstAxis.get1())+abs(this.forSecondAxis.get1())+abs(this.forThirdAxis.get1())!=1 ||
abs(this.forFirstAxis.get2())+abs(this.forSecondAxis.get2())+abs(this.forThirdAxis.get2())!=1){
throw new IllegalArgumentException("Axis are overlapping/missing! "+
forFirstAxis.name()+" "+
forSecondAxis.name()+" "+
forThirdAxis.name());
}
}
public Vec3Impl translate(Vec3Impl point){
return new Vec3Impl(
forFirstAxis.get0()*point.get0() +forFirstAxis.get1()*point.get1() +forFirstAxis.get2()*point.get2(),
forSecondAxis.get0()*point.get0()+forSecondAxis.get1()*point.get1()+forSecondAxis.get2()*point.get2(),
forThirdAxis.get0()*point.get0() +forThirdAxis.get1()*point.get1() +forThirdAxis.get2()*point.get2()
);
}
public Vec3Impl inverseTranslate(Vec3Impl point){
return new Vec3Impl(
forFirstAxis.get0()*point.get0()+forSecondAxis.get0()*point.get1()+forThirdAxis.get0()*point.get2(),
forFirstAxis.get1()*point.get0()+forSecondAxis.get1()*point.get1()+forThirdAxis.get1()*point.get2(),
forFirstAxis.get2()*point.get0()+forSecondAxis.get2()*point.get1()+forThirdAxis.get2()*point.get2()
);
}
public Vec3 translate(Vec3 point){
return Vec3.createVectorHelper(
forFirstAxis.get0()*point.xCoord +forFirstAxis.get1()*point.yCoord +forFirstAxis.get2()*point.zCoord,
forSecondAxis.get0()*point.xCoord+forSecondAxis.get1()*point.yCoord+forSecondAxis.get2()*point.zCoord,
forThirdAxis.get0()*point.xCoord +forThirdAxis.get1()*point.yCoord +forThirdAxis.get2()*point.zCoord
);
}
public Vec3 inverseTranslate(Vec3 point){
return Vec3.createVectorHelper(
forFirstAxis.get0()*point.xCoord+forSecondAxis.get0()*point.yCoord+forThirdAxis.get0()*point.zCoord,
forFirstAxis.get1()*point.xCoord+forSecondAxis.get1()*point.yCoord+forThirdAxis.get1()*point.zCoord,
forFirstAxis.get2()*point.xCoord+forSecondAxis.get2()*point.yCoord+forThirdAxis.get2()*point.zCoord
);
}
public void translate(int[] point,int[] out){
out[0]=forFirstAxis.get0()*point[0] +forFirstAxis.get1()*point[1] +forFirstAxis.get2()*point[2];
out[1]=forSecondAxis.get0()*point[0]+forSecondAxis.get1()*point[1]+forSecondAxis.get2()*point[2];
out[2]=forThirdAxis.get0()*point[0] +forThirdAxis.get1()*point[1] +forThirdAxis.get2()*point[2];
}
public void inverseTranslate(int[] point,int[] out){
out[0]=forFirstAxis.get0()*point[0]+forSecondAxis.get0()*point[1]+forThirdAxis.get0()*point[2];
out[1]=forFirstAxis.get1()*point[0]+forSecondAxis.get1()*point[1]+forThirdAxis.get1()*point[2];
out[2]=forFirstAxis.get2()*point[0]+forSecondAxis.get2()*point[1]+forThirdAxis.get2()*point[2];
}
public void translate(double[] point,double[] out){
out[0]=forFirstAxis.get0()*point[0] +forFirstAxis.get1()*point[1] +forFirstAxis.get2()*point[2];
out[1]=forSecondAxis.get0()*point[0]+forSecondAxis.get1()*point[1]+forSecondAxis.get2()*point[2];
out[2]=forThirdAxis.get0()*point[0] +forThirdAxis.get1()*point[1] +forThirdAxis.get2()*point[2];
}
public void inverseTranslate(double[] point,double[] out){
out[0]=forFirstAxis.get0()*point[0]+forSecondAxis.get0()*point[1]+forThirdAxis.get0()*point[2];
out[1]=forFirstAxis.get1()*point[0]+forSecondAxis.get1()*point[1]+forThirdAxis.get1()*point[2];
out[2]=forFirstAxis.get2()*point[0]+forSecondAxis.get2()*point[1]+forThirdAxis.get2()*point[2];
}
}
@@ -0,0 +1,34 @@
package com.gtnewhorizon.structurelib.alignment.enumerable;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
import net.minecraftforge.common.util.ForgeDirection;
public enum Direction {
DOWN(ForgeDirection.DOWN),
UP(ForgeDirection.UP),
NORTH(ForgeDirection.NORTH),
SOUTH(ForgeDirection.SOUTH),
WEST(ForgeDirection.WEST),
EAST(ForgeDirection.EAST);
private final ForgeDirection forgeDirection;
private final Vec3Impl axisVector;
public static final Direction[] VALUES=values();
Direction(ForgeDirection forgeDirection) {
this.forgeDirection = forgeDirection;
axisVector=new Vec3Impl(forgeDirection.offsetX,forgeDirection.offsetY,forgeDirection.offsetZ);
}
public ForgeDirection getForgeDirection() {
return forgeDirection;
}
public Vec3Impl getAxisVector() {
return axisVector;
}
public static Vec3Impl getAxisVector(ForgeDirection forgeDirection){
return VALUES[forgeDirection.ordinal()].axisVector;
}
}
@@ -0,0 +1,358 @@
package com.gtnewhorizon.structurelib.alignment.enumerable;
import com.gtnewhorizon.structurelib.alignment.IAlignment;
import com.gtnewhorizon.structurelib.alignment.IntegerAxisSwap;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
import net.minecraft.util.Vec3;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.*;
import static com.gtnewhorizon.structurelib.alignment.IAlignment.FLIPS_COUNT;
import static com.gtnewhorizon.structurelib.alignment.IAlignment.ROTATIONS_COUNT;
import static java.lang.Math.abs;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;
public enum ExtendedFacing {
DOWN_NORMAL_NONE("down normal none"),
DOWN_NORMAL_HORIZONTAL("down normal horizontal"),
DOWN_NORMAL_VERTICAL("down normal vertical"),
DOWN_NORMAL_BOTH("down normal both"),
DOWN_CLOCKWISE_NONE("down clockwise none"),
DOWN_CLOCKWISE_HORIZONTAL("down clockwise horizontal"),
DOWN_CLOCKWISE_VERTICAL("down clockwise vertical"),
DOWN_CLOCKWISE_BOTH("down clockwise both"),
DOWN_UPSIDE_DOWN_NONE("down upside down none"),
DOWN_UPSIDE_DOWN_HORIZONTAL("down upside down horizontal"),
DOWN_UPSIDE_DOWN_VERTICAL("down upside down vertical"),
DOWN_UPSIDE_DOWN_BOTH("down upside down both"),
DOWN_COUNTER_CLOCKWISE_NONE("down counter clockwise none"),
DOWN_COUNTER_CLOCKWISE_HORIZONTAL("down counter clockwise horizontal"),
DOWN_COUNTER_CLOCKWISE_VERTICAL("down counter clockwise vertical"),
DOWN_COUNTER_CLOCKWISE_BOTH("down counter clockwise both"),
UP_NORMAL_NONE("up normal none"),
UP_NORMAL_HORIZONTAL("up normal horizontal"),
UP_NORMAL_VERTICAL("up normal vertical"),
UP_NORMAL_BOTH("up normal both"),
UP_CLOCKWISE_NONE("up clockwise none"),
UP_CLOCKWISE_HORIZONTAL("up clockwise horizontal"),
UP_CLOCKWISE_VERTICAL("up clockwise vertical"),
UP_CLOCKWISE_BOTH("up clockwise both"),
UP_UPSIDE_DOWN_NONE("up upside down none"),
UP_UPSIDE_DOWN_HORIZONTAL("up upside down horizontal"),
UP_UPSIDE_DOWN_VERTICAL("up upside down vertical"),
UP_UPSIDE_DOWN_BOTH("up upside down both"),
UP_COUNTER_CLOCKWISE_NONE("up counter clockwise none"),
UP_COUNTER_CLOCKWISE_HORIZONTAL("up counter clockwise horizontal"),
UP_COUNTER_CLOCKWISE_VERTICAL("up counter clockwise vertical"),
UP_COUNTER_CLOCKWISE_BOTH("up counter clockwise both"),
NORTH_NORMAL_NONE("north normal none"),
NORTH_NORMAL_HORIZONTAL("north normal horizontal"),
NORTH_NORMAL_VERTICAL("north normal vertical"),
NORTH_NORMAL_BOTH("north normal both"),
NORTH_CLOCKWISE_NONE("north clockwise none"),
NORTH_CLOCKWISE_HORIZONTAL("north clockwise horizontal"),
NORTH_CLOCKWISE_VERTICAL("north clockwise vertical"),
NORTH_CLOCKWISE_BOTH("north clockwise both"),
NORTH_UPSIDE_DOWN_NONE("north upside down none"),
NORTH_UPSIDE_DOWN_HORIZONTAL("north upside down horizontal"),
NORTH_UPSIDE_DOWN_VERTICAL("north upside down vertical"),
NORTH_UPSIDE_DOWN_BOTH("north upside down both"),
NORTH_COUNTER_CLOCKWISE_NONE("north counter clockwise none"),
NORTH_COUNTER_CLOCKWISE_HORIZONTAL("north counter clockwise horizontal"),
NORTH_COUNTER_CLOCKWISE_VERTICAL("north counter clockwise vertical"),
NORTH_COUNTER_CLOCKWISE_BOTH("north counter clockwise both"),
SOUTH_NORMAL_NONE("south normal none"),
SOUTH_NORMAL_HORIZONTAL("south normal horizontal"),
SOUTH_NORMAL_VERTICAL("south normal vertical"),
SOUTH_NORMAL_BOTH("south normal both"),
SOUTH_CLOCKWISE_NONE("south clockwise none"),
SOUTH_CLOCKWISE_HORIZONTAL("south clockwise horizontal"),
SOUTH_CLOCKWISE_VERTICAL("south clockwise vertical"),
SOUTH_CLOCKWISE_BOTH("south clockwise both"),
SOUTH_UPSIDE_DOWN_NONE("south upside down none"),
SOUTH_UPSIDE_DOWN_HORIZONTAL("south upside down horizontal"),
SOUTH_UPSIDE_DOWN_VERTICAL("south upside down vertical"),
SOUTH_UPSIDE_DOWN_BOTH("south upside down both"),
SOUTH_COUNTER_CLOCKWISE_NONE("south counter clockwise none"),
SOUTH_COUNTER_CLOCKWISE_HORIZONTAL("south counter clockwise horizontal"),
SOUTH_COUNTER_CLOCKWISE_VERTICAL("south counter clockwise vertical"),
SOUTH_COUNTER_CLOCKWISE_BOTH("south counter clockwise both"),
WEST_NORMAL_NONE("west normal none"),
WEST_NORMAL_HORIZONTAL("west normal horizontal"),
WEST_NORMAL_VERTICAL("west normal vertical"),
WEST_NORMAL_BOTH("west normal both"),
WEST_CLOCKWISE_NONE("west clockwise none"),
WEST_CLOCKWISE_HORIZONTAL("west clockwise horizontal"),
WEST_CLOCKWISE_VERTICAL("west clockwise vertical"),
WEST_CLOCKWISE_BOTH("west clockwise both"),
WEST_UPSIDE_DOWN_NONE("west upside down none"),
WEST_UPSIDE_DOWN_HORIZONTAL("west upside down horizontal"),
WEST_UPSIDE_DOWN_VERTICAL("west upside down vertical"),
WEST_UPSIDE_DOWN_BOTH("west upside down both"),
WEST_COUNTER_CLOCKWISE_NONE("west counter clockwise none"),
WEST_COUNTER_CLOCKWISE_HORIZONTAL("west counter clockwise horizontal"),
WEST_COUNTER_CLOCKWISE_VERTICAL("west counter clockwise vertical"),
WEST_COUNTER_CLOCKWISE_BOTH("west counter clockwise both"),
EAST_NORMAL_NONE("east normal none"),
EAST_NORMAL_HORIZONTAL("east normal horizontal"),
EAST_NORMAL_VERTICAL("east normal vertical"),
EAST_NORMAL_BOTH("east normal both"),
EAST_CLOCKWISE_NONE("east clockwise none"),
EAST_CLOCKWISE_HORIZONTAL("east clockwise horizontal"),
EAST_CLOCKWISE_VERTICAL("east clockwise vertical"),
EAST_CLOCKWISE_BOTH("east clockwise both"),
EAST_UPSIDE_DOWN_NONE("east upside down none"),
EAST_UPSIDE_DOWN_HORIZONTAL("east upside down horizontal"),
EAST_UPSIDE_DOWN_VERTICAL("east upside down vertical"),
EAST_UPSIDE_DOWN_BOTH("east upside down both"),
EAST_COUNTER_CLOCKWISE_NONE("east counter clockwise none"),
EAST_COUNTER_CLOCKWISE_HORIZONTAL("east counter clockwise horizontal"),
EAST_COUNTER_CLOCKWISE_VERTICAL("east counter clockwise vertical"),
EAST_COUNTER_CLOCKWISE_BOTH("east counter clockwise both");
public static final ExtendedFacing DEFAULT=NORTH_NORMAL_NONE;
public static final ExtendedFacing[] VALUES = values();
public static final Map<ForgeDirection, List<ExtendedFacing>> FOR_FACING=new HashMap<>();
static {
stream(values()).forEach(extendedFacing ->
FOR_FACING.compute(extendedFacing.direction,((forgeDirection, extendedFacings) -> {
if(extendedFacings==null){
extendedFacings = new ArrayList<>();
}
extendedFacings.add(extendedFacing);
return extendedFacings;
})));
}
private static final Map<String, ExtendedFacing> NAME_LOOKUP = stream(VALUES).collect(toMap(ExtendedFacing::getName2, (extendedFacing) -> extendedFacing));
private final ForgeDirection direction;
private final ForgeDirection a,b,c;
private final Rotation rotation;
private final Flip flip;
private final String name;
private final IntegerAxisSwap integerAxisSwap;
ExtendedFacing(String name) {
this.name = name;
direction= Direction.VALUES[ordinal()/(ROTATIONS_COUNT*FLIPS_COUNT)].getForgeDirection();
rotation=Rotation.VALUES[ordinal()/FLIPS_COUNT-direction.ordinal()*ROTATIONS_COUNT];
flip=Flip.VALUES[ordinal()%FLIPS_COUNT];
ForgeDirection a,b,c;
switch (direction){
case DOWN:
a= ForgeDirection.WEST;
b= ForgeDirection.SOUTH;
c= ForgeDirection.UP;
break;
case UP:
a= ForgeDirection.EAST;
b= ForgeDirection.SOUTH;
c= ForgeDirection.DOWN;
break;
case NORTH:
a= ForgeDirection.WEST;
b= ForgeDirection.DOWN;
c= ForgeDirection.SOUTH;
break;
case SOUTH:
a= ForgeDirection.EAST;
b= ForgeDirection.DOWN;
c= ForgeDirection.NORTH;
break;
case WEST:
a= ForgeDirection.SOUTH;
b= ForgeDirection.DOWN;
c= ForgeDirection.EAST;
break;
case EAST:
a= ForgeDirection.NORTH;
b= ForgeDirection.DOWN;
c= ForgeDirection.WEST;
break;
default:throw new RuntimeException("Is impossible...");
}
switch (flip){//This duplicates some axis swaps since flip boolean would do, but seems more convenient to use
case HORIZONTAL:
a=a.getOpposite();
break;
case BOTH:
a=a.getOpposite();
case VERTICAL:
b=b.getOpposite();
break;
case NONE: break;
default:throw new RuntimeException("Even more impossible...");
}
switch (rotation) {
case CLOCKWISE: {
ForgeDirection _a=a;
a =b;
b =_a.getOpposite();
break;
}
case UPSIDE_DOWN:
a=a.getOpposite();
b=b.getOpposite();
break;
case COUNTER_CLOCKWISE: {
ForgeDirection _a=a;
a =b.getOpposite();
b =_a;
break;
}
case NORMAL: break;
default:
throw new RuntimeException("More impossible...");
}
this.a=a;
this.b=b;
this.c=c;
integerAxisSwap =new IntegerAxisSwap(a,b,c);
}
public static ExtendedFacing of(ForgeDirection direction, Rotation rotation, Flip flip){
if(direction==ForgeDirection.UNKNOWN){
return VALUES[IAlignment.getAlignmentIndex(ForgeDirection.NORTH, rotation, flip)];
}
return VALUES[IAlignment.getAlignmentIndex(direction, rotation, flip)];
}
public static ExtendedFacing of(ForgeDirection direction){
if(direction==ForgeDirection.UNKNOWN){
return DEFAULT;
}
return VALUES[IAlignment.getAlignmentIndex(direction, Rotation.NORMAL, Flip.NONE)];
}
public ExtendedFacing with(ForgeDirection direction){
return of(direction,rotation,flip);
}
public ExtendedFacing with(Rotation rotation){
return of(direction,rotation,flip);
}
public ExtendedFacing with(Flip flip){
return of(direction,rotation,flip);
}
public ExtendedFacing getOppositeDirection() {
return of(direction.getOpposite(),rotation,flip);
}
public ExtendedFacing getOppositeRotation() {
return of(direction,rotation.getOpposite(),flip);
}
public ExtendedFacing getOppositeFlip() {
return of(direction,rotation,flip.getOpposite());
}
/**
* Gets the same effective facing achieved by different rot/flip combo
* @return same effective facing, but different enum value
*/
public ExtendedFacing getDuplicate(){
return of(direction,rotation.getOpposite(),flip.getOpposite());
}
public int getIndex(){
return ordinal();
}
public String getName2() {
return this.name;
}
public static ExtendedFacing byName(String name) {
return name == null ? null : NAME_LOOKUP.get(name.toLowerCase(Locale.ROOT));
}
public static ExtendedFacing byIndex(int index) {
return VALUES[abs(index % VALUES.length)];
}
public static ExtendedFacing random(Random rand) {
return VALUES[rand.nextInt(VALUES.length)];
}
public ForgeDirection getDirection() {
return direction;
}
public Rotation getRotation() {
return rotation;
}
public Flip getFlip() {
return flip;
}
/**
* Translates relative to front facing offset to world offset
* @param abcOffset A,B,C offset (facing relative L-->R,U-->D,F-->B)
* @return X,Y,Z offset in world
*/
public Vec3 getWorldOffset(Vec3 abcOffset) {
return integerAxisSwap.inverseTranslate(abcOffset);
}
public Vec3Impl getWorldOffset(Vec3Impl abcOffset) {
return integerAxisSwap.inverseTranslate(abcOffset);
}
public void getWorldOffset(int[] point,int[] out){
integerAxisSwap.inverseTranslate(point,out);
}
public void getWorldOffset(double[] point,double[] out){
integerAxisSwap.inverseTranslate(point,out);
}
/**
* Translates world offset to relative front facing offset
* @param xyzOffset X,Y,Z offset in world
* @return A,B,C offset (facing relative L-->R,U-->D,F-->B)
*/
public Vec3 getOffsetABC(Vec3 xyzOffset){
return integerAxisSwap.translate(xyzOffset);
}
public Vec3Impl getOffsetABC(Vec3Impl xyzOffset){
return integerAxisSwap.translate(xyzOffset);
}
public void getOffsetABC(int[] point,int[] out){
integerAxisSwap.translate(point,out);
}
public void getOffsetABC(double[] point,double[] out){
integerAxisSwap.translate(point,out);
}
public IntegerAxisSwap getIntegerAxisSwap() {
return integerAxisSwap;
}
public ForgeDirection getRelativeLeftInWorld() {
return a;
}
public ForgeDirection getRelativeRightInWorld() {
return a.getOpposite();
}
public ForgeDirection getRelativeDownInWorld() {
return b;
}
public ForgeDirection getRelativeUpInWorld() {
return b.getOpposite();
}
public ForgeDirection getRelativeBackInWorld() {
return c;
}
public ForgeDirection getRelativeForwardInWorld() {
return c.getOpposite();
}
}
@@ -0,0 +1,76 @@
package com.gtnewhorizon.structurelib.alignment.enumerable;
import javax.annotation.Nonnull;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import static java.lang.Math.abs;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;
public enum Flip {
NONE(3, "none"),
HORIZONTAL(2, "horizontal"),
VERTICAL(1, "vertical"),
BOTH(0, "both");
private final int opposite;
private final String name;
public static final Flip[] VALUES = values();
private static final Map<String, Flip> NAME_LOOKUP = stream(VALUES).collect(toMap(Flip::getName2, (flip) -> flip));
Flip(int oppositeIn, String nameIn) {
this.opposite = oppositeIn;
this.name = nameIn;
}
public int getIndex(){
return ordinal();
}
public Flip getOpposite() {
return VALUES[opposite];
}
public String getName2() {
return this.name;
}
public static Flip byName(String name) {
return name == null ? null : NAME_LOOKUP.get(name.toLowerCase(Locale.ROOT));
}
public static Flip byIndex(int index) {
return VALUES[abs(index % VALUES.length)];
}
public static Flip random(@Nonnull Random rand) {
return VALUES[rand.nextInt(VALUES.length)];
}
public String toString() {
return this.name;
}
public String getName() {
return this.name;
}
public boolean isNotFlipped(){
return this==NONE;
}
public boolean isBothFlipped(){
return this==BOTH;
}
public boolean isHorizontallyFlipped() {
return this==HORIZONTAL || isBothFlipped();
}
public boolean isVerticallyFliped() {
return this==VERTICAL || isBothFlipped();
}
}
@@ -0,0 +1,76 @@
package com.gtnewhorizon.structurelib.alignment.enumerable;
import javax.annotation.Nonnull;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import static java.lang.Math.abs;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;
public enum Rotation {
NORMAL(2, "normal"),
CLOCKWISE(3, "clockwise"),
UPSIDE_DOWN(0, "upside down"),
COUNTER_CLOCKWISE(1, "counter clockwise");
private final int opposite;
private final String name;
public static final Rotation[] VALUES = values();
private static final Map<String, Rotation> NAME_LOOKUP = stream(VALUES).collect(toMap(Rotation::getName2, (rotation) -> rotation));
Rotation(int oppositeIn, String nameIn) {
this.opposite = oppositeIn;
this.name = nameIn;
}
public int getIndex(){
return ordinal();
}
public Rotation getOpposite() {
return VALUES[opposite];
}
public String getName2() {
return this.name;
}
public static Rotation byName(String name) {
return name == null ? null : NAME_LOOKUP.get(name.toLowerCase(Locale.ROOT));
}
public static Rotation byIndex(int index) {
return VALUES[abs(index % VALUES.length)];
}
public static Rotation random(@Nonnull Random rand) {
return VALUES[rand.nextInt(VALUES.length)];
}
public String toString() {
return this.name;
}
public String getName() {
return this.name;
}
public boolean isNotRotated(){
return this==NORMAL;
}
public boolean isClockwise(){
return this==CLOCKWISE;
}
public boolean isCounterClockwise(){
return this==COUNTER_CLOCKWISE;
}
public boolean isUpsideDown(){
return this==UPSIDE_DOWN;
}
}
@@ -0,0 +1,133 @@
package com.gtnewhorizon.structurelib.entity.fx;
import com.gtnewhorizon.structurelib.StructureLib;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.init.Blocks;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
public class BlockHint extends EntityFX {
private IIcon[] icons;
private short[] mRGBa = {255,255,255,0};
public BlockHint(World world){
this(world,0,0,0, Blocks.stone,0);
}
/**
*
* @param world
* @param x
* @param y
* @param z
* @param icons DOWN, UP, NORTH, SOUTH, WEST, EAST
*/
public BlockHint(World world, int x, int y, int z, IIcon[] icons) {
super(world, x + .25, y + .5, z + .25);
particleGravity = 0;
prevPosX = posX;
prevPosY = posY;
prevPosZ = posZ;
noClip = true;
particleMaxAge = 2000 + StructureLib.RANDOM.nextInt(200);
this.icons=icons;
}
public BlockHint(World world, int x, int y, int z, Block block, int meta) {
super(world, x+.25, y+.5, z+.25);
particleGravity = 0;
prevPosX = posX;
prevPosY = posY;
prevPosZ = posZ;
noClip = true;
particleMaxAge = 2000 + StructureLib.RANDOM.nextInt(200);
icons = new IIcon[6];
for (int i = 0; i < 6; i++) {
icons[i] = block.getIcon(i, meta);
}
}
public BlockHint withColorTint(short[] coloure){
this.mRGBa =coloure;
return this;
}
@Override
public void renderParticle(Tessellator tes, float subTickTime, float p_70539_3_, float p_70539_4_, float p_70539_5_, float p_70539_6_, float p_70539_7_) {
float size = .5f;
float X = (float) (prevPosX + (posX - prevPosX) * (double) subTickTime - EntityFX.interpPosX);
float Y = (float) (prevPosY + (posY - prevPosY) * (double) subTickTime - EntityFX.interpPosY) - size / 2;
float Z = (float) (prevPosZ + (posZ - prevPosZ) * (double) subTickTime - EntityFX.interpPosZ);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDepthMask(false);
tes.setColorRGBA((int) (mRGBa[0] * .9F), (int) (mRGBa[1] * .95F), (int) (mRGBa[2] * 1F), 192);
//var8, var9 - X U
//var 10, var 11 - Y V
for(int i=0;i<6;i++){
if(icons[i]==null) {
continue;
}
double u=icons[i].getMinU();
double U=icons[i].getMaxU();
double v=icons[i].getMinV();
double V=icons[i].getMaxV();
switch (i){//{DOWN, UP, NORTH, SOUTH, WEST, EAST}
case 0:
tes.addVertexWithUV(X, Y, Z + size, u, V);
tes.addVertexWithUV(X, Y, Z, u, v);
tes.addVertexWithUV(X + size, Y, Z, U, v);
tes.addVertexWithUV(X + size, Y, Z + size, U, V);
break;
case 1:
tes.addVertexWithUV(X, Y + size, Z, u, v);
tes.addVertexWithUV(X, Y + size, Z + size, u, V);
tes.addVertexWithUV(X + size, Y + size, Z + size, U, V);
tes.addVertexWithUV(X + size, Y + size, Z, U, v);
break;
case 2:
tes.addVertexWithUV(X, Y, Z, U, V);
tes.addVertexWithUV(X, Y + size, Z, U, v);
tes.addVertexWithUV(X + size, Y + size, Z, u, v);
tes.addVertexWithUV(X + size, Y, Z, u, V);
break;
case 3:
tes.addVertexWithUV(X + size, Y, Z + size, U, V);
tes.addVertexWithUV(X + size, Y + size, Z + size, U, v);
tes.addVertexWithUV(X, Y + size, Z + size, u, v);
tes.addVertexWithUV(X, Y, Z + size, u, V);
break;
case 4:
tes.addVertexWithUV(X, Y, Z + size, U, V);
tes.addVertexWithUV(X, Y + size, Z + size, U, v);
tes.addVertexWithUV(X, Y + size, Z, u, v);
tes.addVertexWithUV(X, Y, Z, u, V);
break;
case 5:
tes.addVertexWithUV(X + size, Y, Z, U, V);
tes.addVertexWithUV(X + size, Y + size, Z, U, v);
tes.addVertexWithUV(X + size, Y + size, Z + size, u, v);
tes.addVertexWithUV(X + size, Y, Z + size, u, V);
break;
}
}
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glDepthMask(true);
}
@Override
public int getFXLayer() {
return 1;
}
@Override
public boolean shouldRenderInPass(int pass) {
return pass==2;
}
}
@@ -0,0 +1,44 @@
package com.gtnewhorizon.structurelib.entity.fx;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class WeightlessParticleFX extends EntityFX
{
public WeightlessParticleFX(World p_i1205_1_, double p_i1205_2_, double p_i1205_4_, double p_i1205_6_, double p_i1205_8_, double p_i1205_10_, double p_i1205_12_)
{
super(p_i1205_1_, p_i1205_2_, p_i1205_4_, p_i1205_6_, p_i1205_8_, p_i1205_10_, p_i1205_12_);
this.motionX = p_i1205_8_ + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.05F);
this.motionY = p_i1205_10_ + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.05F);
this.motionZ = p_i1205_12_ + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.05F);
this.particleRed = this.particleGreen = this.particleBlue = this.rand.nextFloat() * 0.3F + 0.7F;
this.particleScale = this.rand.nextFloat() * this.rand.nextFloat() * 6.0F + 1.0F;
this.particleMaxAge = (int)(16.0D / ((double)this.rand.nextFloat() * 0.8D + 0.2D)) + 2;
this.noClip=true;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
this.setParticleTextureIndex(7 - this.particleAge * 8 / this.particleMaxAge);
//this.motionY += 0.004D;
this.moveEntity(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.8999999761581421D;
this.motionY *= 0.8999999761581421D;
this.motionZ *= 0.8999999761581421D;
}
}
@@ -0,0 +1,43 @@
package com.gtnewhorizon.structurelib.proxy;
import com.gtnewhorizon.structurelib.entity.fx.BlockHint;
import com.gtnewhorizon.structurelib.entity.fx.WeightlessParticleFX;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import static com.gtnewhorizon.structurelib.StructureLib.RANDOM;
public class ClientProxy extends CommonProxy {
@Override
public void hint_particle_tinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
Minecraft.getMinecraft().effectRenderer.addEffect(new BlockHint(w, x, y, z, icons).withColorTint(RGBa));
createParticleFX(w, x, y, z);
}
@Override
public void hint_particle_tinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa) {
Minecraft.getMinecraft().effectRenderer.addEffect(new BlockHint(w, x, y, z, block, meta).withColorTint(RGBa));
createParticleFX(w, x, y, z);
}
@Override
public void hint_particle(World w, int x, int y, int z, IIcon[] icons) {
Minecraft.getMinecraft().effectRenderer.addEffect(new BlockHint(w, x, y, z, icons));
createParticleFX(w, x, y, z);
}
@Override
public void hint_particle(World w, int x, int y, int z, Block block, int meta) {
Minecraft.getMinecraft().effectRenderer.addEffect(new BlockHint(w, x, y, z, block, meta));
createParticleFX(w, x, y, z);
}
private static void createParticleFX(World w, int x, int y, int z) {
EntityFX particle = new WeightlessParticleFX(w, x + RANDOM.nextFloat() * 0.5F, y + RANDOM.nextFloat() * 0.5F, z + RANDOM.nextFloat() * 0.5F, 0, 0, 0);
particle.setRBGColorF(0, 0.6F * RANDOM.nextFloat(), 0.8f);
Minecraft.getMinecraft().effectRenderer.addEffect(particle);
}
}
@@ -0,0 +1,12 @@
package com.gtnewhorizon.structurelib.proxy;
import net.minecraft.block.Block;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
public class CommonProxy {
public void hint_particle_tinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa){}
public void hint_particle_tinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa){}
public void hint_particle(World w,int x, int y, int z, IIcon[] icons){}
public void hint_particle(World w,int x, int y, int z, Block block, int meta){}
}
@@ -0,0 +1,7 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.world.World;
public interface IBlockPosConsumer {
void consume(World world, int x, int y, int z);
}
@@ -0,0 +1,18 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.block.Block;
import net.minecraft.world.World;
public interface ICustomBlockSetting {
/**
* Default block setting calls {@link World#setBlock(int x, int y, int z, Block block, int meta, int updateType)} like:
* {@code world.setBlock(x,y,z,this/block,meta,2)} where updateType 2 means to update lighting and stuff
*
* @param world world that should be affected
* @param x x position to set
* @param y y position to set
* @param z z position to set
* @param meta required meta
*/
void setBlock(World world, int x, int y, int z, int meta);
}
@@ -0,0 +1,168 @@
package com.gtnewhorizon.structurelib.structure;
import com.gtnewhorizon.structurelib.StructureLib;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import java.util.Arrays;
import static com.gtnewhorizon.structurelib.StructureLib.DEBUG_MODE;
public interface IStructureDefinition<T> {
/**
* Used internally
*
* @param name same name as for other methods here
* @return the array of elements to process
*/
IStructureElement<T>[] getStructureFor(String name);
default boolean check(T object, String piece, World world, ExtendedFacing extendedFacing,
int basePositionX, int basePositionY, int basePositionZ,
int basePositionA, int basePositionB, int basePositionC,
boolean forceCheckAllBlocks) {
return iterate(object, null, getStructureFor(piece), world, extendedFacing, basePositionX, basePositionY, basePositionZ,
basePositionA, basePositionB, basePositionC, false, forceCheckAllBlocks);
}
default boolean hints(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
int basePositionX, int basePositionY, int basePositionZ,
int basePositionA, int basePositionB, int basePositionC) {
return iterate(object, trigger, getStructureFor(piece), world, extendedFacing, basePositionX, basePositionY, basePositionZ,
basePositionA, basePositionB, basePositionC, true, null);
}
default boolean build(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
int basePositionX, int basePositionY, int basePositionZ,
int basePositionA, int basePositionB, int basePositionC) {
return iterate(object, trigger, getStructureFor(piece), world, extendedFacing, basePositionX, basePositionY, basePositionZ,
basePositionA, basePositionB, basePositionC, false, null);
}
default boolean buildOrHints(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
int basePositionX, int basePositionY, int basePositionZ,
int basePositionA, int basePositionB, int basePositionC,
boolean hintsOnly) {
return iterate(object, trigger, getStructureFor(piece), world, extendedFacing, basePositionX, basePositionY, basePositionZ,
basePositionA, basePositionB, basePositionC, hintsOnly, null);
}
static <T> boolean iterate(T object, ItemStack trigger, IStructureElement<T>[] elements, World world, ExtendedFacing extendedFacing,
int basePositionX, int basePositionY, int basePositionZ,
int basePositionA, int basePositionB, int basePositionC,
boolean hintsOnly, Boolean checkBlocksIfNotNullForceCheckAllIfTrue) {
if (world.isRemote ^ hintsOnly) {
return false;
}
//change base position to base offset
basePositionA = -basePositionA;
basePositionB = -basePositionB;
basePositionC = -basePositionC;
int[] abc = new int[]{basePositionA, basePositionB, basePositionC};
int[] xyz = new int[3];
if (checkBlocksIfNotNullForceCheckAllIfTrue != null) {
if (checkBlocksIfNotNullForceCheckAllIfTrue) {
for (IStructureElement<T> element : elements) {
if (element.isNavigating()) {
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
} else {
extendedFacing.getWorldOffset(abc, xyz);
xyz[0] += basePositionX;
xyz[1] += basePositionY;
xyz[2] += basePositionZ;
if (world.blockExists(xyz[0], xyz[1], xyz[2])) {
if (!element.check(object, world, xyz[0], xyz[1], xyz[2])) {
if (DEBUG_MODE) {
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] failed @ " +
Arrays.toString(xyz) + " " + Arrays.toString(abc));
}
return false;
}
} else {
if (DEBUG_MODE) {
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] !blockExists @ " +
Arrays.toString(xyz) + " " + Arrays.toString(abc));
}
return false;
}
abc[0] += 1;
}
}
} else {
for (IStructureElement<T> element : elements) {
if (element.isNavigating()) {
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
} else {
extendedFacing.getWorldOffset(abc, xyz);
xyz[0] += basePositionX;
xyz[1] += basePositionY;
xyz[2] += basePositionZ;
if (world.blockExists(xyz[0], xyz[1], xyz[2])) {
if (!element.check(object, world, xyz[0], xyz[1], xyz[2])) {
if (DEBUG_MODE) {
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] failed @ " +
Arrays.toString(xyz) + " " + Arrays.toString(abc));
}
return false;
}
} else {
if (DEBUG_MODE) {
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] !blockExists @ " +
Arrays.toString(xyz) + " " + Arrays.toString(abc));
}
}
abc[0] += 1;
}
}
}
} else {
if (hintsOnly) {
for (IStructureElement<T> element : elements) {
if (element.isNavigating()) {
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
} else {
extendedFacing.getWorldOffset(abc, xyz);
xyz[0] += basePositionX;
xyz[1] += basePositionY;
xyz[2] += basePositionZ;
element.spawnHint(object, world, xyz[0], xyz[1], xyz[2], trigger);
abc[0] += 1;
}
}
} else {
for (IStructureElement<T> element : elements) {
if (element.isNavigating()) {
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
} else {
extendedFacing.getWorldOffset(abc, xyz);
xyz[0] += basePositionX;
xyz[1] += basePositionY;
xyz[2] += basePositionZ;
if (world.blockExists(xyz[0], xyz[1], xyz[2])) {
element.placeBlock(object, world, xyz[0], xyz[1], xyz[2], trigger);
}
abc[0] += 1;
}
}
}
}
return true;
}
}
@@ -0,0 +1,43 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
/**
* Use StructureUtility to instantiate
*/
public interface IStructureElement<T> {
boolean check(T t, World world, int x, int y, int z);
boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger);
boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger);
default int getStepA() {
return 1;
}
default int getStepB() {
return 0;
}
default int getStepC() {
return 0;
}
default boolean resetA() {
return false;
}
default boolean resetB() {
return false;
}
default boolean resetC() {
return false;
}
default boolean isNavigating() {
return false;
}
}
@@ -0,0 +1,41 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
/**
* Use StructureUtility to instantiate
*/
public interface IStructureElementChain<T> extends IStructureElement<T> {
IStructureElement<T>[] fallbacks();
@Override
default boolean check(T t, World world, int x, int y, int z) {
for (IStructureElement<T> fallback : fallbacks()) {
if (fallback.check(t, world, x, y, z)) {
return true;
}
}
return false;
}
@Override
default boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
for (IStructureElement<T> fallback : fallbacks()) {
if (fallback.spawnHint(t, world, x, y, z, trigger)) {
return true;
}
}
return false;
}
@Override
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
for (IStructureElement<T> fallback : fallbacks()) {
if (fallback.placeBlock(t, world, x, y, z, trigger)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,16 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public interface IStructureElementCheckOnly<T> extends IStructureElement<T> {
@Override
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return false;
}
@Override
default boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return false;
}
}
@@ -0,0 +1,7 @@
package com.gtnewhorizon.structurelib.structure;
/**
* Use StructureUtility to instantiate
*/
public interface IStructureElementDeferred<T> extends IStructureElement<T> {
}
@@ -0,0 +1,11 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public interface IStructureElementNoPlacement<T> extends IStructureElement<T> {
@Override
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return false;
}
}
@@ -0,0 +1,28 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
/**
* Use StructureUtility to instantiate
*/
interface IStructureNavigate<T> extends IStructureElement<T> {
@Override
default boolean check(T t, World world, int x, int y, int z) {
return true;
}
@Override
default boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return true;
}
@Override
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return true;
}
default boolean isNavigating() {
return true;
}
}
@@ -0,0 +1,211 @@
package com.gtnewhorizon.structurelib.structure;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
import java.util.*;
import static com.gtnewhorizon.structurelib.StructureLib.DEBUG_MODE;
import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
public class StructureDefinition<T> implements IStructureDefinition<T> {
private final Map<Character, IStructureElement<T>> elements;
private final Map<String, String> shapes;
private final Map<String, IStructureElement<T>[]> structures;
public static <B> Builder<B> builder() {
return new Builder<>();
}
private StructureDefinition(
Map<Character, IStructureElement<T>> elements,
Map<String, String> shapes,
Map<String, IStructureElement<T>[]> structures) {
this.elements = elements;
this.shapes = shapes;
this.structures = structures;
}
public static class Builder<T> {
private static final char A = '\uA000';
private static final char B = '\uB000';
private static final char C = '\uC000';
private char d = '\uD000';
private final Map<Vec3Impl, Character> navigates;
private final Map<Character, IStructureElement<T>> elements;
private final Map<String, String> shapes;
private Builder() {
navigates = new HashMap<>();
elements = new HashMap<>();
shapes = new HashMap<>();
}
public Map<Character, IStructureElement<T>> getElements() {
return elements;
}
public Map<String, String> getShapes() {
return shapes;
}
/**
* Adds shape
* +- is air/no air checks
* space bar is skip
* ~ is also skip (but marks controller position, optional and logically it is a space...)
* rest needs to be defined
* <p>
* next char is next block(a)
* next string is next line(b)
* next string[] is next slice(c)
* <p>
* char A000-FFFF range is reserved for generated skips
*
* @param name unlocalized/code name
* @param structurePiece generated or written struct - DO NOT STORE IT ANYWHERE, or at least set them to null afterwards
* @return this builder
*/
public Builder<T> addShape(String name, String[][] structurePiece) {
StringBuilder builder = new StringBuilder();
if (structurePiece.length > 0) {
for (String[] strings : structurePiece) {
if (strings.length > 0) {
for (String string : strings) {
builder.append(string).append(B);
}
builder.setLength(builder.length() - 1);
}
builder.append(C);
}
builder.setLength(builder.length() - 1);
}
int a = 0, b = 0, c = 0;
for (int i = 0; i < builder.length(); i++) {
char ch = builder.charAt(i);
if (ch == ' ' || ch == '~') {
builder.setCharAt(i, A);
ch = A;
}
if (ch == A) {
a++;
} else if (ch == B) {
a = 0;
b++;
} else if (ch == C) {
a = 0;
b = 0;
c++;
} else if (a != 0 || b != 0 || c != 0) {
Vec3Impl vec3 = new Vec3Impl(a, b, c);
Character navigate = navigates.get(vec3);
if (navigate == null) {
navigate = d++;
navigates.put(vec3, navigate);
addElement(navigate, step(vec3));
}
builder.setCharAt(i - 1, navigate);
a = 0;
b = 0;
c = 0;
}
}
String built = builder.toString().replaceAll("[\\uA000\\uB000\\uC000]", "");
if (built.contains("+")) {
addElement('+', notAir());
}
if (built.contains("-")) {
addElement('-', isAir());
}
shapes.put(name, built);
return this;
}
public Builder<T> addElement(Character name, IStructureElement<T> structurePiece) {
elements.putIfAbsent(name, structurePiece);
return this;
}
public IStructureDefinition<T> build() {
Map<String, IStructureElement<T>[]> structures = compileStructureMap();
if (DEBUG_MODE) {
return new StructureDefinition<>(new HashMap<>(elements), new HashMap<>(shapes), structures);
} else {
return structures::get;
}
}
@SuppressWarnings("unchecked")
private Map<String, IStructureElement<T>[]> compileElementSetMap() {
Set<Integer> missing = new HashSet<>();
shapes.values().stream().map(CharSequence::chars).forEach(intStream -> intStream.forEach(c -> {
IStructureElement<T> iStructureElement = elements.get((char) c);
if (iStructureElement == null) {
missing.add(c);
}
}));
if (missing.isEmpty()) {
Map<String, IStructureElement<T>[]> map = new HashMap<>();
shapes.forEach((key, value) -> {
Set<Character> chars = new HashSet<>();
for (char c : value.toCharArray()) {
chars.add(c);
}
IStructureElement<T>[] compiled = new IStructureElement[chars.size()];
int i = 0;
for (Character aChar : chars) {
compiled[i++] = elements.get(aChar);
}
map.put(key, compiled);
});
return map;
} else {
throw new RuntimeException("Missing Structure Element bindings for (chars as integers): " +
Arrays.toString(missing.toArray()));
}
}
@SuppressWarnings("unchecked")
private Map<String, IStructureElement<T>[]> compileStructureMap() {
Set<Integer> mising = new HashSet<>();
shapes.values().stream().map(CharSequence::chars).forEach(intStream -> intStream.forEach(c -> {
IStructureElement<T> iStructureElement = elements.get((char) c);
if (iStructureElement == null) {
mising.add(c);
}
}));
if (mising.isEmpty()) {
Map<String, IStructureElement<T>[]> map = new HashMap<>();
shapes.forEach((key, value) -> {
IStructureElement<T>[] compiled = new IStructureElement[value.length()];
for (int i = 0; i < value.length(); i++) {
compiled[i] = elements.get(value.charAt(i));
}
map.put(key, compiled);
});
return map;
} else {
throw new RuntimeException("Missing Structure Element bindings for (chars as integers): " +
Arrays.toString(mising.toArray()));
}
}
}
public Map<Character, IStructureElement<T>> getElements() {
return elements;
}
public Map<String, String> getShapes() {
return shapes;
}
public Map<String, IStructureElement<T>[]> getStructures() {
return structures;
}
@Override
public IStructureElement<T>[] getStructureFor(String name) {
return structures.get(name);
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,15 @@
package com.gtnewhorizon.structurelib.structure.adders;
import net.minecraft.block.Block;
public interface IBlockAdder<T> {
/**
* Callback on block added, needs to check if block is valid (and add it)
*
* @param block block attempted to add
* @param meta meta of block attempted to add
* @return is structure still valid
*/
boolean apply(T t, Block block, Integer meta);
}
@@ -0,0 +1,13 @@
package com.gtnewhorizon.structurelib.structure.adders;
import net.minecraft.tileentity.TileEntity;
public interface ITileAdder<T> {
/**
* Callback to add hatch, needs to check if tile is valid (and add it)
*
* @param tileEntity tile
* @return managed to add hatch (structure still valid)
*/
boolean apply(T t, TileEntity tileEntity);
}
@@ -0,0 +1,133 @@
package com.gtnewhorizon.structurelib.util;
import net.minecraft.dispenser.IPosition;
import net.minecraftforge.common.util.ForgeDirection;
public class Vec3Impl implements Comparable<Vec3Impl> {
public static final Vec3Impl NULL_VECTOR = new Vec3Impl(0, 0, 0);
private final int val0;
private final int val1;
private final int val2;
public Vec3Impl(int in0, int in1, int in2) {
this.val0 = in0;
this.val1 = in1;
this.val2 = in2;
}
public int compareTo(Vec3Impl o) {
return val1 == o.val1 ? val2 == o.val2 ? val0 - o.val0 : val2 - o.val2 : val1 - o.val1;
}
/**
* Gets the coordinate.
*/
public int get(int index) {
switch (index){
case 0: return val0;
case 1: return val1;
case 2: return val2;
default: return 0;
}
}
/**
* Gets the X coordinate.
*/
public int get0() {
return this.val0;
}
/**
* Gets the Y coordinate.
*/
public int get1() {
return this.val1;
}
/**
* Gets the Z coordinate.
*/
public int get2() {
return this.val2;
}
public Vec3Impl offset(ForgeDirection facing, int n) {
return n == 0 ? this : new Vec3Impl(val0 + facing.offsetX * n, val1 + facing.offsetY * n, val2 + facing.offsetZ * n);
}
public Vec3Impl add(Vec3Impl pos) {
return new Vec3Impl(val0 + pos.val0, val1 + pos.val1, val2 + pos.val2);
}
public Vec3Impl sub(Vec3Impl pos) {
return new Vec3Impl(val0 - pos.val0, val1 - pos.val1, val2 - pos.val2);
}
public Vec3Impl add(int pos0,int pos1,int pos2) {
return new Vec3Impl(val0 + pos0, val1 + pos1, val2 + pos2);
}
public Vec3Impl sub(int pos0,int pos1,int pos2) {
return new Vec3Impl(val0 - pos0, val1 - pos1, val2 - pos2);
}
public Vec3Impl crossProduct(Vec3Impl vec) {
return new Vec3Impl(val1 * vec.val2 - val2 * vec.val1, val2 * vec.val0 - val0 * vec.val2,
val0 * vec.val1 - val1 * vec.val0);
}
public boolean withinDistance(Vec3Impl to, double distance) {
return this.distanceSq(to.val0, to.val1, to.val2, false) < distance * distance;
}
public boolean withinDistance(IPosition to, double distance) {
return this.distanceSq(to.getX(), to.getY(), to.getZ(), true) < distance * distance;
}
public double distanceSq(Vec3Impl to) {
return this.distanceSq(to.val0, to.val1, to.val2, true);
}
public double distanceSq(IPosition to, boolean useCenter) {
return this.distanceSq(to.getX(), to.getY(), to.getZ(), useCenter);
}
public double distanceSq(double x, double y, double z, boolean useCenter) {
double d0 = useCenter ? 0.5D : 0.0D;
double d1 = (double)val0 + d0 - x;
double d2 = (double)val1 + d0 - y;
double d3 = (double)val2 + d0 - z;
return d1 * d1 + d2 * d2 + d3 * d3;
}
public int manhattanDistance(Vec3Impl to) {
float f = (float)Math.abs(to.val0 - val0);
float f1 = (float)Math.abs(to.val1 - val1);
float f2 = (float)Math.abs(to.val2 - val2);
return (int)(f + f1 + f2);
}
@Override
public String toString() {
return "Vec3[" + val0 + ", " + val1 + ", " + val2 + "]";
}
public Vec3Impl abs() {
return new Vec3Impl(Math.abs(val0),Math.abs(val1),Math.abs(val2));
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o instanceof Vec3Impl) {
Vec3Impl vec3i = (Vec3Impl)o;
return val0 == vec3i.val0 && val1 == vec3i.val1 && val2 == vec3i.val2;
}
return false;
}
public int hashCode() {
return (val1 + val2 * 31) * 31 + val0;
}
}
@@ -0,0 +1,278 @@
package com.gtnewhorizon.structurelib.util;
/*
A subclass of java.util.random that implements the Xorshift random number
generator
<p>
- it is 30% faster than the generator from Java's library - it produces
random sequences of higher quality than java.util.Random - this class also
provides a clone() function
<p>
Usage: XSRandom rand = new XSRandom(); //Instantiation x = rand.nextInt();
//pull a random number
<p>
To use the class in legacy code, you may also instantiate an XSRandom object
and assign it to a java.util.Random object: java.util.Random rand = new
XSRandom();
<p>
for an explanation of the algorithm, see
http://demesos.blogspot.com/2011/09/pseudo-random-number-generators.html
@author Wilfried Elmenreich University of Klagenfurt/Lakeside Labs
* http://www.elmenreich.tk
* <p>
* This code is released under the GNU Lesser General Public License Version 3
* http://www.gnu.org/licenses/lgpl-3.0.txt
*/
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
/**
* XSTR - Xorshift ThermiteRandom
* Modified by Bogdan-G
* 03.06.2016
* version 0.0.4
*/
public class XSTR extends Random {
private static final long serialVersionUID = 6208727693524452904L;
private long seed;
private static final long GAMMA = 0x9e3779b97f4a7c15L;
private static final int PROBE_INCREMENT = 0x9e3779b9;
private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);
public static final XSTR XSTR_INSTANCE=new XSTR(){
@Override
public synchronized void setSeed(long seed) {
if(!Thread.currentThread().getStackTrace()[2].getClassName().equals(Random.class.getName())) {
throw new NoSuchMethodError("This is meant to be shared!, leave seed state alone!");
}
}
};
/*
MODIFIED BY: Robotia
Modification: Implemented Random class seed generator
*/
/**
* Creates a new pseudo random number generator. The seed is initialized to
* the current time, as if by
* <code>setSeed(System.currentTimeMillis());</code>.
*/
public XSTR() {
this(seedUniquifier() ^ System.nanoTime());
}
private static long seedUniquifier() {
// L'Ecuyer, "Tables of Linear Congruential Generators of
// Different Sizes and Good Lattice Structure", 1999
while (true) {
long current = seedUniquifier.get();
long next = current * 181783497276652981L;
if (seedUniquifier.compareAndSet(current, next)) {
return next;
}
}
}
/**
* Creates a new pseudo random number generator, starting with the specified
* seed, using <code>setSeed(seed);</code>.
*
* @param seed the initial seed
*/
public XSTR(long seed) {
this.seed = seed;
}
@Override
public boolean nextBoolean() {
return next(1) != 0;
}
@Override
public double nextDouble() {
return (((long) next(26) << 27) + next(27)) * DOUBLE_UNIT;
}
/**
* Returns the current state of the seed, can be used to clone the object
*
* @return the current seed
*/
public synchronized long getSeed() {
return seed;
}
/**
* Sets the seed for this pseudo random number generator. As described
* above, two instances of the same random class, starting with the same
* seed, produce the same results, if the same methods are called.
*
* @param seed the new seed
*/
@Override
public synchronized void setSeed(long seed) {
this.seed = seed;
}
/**
* @return Returns an XSRandom object with the same state as the original
*/
@Override
public XSTR clone() {
return new XSTR(getSeed());
}
/**
* Implementation of George Marsaglia's elegant Xorshift random generator
* 30% faster and better quality than the built-in java.util.random see also
* see http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
*
* @param nbits will shift nbits bits
* @return next seed
*/
@Override
public int next(int nbits) {
long x = seed;
x ^= x << 21;
x ^= x >>> 35;
x ^= x << 4;
seed = x;
x &= (1L << nbits) - 1;
return (int) x;
}
private boolean haveNextNextGaussian = false;
private double nextNextGaussian = 0;
@Override
public synchronized double nextGaussian() {
// See Knuth, ACP, Section 3.4.1 Algorithm C.
if (haveNextNextGaussian) {
haveNextNextGaussian = false;
return nextNextGaussian;
} else {
double v1, v2, vs;
do {
v1 = 2 * nextDouble() - 1; // between -1 and 1
v2 = 2 * nextDouble() - 1; // between -1 and 1
vs = v1 * v1 + v2 * v2;
} while (vs >= 1 || vs == 0);
double multiplier = StrictMath.sqrt(-2 * StrictMath.log(vs) / vs);
nextNextGaussian = v2 * multiplier;
haveNextNextGaussian = true;
return v1 * multiplier;
}
}
/**
* Returns a pseudorandom, uniformly distributed {@code int} value between 0
* (inclusive) and the specified value (exclusive), drawn from this random
* number generator's sequence. The general contract of {@code nextInt} is
* that one {@code int} value in the specified range is pseudorandomly
* generated and returned. All {@code bound} possible {@code int} values are
* produced with (approximately) equal probability. The method
* {@code nextInt(int bound)} is implemented by class {@code Random} as if
* by:
* <pre> {@code
* public int nextInt(int bound) {
* if (bound <= 0)
* throw new IllegalArgumentException("bound must be positive");
*
* if ((bound & -bound) == bound) // i.e., bound is a power of 2
* return (int)((bound * (long)next(31)) >> 31);
*
* int bits, val;
* do {
* bits = next(31);
* val = bits % bound;
* } while (bits - val + (bound-1) < 0);
* return val;
* }}</pre>
*
* <p>The hedge "approx
* imately" is used in the foregoing description only because the next
* method is only approximately an unbiased source of independently chosen
* bits. If it were a perfect source of randomly chosen bits, then the
* algorithm shown would choose {@code int} values from the stated range
* with perfect uniformity.
* <p>
* The algorithm is slightly tricky. It rejects values that would result in
* an uneven distribution (due to the fact that 2^31 is not divisible by n).
* The probability of a value being rejected depends on n. The worst case is
* n=2^30+1, for which the probability of a reject is 1/2, and the expected
* number of iterations before the loop terminates is 2.
* <p>
* The algorithm treats the case where n is a power of two specially: it
* returns the correct number of high-order bits from the underlying
* pseudo-random number generator. In the absence of special treatment, the
* correct number of <i>low-order</i> bits would be returned. Linear
* congruential pseudo-random number generators such as the one implemented
* by this class are known to have short periods in the sequence of values
* of their low-order bits. Thus, this special case greatly increases the
* length of the sequence of values returned by successive calls to this
* method if n is a small power of two.
*
* @param bound the upper bound (exclusive). Must be positive.
* @return the next pseudorandom, uniformly distributed {@code int} value
* between zero (inclusive) and {@code bound} (exclusive) from this random
* number generator's sequence
* @throws IllegalArgumentException if bound is not positive
* @since 1.2
*/
@Override
public int nextInt(int bound) {
//if (bound <= 0) {
//throw new RuntimeException("BadBound");
//}
/*int r = next(31);
int m = bound - 1;
if ((bound & m) == 0) // i.e., bound is a power of 2
{
r = (int) ((bound * (long) r) >> 31);
} else {
for (int u = r;
u - (r = u % bound) + m < 0;
u = next(31))
;
}
return r;*/
//speedup, new nextInt ~+40%
long last = seed ^ seed << 21;
last ^= last >>> 35;
last ^= last << 4;
seed = last;
int out = (int) last % bound;
return out < 0 ? -out : out;
}
@Override
public int nextInt() {
return next(32);
}
@Override
public float nextFloat() {
return next(24) * FLOAT_UNIT;
}
@Override
public long nextLong() {
// it's okay that the bottom word remains signed.
return ((long) next(32) << 32) + next(32);
}
@Override
public void nextBytes(byte[] bytes_arr) {
for (int iba = 0, lenba = bytes_arr.length; iba < lenba; ) {
for (int rndba = nextInt(), nba = Math.min(lenba - iba, Integer.SIZE / Byte.SIZE); nba-- > 0; rndba >>= Byte.SIZE) {
bytes_arr[iba++] = (byte) rndba;
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
[
{
"modid": "structurelib",
"name": "StructureLib",
"description": "Multiblocks with ease",
"version": "${version}",
"mcversion": "${mcversion}",
"url": "",
"updateUrl": "",
"authorList": ["glee8e"],
"credits": "",
"logoFile": "",
"screenshots": [],
"dependencies": ["Thaumcraft"]
}
]