Browse Source

first commit

master
asie 2 years ago
commit
81fa137a0e
47 changed files with 3422 additions and 0 deletions
  1. 63
    0
      build.gradle
  2. 3
    0
      gradle.properties
  3. BIN
      gradle/wrapper/gradle-wrapper.jar
  4. 6
    0
      gradle/wrapper/gradle-wrapper.properties
  5. 164
    0
      gradlew
  6. 90
    0
      gradlew.bat
  7. 303
    0
      src/main/java/pl/asie/minetestbridge/MinetestBridge.java
  8. 22
    0
      src/main/java/pl/asie/minetestbridge/MinetestGroupProxy.java
  9. 271
    0
      src/main/java/pl/asie/minetestbridge/MinetestLib.java
  10. 59
    0
      src/main/java/pl/asie/minetestbridge/MinetestMod.java
  11. 22
    0
      src/main/java/pl/asie/minetestbridge/MinetestSettingsLib.java
  12. 31
    0
      src/main/java/pl/asie/minetestbridge/ProxyClient.java
  13. 12
    0
      src/main/java/pl/asie/minetestbridge/ProxyCommon.java
  14. 32
    0
      src/main/java/pl/asie/minetestbridge/backwards/BackwardsBlockItemPopulator.java
  15. 27
    0
      src/main/java/pl/asie/minetestbridge/backwards/EntityWrapped.java
  16. 107
    0
      src/main/java/pl/asie/minetestbridge/backwards/ItemStackWrapped.java
  17. 26
    0
      src/main/java/pl/asie/minetestbridge/client/ItemNodeColorHandler.java
  18. 153
    0
      src/main/java/pl/asie/minetestbridge/client/ModelRegistry.java
  19. 105
    0
      src/main/java/pl/asie/minetestbridge/client/TextureAtlasSpriteCustom.java
  20. 59
    0
      src/main/java/pl/asie/minetestbridge/client/TextureMinetestSprite.java
  21. 69
    0
      src/main/java/pl/asie/minetestbridge/client/TextureRegistry.java
  22. 121
    0
      src/main/java/pl/asie/minetestbridge/client/util/BaseBakedModel.java
  23. 76
    0
      src/main/java/pl/asie/minetestbridge/client/util/CharsetFaceBakery.java
  24. 149
    0
      src/main/java/pl/asie/minetestbridge/client/util/NodeboxBakedModel.java
  25. 278
    0
      src/main/java/pl/asie/minetestbridge/client/util/RenderUtils.java
  26. 109
    0
      src/main/java/pl/asie/minetestbridge/client/util/SimpleBakedModel.java
  27. 61
    0
      src/main/java/pl/asie/minetestbridge/client/util/WrappedBakedModel.java
  28. 141
    0
      src/main/java/pl/asie/minetestbridge/node/BlockNode.java
  29. 7
    0
      src/main/java/pl/asie/minetestbridge/node/IBlockNode.java
  30. 7
    0
      src/main/java/pl/asie/minetestbridge/node/IItemNode.java
  31. 47
    0
      src/main/java/pl/asie/minetestbridge/node/ItemBlockNode.java
  32. 77
    0
      src/main/java/pl/asie/minetestbridge/node/ItemNode.java
  33. 48
    0
      src/main/java/pl/asie/minetestbridge/node/TileEntityNode.java
  34. 8
    0
      src/main/java/pl/asie/minetestbridge/recipe/IMinetestRecipe.java
  35. 189
    0
      src/main/java/pl/asie/minetestbridge/recipe/MinetestRecipeProxy.java
  36. 64
    0
      src/main/java/pl/asie/minetestbridge/recipe/MinetestShapedRecipe.java
  37. 41
    0
      src/main/java/pl/asie/minetestbridge/recipe/MinetestShapelessRecipe.java
  38. 36
    0
      src/main/java/pl/asie/minetestbridge/util/EntityUtils.java
  39. 13
    0
      src/main/java/pl/asie/minetestbridge/util/LuaField.java
  40. 13
    0
      src/main/java/pl/asie/minetestbridge/util/LuaMethod.java
  41. 93
    0
      src/main/java/pl/asie/minetestbridge/util/LuaProxy.java
  42. 91
    0
      src/main/java/pl/asie/minetestbridge/util/MethodHandleHelper.java
  43. 67
    0
      src/main/java/pl/asie/minetestbridge/util/TileBase.java
  44. 38
    0
      src/main/java/pl/asie/minetestbridge/util/UnlistedPropertyInteger.java
  45. 1
    0
      src/main/resources/assets/minetestbridge/lang/en_us.lang
  46. 16
    0
      src/main/resources/mcmod.info
  47. 7
    0
      src/main/resources/pack.mcmeta

+ 63
- 0
build.gradle View File

@@ -0,0 +1,63 @@
buildscript {
repositories {
jcenter()
maven { url = "http://files.minecraftforge.net/maven" }
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
}
}
apply plugin: 'net.minecraftforge.gradle.forge'
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
version = "0.1.0"
group = "pl.asie.minetestbridge" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "MinetestBridge"
sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
compileJava {
sourceCompatibility = targetCompatibility = '1.8'
}
minecraft {
version = "1.12.2-14.23.2.2654"
runDir = "run"
mappings = "snapshot_20180405"
makeObfSourceJar = false
replace "\${version}", project.version
replace "\${mcversion}", version
}
repositories {
ivy {
name 'asie dependency mirror'
artifactPattern "http://asie.pl/javadeps/[module]-[revision](-[classifier]).[ext]"
}
}
dependencies {
deobfCompile name: "Charset", version: "Lib-0.5.0.223"
compile group: 'org.luaj', name: 'luaj-jse', version: '2.0.3'
}
processResources {
// this will ensure that this task is redone when the versions change.
inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version
// replace stuff in mcmod.info, nothing else
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
// replace version and mcversion
expand 'version':project.version, 'mcversion':project.minecraft.version
}
// copy everything else except the mcmod.info
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
}

+ 3
- 0
gradle.properties View File

@@ -0,0 +1,3 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G

BIN
gradle/wrapper/gradle-wrapper.jar View File


+ 6
- 0
gradle/wrapper/gradle-wrapper.properties View File

@@ -0,0 +1,6 @@
#Mon Sep 14 12:28:28 PDT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip

+ 164
- 0
gradlew 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 "$@"

+ 90
- 0
gradlew.bat 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

+ 303
- 0
src/main/java/pl/asie/minetestbridge/MinetestBridge.java View File

@@ -0,0 +1,303 @@
package pl.asie.minetestbridge;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import org.apache.logging.log4j.Logger;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.ast.Str;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.VarArgFunction;
import org.luaj.vm2.lib.jse.JsePlatform;
import pl.asie.minetestbridge.backwards.BackwardsBlockItemPopulator;
import pl.asie.minetestbridge.backwards.ItemStackWrapped;
import pl.asie.minetestbridge.client.ModelRegistry;
import pl.asie.minetestbridge.client.TextureRegistry;
import pl.asie.minetestbridge.node.BlockNode;
import pl.asie.minetestbridge.node.ItemBlockNode;
import pl.asie.minetestbridge.node.ItemNode;
import pl.asie.minetestbridge.node.TileEntityNode;
import pl.asie.minetestbridge.recipe.MinetestRecipeProxy;

import java.io.File;
import java.util.*;

@Mod(modid = MinetestBridge.MODID, name = MinetestBridge.NAME, version = MinetestBridge.VERSION)
public class MinetestBridge
{
static final String MODID = "minetestbridge";
static final String NAME = "MinetestBridge";
static final String VERSION = "0.1.0";

static LuaValue globals;

public static Logger logger;
public static CreativeTabs tab;

private static MinetestMod currMod, lastMod;
private static File minetestEnvDir, modDir;
private static List<MinetestMod> modOrder = new ArrayList<>();
private static Map<String, MinetestMod> modMap = new HashMap<>();

@SidedProxy(serverSide = "pl.asie.minetestbridge.ProxyCommon", clientSide = "pl.asie.minetestbridge.ProxyClient", modId = MODID)
private static ProxyCommon proxy;

public static MinetestMod getCurrentMod() {
return currMod;
}

public static MinetestMod getLastRunMod() {
return lastMod;
}

public static File getBaseDir() {
return minetestEnvDir;
}

public static File getBuiltinDir() {
return new File(minetestEnvDir, "builtin");
}

public static Collection<MinetestMod> getLoadedMods() {
return Collections.unmodifiableList(modOrder);
}

@SuppressWarnings("ResultOfMethodCallIgnored")
@EventHandler
public void preInit(FMLPreInitializationEvent event) {
logger = event.getModLog();
globals = JsePlatform.debugGlobals();
globals.set("DIR_DELIM", LuaValue.valueOf(File.separator));
globals.set("INIT", LuaValue.valueOf("game"));
globals.load(new MinetestLib());
globals.set("ItemStack", new OneArgFunction() {
@Override
public LuaValue call(LuaValue arg) {
return new ItemStackWrapped(arg);
}
});

minetestEnvDir = new File(event.getModConfigurationDirectory().getParentFile(), "minetest");
modDir = new File(minetestEnvDir, "mods");
if (!minetestEnvDir.exists()) minetestEnvDir.mkdir();
if (!modDir.exists()) modDir.mkdir();

logger.info("Loading builtin Lua code");
MinetestBridge.globals.get("dofile").call(LuaValue.valueOf(new File(getBuiltinDir(), "init.lua").getAbsolutePath()));

try {
for (File f : Objects.requireNonNull(modDir.listFiles())) {
if (f.isDirectory() && new File(f, "init.lua").exists()) {
MinetestMod mod = new MinetestMod(f);
modMap.put(mod.getName(), mod);
logger.info("Found Minetest mod " + mod.getName());
}
}

Set<String> modsAdded = new HashSet<>();
while (modOrder.size() < modMap.size()) {
int lastSize = modOrder.size();
List<MinetestMod> mta = new ArrayList<>();

for (MinetestMod m : modMap.values()) {
if (modsAdded.contains(m.getName())) continue;

boolean canAdd = true;
for (String s : m.getDependencies()) {
if (s.endsWith("?")) {
s = s.substring(0, s.length() - 1);
if (!modMap.containsKey(s)) {
continue;
}
}

if (!modsAdded.contains(s)) {
canAdd = false;
break;
}
}

if (canAdd) {
mta.add(m);
}
}

mta.sort(Comparator.comparing(MinetestMod::getName));
modOrder.addAll(mta);
for (MinetestMod m : mta) {
modsAdded.add(m.getName());
}

if (modOrder.size() == lastSize) {
throw new RuntimeException("Could not resolve dependency graph!");
}
}

for (MinetestMod mod : modOrder) {
currMod = mod;
lastMod = mod;
logger.info("Initializing mod " + mod.getName());
mod.preInit();
}
currMod = null;
} catch (Exception e) {
throw new RuntimeException(e);
}

MinecraftForge.EVENT_BUS.register(this);
tab = new CreativeTabs("minetestbridge") {
@Override
public ItemStack getTabIconItem() {
return new ItemStack(Blocks.BEDROCK);
}
};

MinecraftForge.EVENT_BUS.register(MinetestRecipeProxy.INSTANCE);

proxy.preInit();
}

@EventHandler
public void init(FMLInitializationEvent event) {
GameRegistry.registerTileEntity(TileEntityNode.class, "minetestbridge:node");
BackwardsBlockItemPopulator.populate(globals);
}

private static final Map<LuaValue, BlockNode> blocks = new HashMap<>();

// TODO: ProxyClient-ify
public static World getCurrentWorld() {
if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
return DimensionManager.getWorld(0);
} else {
return Minecraft.getMinecraft().world;
}
}

public static LuaTable toMtPointedThing(BlockPos pos, EnumFacing facing) {
LuaTable result = new LuaTable();
result.set("type", "node");
result.set("under", toMtPos(pos));
result.set("above", toMtPos(pos.offset(facing)));
return result;
}

public static LuaTable toMtPointedThing(RayTraceResult trace) {
LuaTable result = new LuaTable();
if (trace != null) {
if (trace.typeOfHit == RayTraceResult.Type.BLOCK) {
result.set("type", "node");
result.set("under", toMtPos(trace.getBlockPos()));
result.set("above", toMtPos(trace.getBlockPos().offset(trace.sideHit)));
} else {
result.set("type", LuaValue.valueOf("nothing"));
}
} else {
result.set("type", LuaValue.valueOf("nothing"));
}
return result;
}

public static BlockPos toMcPos(LuaValue value) {
return value.istable() ? new BlockPos(value.get("x").checkint(), value.get("y").checkint(), value.get("z").checkint()) : BlockPos.ORIGIN;
}

public static LuaTable toMtPos(BlockPos pos) {
LuaTable result = new LuaTable();
result.set("x", LuaValue.valueOf(pos.getX()));
result.set("y", LuaValue.valueOf(pos.getY()));
result.set("z", LuaValue.valueOf(pos.getZ()));
return result;
}

@SubscribeEvent
public void onRegisterBlocks(RegistryEvent.Register<Block> event) {
blocks.clear();

for (LuaValue key : MinetestLib.getRegistry("nodes").keys()) {
LuaValue value = MinetestLib.getRegistry("nodes").get(key);
if (key.isstring() && value.istable()) {
BlockNode blockNode = new BlockNode(value.checktable());
blockNode.setRegistryName(asMcName(key.tojstring()));
event.getRegistry().register(blockNode);
blocks.put(key, blockNode);
}
}
}

@SubscribeEvent
public void onRegisterItems(RegistryEvent.Register<Item> event) {
for (LuaValue key : MinetestLib.getRegistry("items").keys()) {
LuaValue value = MinetestLib.getRegistry("items").get(key);
if (key.isstring() && value.istable()) {
if (MinetestLib.getRegistry("nodes").get(key).istable()) {
ItemBlockNode itemNode = new ItemBlockNode(blocks.get(key), value.checktable());
itemNode.setRegistryName(asMcName(key.tojstring()));
event.getRegistry().register(itemNode);
} else {
ItemNode itemNode = new ItemNode(value.checktable());
itemNode.setRegistryName(asMcName(key.tojstring()));
event.getRegistry().register(itemNode);
}
}
}
}

public static File getModDir() {
return modDir;
}

public static ResourceLocation asMcName(String mtName) {
mtName = MinetestLib.getAliased(mtName);

if (mtName.startsWith("minecraft_")) {
// submod
return new ResourceLocation(mtName.substring(10));
} else if (mtName.startsWith("minecraft:")) {
// vanilla
return new ResourceLocation(mtName);
} else {
// minetest
return new ResourceLocation("minetestbridge", mtName.replace(':', '/'));
}
}

public static String asMtName(ResourceLocation mcName) {
if (mcName.getResourceDomain().equals("minetestbridge")) {
// minetest
return mcName.getResourcePath().replaceFirst("/", ":");
} else if (mcName.getResourceDomain().equals("minecraft")) {
// vanilla
return mcName.toString();
} else {
// submod
return "minecraft_" + mcName.toString();
}
}

public static MinetestMod getMod(String modname) {
return modMap.get(modname);
}
}

+ 22
- 0
src/main/java/pl/asie/minetestbridge/MinetestGroupProxy.java View File

@@ -0,0 +1,22 @@
package pl.asie.minetestbridge;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import org.luaj.vm2.ast.Str;

public class MinetestGroupProxy {
private static final BiMap<String, String> minetestToMinecraft;

static {
minetestToMinecraft = HashBiMap.create();
minetestToMinecraft.put("stick", "stickWood");
}

public static String toMinecraft(String s) {
return minetestToMinecraft.getOrDefault(s, s);
}

public static String toMinetest(String s) {
return minetestToMinecraft.inverse().getOrDefault(s, s);
}
}

+ 271
- 0
src/main/java/pl/asie/minetestbridge/MinetestLib.java View File

@@ -0,0 +1,271 @@
package pl.asie.minetestbridge;

import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
import org.apache.commons.codec.binary.Base64;
import org.luaj.vm2.LuaBoolean;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.ast.Str;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
import pl.asie.minetestbridge.backwards.ItemStackWrapped;
import pl.asie.minetestbridge.node.BlockNode;
import pl.asie.minetestbridge.recipe.MinetestRecipeProxy;
import pl.asie.minetestbridge.util.LuaField;
import pl.asie.minetestbridge.util.LuaMethod;
import pl.asie.minetestbridge.util.LuaProxy;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

public class MinetestLib extends ZeroArgFunction {
@LuaField
public static MinetestSettingsLib settings = new MinetestSettingsLib();

public static String getAliased(String name) {
LuaTable aliases = MinetestBridge.globals.get("core").get("registered_aliases").checktable();
while (aliases.get(name).isstring()) {
name = aliases.get(name).tojstring();
}
return name;
}

public static LuaTable getRegistry(String name) {
return MinetestBridge.globals.get("core").get("registered_"+name).checktable();
}

@LuaMethod
public LuaValue is_singleplayer() {
return LuaBoolean.FALSE;
}

@LuaMethod
public LuaValue get_craft_result(LuaValue value) {
// TODO: return two, work
LuaValue table = LuaValue.tableOf();
table.set("item", new ItemStackWrapped(ItemStack.EMPTY));
table.set("time", 0);
table.set("replacements", LuaValue.tableOf());
return table;
}

@LuaMethod
public LuaValue log(String type, String text) {
if (text == null) {
type = "info";
text = type;
}

if ("warning".equals(type) || "deprecated".equals(type)) {
MinetestBridge.logger.warn("[Minetest] " + text);
} else {
MinetestBridge.logger.info("[Minetest] " + text);
}

return LuaValue.NIL;
}

@LuaMethod
public LuaValue get_mapgen_setting(String key) {
// TODO
if ("chunksize".equals(key)) {
return LuaValue.valueOf("6");
} else if ("mg_name".equals(key)) {
return LuaValue.valueOf("v6");
} else {
return LuaValue.NIL;
}
}

@LuaMethod
public LuaValue get_decoration_id(String name) {
// TODO
return LuaValue.NIL;
}

@LuaMethod
public LuaValue set_gen_notify(LuaValue a, LuaValue b) {
// TODO
return null;
}

@LuaMethod
public LuaValue register_craft(LuaValue craft) {
if (craft.istable()) {
MinetestRecipeProxy.INSTANCE.registerRecipe(craft.checktable());
}
return null;
}

@LuaMethod
public LuaValue register_biome(LuaValue table) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue register_ore(LuaValue table) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue register_decoration(LuaValue table) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue clear_registered_biomes(LuaValue table) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue clear_registered_ores(LuaValue table) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue clear_registered_decorations(LuaValue table) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue register_item_raw(LuaValue table) {
MinetestBridge.logger.info("Registering item " + table.get("name").optjstring("???"));
return LuaValue.NIL;
}

@LuaMethod
public LuaValue unregister_item_raw(LuaValue table) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue register_alias_raw(String from, String to) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue get_current_modname() {
MinetestMod mod = MinetestBridge.getCurrentMod();
return mod != null ? LuaValue.valueOf(mod.getName()) : LuaValue.NIL;
}

@LuaMethod
public LuaValue get_last_run_mod() {
MinetestMod mod = MinetestBridge.getLastRunMod();
return mod != null ? LuaValue.valueOf(mod.getName()) : LuaValue.valueOf("*builtin*");
}

@LuaMethod
public LuaValue get_builtin_path() {
return LuaValue.valueOf(MinetestBridge.getBuiltinDir().getAbsolutePath() + File.separator);
}

@LuaMethod
public LuaValue get_worldpath() {
return LuaValue.valueOf(MinetestBridge.getBaseDir().getAbsolutePath() + File.separator);
}

@LuaMethod
public LuaValue get_modpath(String modname) {
MinetestMod mod = MinetestBridge.getMod(modname);
if (mod != null) {
return LuaValue.valueOf(mod.getDir().getAbsolutePath() + File.separator);
}
return LuaValue.NIL;
}

@LuaMethod
public LuaValue get_node(LuaValue pos) {
LuaValue result = get_node_or_nil(pos);
if (result.isnil()) {
result = new LuaTable();
result.set("name", LuaValue.valueOf("ignore"));
result.set("param1", LuaValue.valueOf(0));
result.set("param2", LuaValue.valueOf(0));
}
return result;
}

@LuaMethod
public LuaValue get_node_or_nil(LuaValue pos) {
BlockPos mcPos = MinetestBridge.toMcPos(pos);
World w = MinetestBridge.getCurrentWorld();
if (w.isBlockLoaded(mcPos)) {
IBlockState state = w.getBlockState(mcPos);
LuaTable result = new LuaTable();
result.set("name", LuaValue.valueOf(MinetestBridge.asMtName(state.getBlock().getRegistryName())));
result.set("param1", LuaValue.valueOf(
(w.getLightFor(EnumSkyBlock.BLOCK, mcPos) & 0xF)
| ((w.getLight(mcPos) & 0xF) << 4)
));
result.set("param2", LuaValue.valueOf(0));
if (state.getBlock() instanceof BlockNode) {
// TODO: copy over param2 from TileEntityNode
}
return result;
} else {
return LuaValue.NIL;
}
}

@LuaMethod
public LuaValue remove_node(LuaValue pos) {
BlockPos mcPos = MinetestBridge.toMcPos(pos);
MinetestBridge.getCurrentWorld().setBlockToAir(mcPos);
return LuaValue.NIL;
}

@LuaMethod
public LuaValue delete_area(LuaValue pos1, LuaValue pos2) {
World w = MinetestBridge.getCurrentWorld();
BlockPos.getAllInBoxMutable(MinetestBridge.toMcPos(pos1), MinetestBridge.toMcPos(pos2)).forEach(
w::setBlockToAir
);
return LuaValue.NIL;
}

@LuaMethod
public LuaValue get_timeofday() {
int l = (int) MinetestBridge.getCurrentWorld().getWorldTime();
return LuaValue.valueOf((double) ((l + 6000) % 24000) / 24000.0);
}

@LuaMethod
public LuaValue get_gametime() {
long l = MinetestBridge.getCurrentWorld().getTotalWorldTime();
return LuaValue.valueOf((int) (l / 20));
}

@LuaMethod
public LuaValue get_day_count() {
long l = MinetestBridge.getCurrentWorld().getTotalWorldTime();
return LuaValue.valueOf((int) (l / 24000));
}

@LuaMethod
public LuaValue set_timeofday(LuaValue val) {
double d = val.checkdouble();
int l = ((int) (d * 24000.0) + 18000) % 24000;
MinetestBridge.getCurrentWorld().setWorldTime(l);
return LuaValue.NIL;
}

@LuaMethod
public LuaValue get_us_time() {
return LuaValue.valueOf((double) (System.currentTimeMillis() * 1000));
}

@Override
public LuaValue call() {
LuaValue lib = LuaProxy.reflect(this);
env.set("core", lib);
return lib;
}
}

+ 59
- 0
src/main/java/pl/asie/minetestbridge/MinetestMod.java View File

@@ -0,0 +1,59 @@
package pl.asie.minetestbridge;

import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;

public class MinetestMod {
private final File dir;
private final String name;
private final Collection<String> dependencies;

public MinetestMod(File dir) {
this.dir = dir;
this.name = dir.getName();

File dependsFile = new File(dir, "depends.txt");
if (dependsFile.exists()) {
ImmutableSet.Builder<String> depBuilder = new ImmutableSet.Builder<>();

try {
for (String s : Files.readLines(dependsFile, Charsets.UTF_8)) {
s = s.trim();
if (!s.isEmpty()) {
depBuilder.add(s);
}
}
} catch (IOException e) {
e.printStackTrace();
}

this.dependencies = depBuilder.build();
} else {
this.dependencies = Collections.emptySet();
}
}

public File getDir() {
return dir;
}

public String getName() {
return name;
}

public Collection<String> getDependencies() {
return dependencies;
}

public void preInit() {
MinetestBridge.globals.get("dofile").call(LuaValue.valueOf(new File(dir, "init.lua").getAbsolutePath()));
}
}

+ 22
- 0
src/main/java/pl/asie/minetestbridge/MinetestSettingsLib.java View File

@@ -0,0 +1,22 @@
package pl.asie.minetestbridge;

import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import pl.asie.minetestbridge.util.LuaMethod;
import pl.asie.minetestbridge.util.LuaProxy;

public class MinetestSettingsLib extends LuaTable {
public MinetestSettingsLib() {
LuaProxy.reflect(this, this);
}

@LuaMethod
public LuaValue get(LuaValue wrap, String name) {
return LuaValue.NIL;
}

@LuaMethod
public LuaValue get_bool(LuaValue wrap, String name) {
return LuaValue.valueOf(false);
}
}

+ 31
- 0
src/main/java/pl/asie/minetestbridge/ProxyClient.java View File

@@ -0,0 +1,31 @@
package pl.asie.minetestbridge;

import net.minecraft.item.Item;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import pl.asie.minetestbridge.client.ItemNodeColorHandler;
import pl.asie.minetestbridge.client.ModelRegistry;
import pl.asie.minetestbridge.client.TextureRegistry;
import pl.asie.minetestbridge.node.ItemNode;

public class ProxyClient extends ProxyCommon {
@Override
public void preInit() {
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(new TextureRegistry());
MinecraftForge.EVENT_BUS.register(new ModelRegistry());
}

@SubscribeEvent
public void onItemColor(ColorHandlerEvent.Item event) {
ItemNodeColorHandler itemNodeColorHandler = new ItemNodeColorHandler();

for (Item i : ForgeRegistries.ITEMS) {
if (i instanceof ItemNode) {
event.getItemColors().registerItemColorHandler(itemNodeColorHandler, i);
}
}
}
}

+ 12
- 0
src/main/java/pl/asie/minetestbridge/ProxyCommon.java View File

@@ -0,0 +1,12 @@
package pl.asie.minetestbridge;

import net.minecraft.item.Item;
import net.minecraftforge.common.MinecraftForge;
import pl.asie.minetestbridge.client.ModelRegistry;
import pl.asie.minetestbridge.client.TextureRegistry;

public class ProxyCommon {
public void preInit() {

}
}

+ 32
- 0
src/main/java/pl/asie/minetestbridge/backwards/BackwardsBlockItemPopulator.java View File

@@ -0,0 +1,32 @@
package pl.asie.minetestbridge.backwards;

import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import pl.asie.minetestbridge.MinetestBridge;
import pl.asie.minetestbridge.MinetestLib;

public class BackwardsBlockItemPopulator {
public static void populate(LuaValue globals) {
/* for (Block b : ForgeRegistries.BLOCKS) {
LuaTable table = LuaValue.tableOf();

globals.get("core").get("register_node").invoke(LuaValue.valueOf(MinetestBridge.asMtName(b.getRegistryName())), table);
}

for (Item i : ForgeRegistries.ITEMS) {
if (Block.getBlockFromItem(i) != Blocks.AIR) continue;

LuaTable table = LuaValue.tableOf();

table.set("description", LuaValue.valueOf(i.getUnlocalizedName()));
table.set("stack_max", LuaValue.valueOf(i.getItemStackLimit()));

globals.get("core").get("register_item").invoke(LuaValue.valueOf(MinetestBridge.asMtName(i.getRegistryName())), table);
} */
// TODO
}
}

+ 27
- 0
src/main/java/pl/asie/minetestbridge/backwards/EntityWrapped.java View File

@@ -0,0 +1,27 @@
package pl.asie.minetestbridge.backwards;

import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import pl.asie.minetestbridge.util.LuaMethod;
import pl.asie.minetestbridge.util.LuaProxy;

public class EntityWrapped extends LuaTable {
private final Entity entity;

public EntityWrapped(Entity entity) {
this.entity = entity;
LuaProxy.reflect(this, this);
}

@LuaMethod
public LuaValue is_player(LuaValue wrap) {
return LuaValue.valueOf(entity instanceof EntityPlayer);
}

@LuaMethod
public LuaValue get_player_name(LuaValue wrap) {
return LuaValue.valueOf(entity.getName());
}
}

+ 107
- 0
src/main/java/pl/asie/minetestbridge/backwards/ItemStackWrapped.java View File

@@ -0,0 +1,107 @@
package pl.asie.minetestbridge.backwards;

import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import pl.asie.minetestbridge.MinetestBridge;
import pl.asie.minetestbridge.MinetestLib;
import pl.asie.minetestbridge.recipe.MinetestRecipeProxy;
import pl.asie.minetestbridge.util.LuaMethod;
import pl.asie.minetestbridge.util.LuaProxy;

import javax.annotation.Nullable;
import java.util.function.Consumer;

public class ItemStackWrapped extends LuaTable {
@Nullable
private final Consumer<ItemStack> stackReplacer;
private final ItemStack stack;

public ItemStackWrapped(ItemStack stack) {
this(stack, null);
}

public ItemStackWrapped(LuaValue wrap) {
this.stackReplacer = null;
if (wrap instanceof ItemStackWrapped) {
this.stack = ((ItemStackWrapped) wrap).getStack();
} else {
this.stack = MinetestRecipeProxy.getStack(wrap);
}
LuaProxy.reflect(this, this);
}

public ItemStackWrapped(ItemStack stack, Consumer<ItemStack> stackReplacer) {
this.stack = stack;
this.stackReplacer = stackReplacer;
LuaProxy.reflect(this, this);
}

public ItemStack getStack() {
return stack;
}

@LuaMethod
public LuaValue is_empty(LuaValue wrap) {
return LuaValue.valueOf(stack.isEmpty());
}

@LuaMethod
public LuaValue get_name(LuaValue wrap) {
return LuaValue.valueOf(MinetestBridge.asMtName(stack.getItem().getRegistryName()));
}

@LuaMethod
public LuaValue get_count(LuaValue wrap) {
return LuaValue.valueOf(stack.getCount());
}

@LuaMethod
public LuaValue set_count(LuaValue wrap, LuaValue count) {
stack.setCount(count.checkint());
return is_empty(wrap);
}

@LuaMethod
public LuaValue clear(LuaValue wrap) {
stack.setCount(0);
return LuaValue.NIL;
}

@LuaMethod
public LuaValue get_definition(LuaValue wrap) {
try {
return MinetestLib.getRegistry("items").get(MinetestBridge.asMtName(stack.getItem().getRegistryName()));
} catch (LuaError e) {
return LuaValue.NIL;
}
}

@LuaMethod
public LuaValue get_stack_max(LuaValue wrap) {
return LuaValue.valueOf(stack.getMaxStackSize());
}

@LuaMethod
public LuaValue get_free_space(LuaValue wrap) {
return LuaValue.valueOf(stack.getMaxStackSize() - stack.getCount());
}

@LuaMethod
public LuaValue take_item(LuaValue wrap, LuaValue count) {
int c = count.optint(1);
return new ItemStackWrapped(stack.splitStack(c));
}

@LuaMethod
public LuaValue peek_item(LuaValue wrap, LuaValue count) {
int c = count.optint(1);
ItemStack ns = stack.copy();
ns.setCount(Math.min(c, ns.getCount()));
return new ItemStackWrapped(ns);
}
}

+ 26
- 0
src/main/java/pl/asie/minetestbridge/client/ItemNodeColorHandler.java View File

@@ -0,0 +1,26 @@
package pl.asie.minetestbridge.client;

import net.minecraft.client.renderer.color.IItemColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import pl.asie.minetestbridge.node.ItemNode;

public class ItemNodeColorHandler implements IItemColor {
@Override
public int colorMultiplier(ItemStack stack, int tintIndex) {
if (tintIndex == 0) {
Item i = stack.getItem();
if (i instanceof ItemNode) {
LuaTable table = ((ItemNode) i).getLuaTable();
LuaValue color = table.get("color");
if (color.isint()) {
return color.toint() | 0xFF000000;
}
}
}

return -1;
}
}

+ 153
- 0
src/main/java/pl/asie/minetestbridge/client/ModelRegistry.java View File

@@ -0,0 +1,153 @@
package pl.asie.minetestbridge.client;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.block.model.ModelRotation;
import net.minecraft.client.renderer.block.statemap.IStateMapper;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ItemLayerModel;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.ITransformation;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.common.registry.GameRegistry;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.ast.Str;
import pl.asie.charset.lib.utils.Orientation;
import pl.asie.minetestbridge.MinetestBridge;
import pl.asie.minetestbridge.MinetestLib;
import pl.asie.minetestbridge.client.util.NodeboxBakedModel;
import pl.asie.minetestbridge.node.BlockNode;
import pl.asie.minetestbridge.node.ItemNode;

import java.util.HashMap;
import java.util.Map;

public class ModelRegistry implements IStateMapper {
public static String getTextureName(String owner, LuaValue value) {
if (value.isstring()) {
return TextureRegistry.toMcLoc(owner, value.checkjstring()).toString();
} else if (value.istable() && value.get("name").isstring()) {
return TextureRegistry.toMcLoc(owner, value.get("name").checkjstring()).toString();
} else {
return "missingno";
}
}

public static IModel getModel(ResourceLocation location) {
try {
return ModelLoaderRegistry.getModel(location);
} catch (Exception e) {
MinetestBridge.logger.error("Model " + location.toString() + " is missing! THIS WILL CAUSE A CRASH!");
e.printStackTrace();
return null;
}
}

@SubscribeEvent
public void onModelRegistry(ModelRegistryEvent event) {
for (LuaValue key : MinetestLib.getRegistry("items").keys()) {
LuaValue value = MinetestLib.getRegistry("items").get(key);
if (key.isstring() && value.istable()) {
ResourceLocation loc = MinetestBridge.asMcName(key.tojstring());
Item item = ForgeRegistries.ITEMS.getValue(loc);
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(loc, "inventory"));
}
}
}

private static void add(ImmutableMap.Builder<String, String> builder, String key, String value) {
builder.put(key, value);
builder.put('#'+key, value);
}

@SubscribeEvent
public void onModelBake(ModelBakeEvent event) {
for (LuaValue key : MinetestLib.getRegistry("items").keys()) {
LuaValue value = MinetestLib.getRegistry("items").get(key);
if (key.isstring() && value.istable()) {
if (value.get("inventory_image").isstring()) {
String owner = key.tojstring().split(":")[0];
ImmutableList.Builder<ResourceLocation> textures = new ImmutableList.Builder<>();
textures.add(TextureRegistry.toMcLoc(owner, value.get("inventory_image").checkjstring()));
if (value.get("inventory_overlay").isstring()) {
textures.add(TextureRegistry.toMcLoc(owner, value.get("inventory_overlay").checkjstring()));
}

ResourceLocation loc = MinetestBridge.asMcName(key.tojstring());
ModelResourceLocation mloc = new ModelResourceLocation(loc, "inventory");
ItemLayerModel model = new ItemLayerModel(textures.build());

event.getModelRegistry().putObject(mloc,
model.bake(TRSRTransformation.identity(), DefaultVertexFormats.ITEM, ModelLoader.defaultTextureGetter()));
}
}
}

for (LuaValue key : MinetestLib.getRegistry("nodes").keys()) {
LuaValue value = MinetestLib.getRegistry("nodes").get(key);
if (key.isstring() && value.istable()) {
if (value.get("tiles").istable()) {
String owner = key.tojstring().split(":")[0];
ResourceLocation loc = MinetestBridge.asMcName(key.tojstring());
LuaValue tiles = value.get("tiles");

IModel model = null;
IBakedModel bm = null;
String drawtype = value.get("drawtype").optjstring("normal");

if (drawtype.equals("plantlike")) {
ImmutableMap.Builder<String, String> map = ImmutableMap.builder();
add(map, "cross", getTextureName(owner, tiles.get(1)));
model = getModel(new ResourceLocation("minecraft", "block/cross"))
.retexture(map.build());
} else {
bm = new NodeboxBakedModel(owner, value, ModelRotation.X0_Y0, ModelLoader.defaultTextureGetter());
}

if (model != null && bm == null) {
bm = model.bake(TRSRTransformation.identity(), DefaultVertexFormats.ITEM, ModelLoader.defaultTextureGetter());
}

if (bm != null) {
event.getModelRegistry().putObject(new ModelResourceLocation(loc, "normal"), bm);
event.getModelRegistry().putObject(new ModelResourceLocation(loc, "inventory"), bm);
}
}
}
}
}

private static final Map<String, ITransformation[]> types = new HashMap<>();

static {
types.put("none", new ITransformation[]{ModelRotation.X0_Y0});
}

private ITransformation[] getTransformations(LuaValue value) {
String paramtype2 = value.get("paramtype2").optjstring("none");
if (!types.containsKey(paramtype2)) paramtype2 = "none";
return types.get(paramtype2);
}

@Override
public Map<IBlockState, ModelResourceLocation> putStateModelLocations(Block blockIn) {
ImmutableMap.Builder<IBlockState, ModelResourceLocation> builder = new ImmutableMap.Builder<>();
for (IBlockState state : blockIn.getBlockState().getValidStates()) {
builder.put(state, new ModelResourceLocation(blockIn.getRegistryName(), "normal"));
}
return builder.build();
}
}

+ 105
- 0
src/main/java/pl/asie/minetestbridge/client/TextureAtlasSpriteCustom.java View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2015, 2016, 2017, 2018 Adrian Siekierka
*
* This file is part of Charset.
*
* Charset is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Charset is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Charset. If not, see <http://www.gnu.org/licenses/>.
*/

package pl.asie.minetestbridge.client;

import com.google.common.collect.Lists;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.data.AnimationFrame;
import net.minecraft.client.resources.data.AnimationMetadataSection;
import pl.asie.minetestbridge.util.MethodHandleHelper;

import javax.annotation.Nullable;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class TextureAtlasSpriteCustom extends TextureAtlasSprite {
private static final MethodHandle ANIMATION_METADATA_SETTER = MethodHandleHelper.findFieldSetter(TextureAtlasSprite.class, "animationMetadata", "field_110982_k");

protected TextureAtlasSpriteCustom(String spriteName) {
super(spriteName);
}

protected void addFrameTextureData(int width, int height, int[] pixels) {
addFrameTextureData(width, height, pixels, null);
}

protected void addFrameTextureData(int width, int height, int[] pixels, @Nullable IResource resource) {
AnimationMetadataSection section = resource != null ? resource.getMetadata("animation") : null;

this.clearFramesTextureData();

if (section == null) {
this.setIconWidth(width);
this.setIconHeight(height);

int[][] pixelsCtr = new int[Minecraft.getMinecraft().getTextureMapBlocks().getMipmapLevels() + 1][];
pixelsCtr[0] = pixels;
framesTextureData.add(pixelsCtr);
} else {
this.setIconWidth(width);
this.setIconHeight(width);

int i = height / width;
if (section.getFrameCount() > 0) {
for (Integer index : section.getFrameIndexSet()) {
if (index >= i) {
throw new RuntimeException("invalid frameindex " + index);
}

while (framesTextureData.size() <= index) {
framesTextureData.add(null);
}

int[] data = new int[width * width];
int[][] container = new int[Minecraft.getMinecraft().getTextureMapBlocks().getMipmapLevels() + 1][];
System.arraycopy(pixels, width * width * index, data, 0, width * width);
container[0] = data;

framesTextureData.set(index, container);
}
} else {
List<AnimationFrame> frames = new ArrayList<>(i);
for (int index = 0; index < i; index++) {
int[] data = new int[width * width];
int[][] container = new int[Minecraft.getMinecraft().getTextureMapBlocks().getMipmapLevels() + 1][];
System.arraycopy(pixels, width * width * index, data, 0, width * width);
container[0] = data;

framesTextureData.add(container);
frames.add(new AnimationFrame(index, -1));
}
section = new AnimationMetadataSection(frames, width, height, section.getFrameTime(), section.isInterpolate());
}

try {
ANIMATION_METADATA_SETTER.invokeExact((TextureAtlasSprite) this, section);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}
}

+ 59
- 0
src/main/java/pl/asie/minetestbridge/client/TextureMinetestSprite.java View File

@@ -0,0 +1,59 @@
package pl.asie.minetestbridge.client;

import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import pl.asie.minetestbridge.MinetestMod;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;

public class TextureMinetestSprite extends TextureAtlasSpriteCustom {
private final File dir;
private final Collection<MinetestMod> mods;
private final String suffix;

protected TextureMinetestSprite(String spriteName, File dir, Collection<MinetestMod> mods, String suffix) {
super(spriteName);
this.dir = dir;
this.mods = mods;
this.suffix = suffix;
}

@Override
public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) {
return true;
}

@Override
public boolean load(IResourceManager manager, ResourceLocation loc, Function<ResourceLocation, TextureAtlasSprite> getter) {
try {
File f = null;
for (MinetestMod mod : mods) {
File ff = new File(dir, mod.getName() + suffix);
if (ff.exists()) {
f = ff;
break;
}
}

if (f == null) {
return true;
}

BufferedImage img = TextureUtil.readBufferedImage(new FileInputStream(f));
int[] pixels = new int[img.getWidth() * img.getHeight()];
img.getRGB(0, 0, img.getWidth(), img.getHeight(), pixels, 0, img.getWidth());
this.addFrameTextureData(img.getWidth(), img.getHeight(), pixels);
return false;
} catch (IOException e) {
return true;
}
}
}

+ 69
- 0
src/main/java/pl/asie/minetestbridge/client/TextureRegistry.java View File

@@ -0,0 +1,69 @@
package pl.asie.minetestbridge.client;

import com.google.common.eventbus.Subscribe;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.ast.Str;
import pl.asie.minetestbridge.MinetestBridge;
import pl.asie.minetestbridge.MinetestLib;

import java.io.File;

public class TextureRegistry {
public static ResourceLocation toMcLoc(String owner, String tex) {
return new ResourceLocation("minetestbridge:" + tex);
}

private void appendTexture(String owner, LuaValue invImage, TextureMap map) {
if (invImage.istable() && invImage.get("name").isstring()) {
invImage = invImage.get("name");
}

if (invImage.isstring()) {
String textureName = "minetestbridge:" + invImage.tojstring();
map.setTextureEntry(new TextureMinetestSprite(textureName,
MinetestBridge.getModDir(), MinetestBridge.getLoadedMods(), "/textures/" + invImage.tojstring()));
}
}

private void appendTextureTable(String owner, LuaValue texTable, TextureMap map) {
if (texTable.istable()) {
for (LuaValue key : texTable.checktable().keys()) {
appendTexture(owner, texTable.checktable().get(key), map);
}
}
}

private void appendTextures(String owner, LuaValue node, TextureMap map) {
appendTexture(owner, node.get("inventory_image"), map);
appendTexture(owner, node.get("inventory_overlay"), map);
appendTexture(owner, node.get("wield_image"), map);
appendTexture(owner, node.get("wield_overlay"), map);

appendTextureTable(owner, node.get("textures"), map);

appendTextureTable(owner, node.get("tiles"), map);
appendTextureTable(owner, node.get("overlay_tiles"), map);
appendTextureTable(owner, node.get("special_tiles"), map);
}

@SubscribeEvent
public void onTextureStitchPre(TextureStitchEvent.Pre event) {
for (LuaValue key : MinetestLib.getRegistry("nodes").keys()) {
LuaValue value = MinetestLib.getRegistry("nodes").get(key);
if (key.isstring() && value.istable()) {
appendTextures(key.tojstring().split(":")[0], value, event.getMap());
}
}

for (LuaValue key : MinetestLib.getRegistry("items").keys()) {
LuaValue value = MinetestLib.getRegistry("items").get(key);
if (key.isstring() && value.istable()) {
appendTextures(key.tojstring().split(":")[0], value, event.getMap());
}
}
}
}

+ 121
- 0
src/main/java/pl/asie/minetestbridge/client/util/BaseBakedModel.java View File

@@ -0,0 +1,121 @@
/*
* Copyright (c) 2015, 2016, 2017, 2018 Adrian Siekierka
*
* This file is part of Charset.
*
* Charset is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Charset is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Charset. If not, see <http://www.gnu.org/licenses/>.
*/

package pl.asie.minetestbridge.client.util;

import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraftforge.common.model.TRSRTransformation;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;

import javax.vecmath.Matrix4f;
import javax.vecmath.Vector3f;
import java.util.EnumMap;

public abstract class BaseBakedModel implements IBakedModel {
private final EnumMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap = new EnumMap(ItemCameraTransforms.TransformType.class);

@Override
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) {
return ImmutablePair.of(this,
transformMap.containsKey(cameraTransformType) ? transformMap.get(cameraTransformType).getMatrix() : null);
}

@Override
public boolean isAmbientOcclusion() {
return true;
}

@Override
public boolean isGui3d() {
return true;
}

@Override
public boolean isBuiltInRenderer() {
return false;
}

@Override
public ItemOverrideList getOverrides() {
return ItemOverrideList.NONE;
}

public void addTransformation(ItemCameraTransforms.TransformType type, TRSRTransformation transformation) {
transformMap.put(type, TRSRTransformation.blockCornerToCenter(transformation));
}

public void addThirdPersonTransformation(TRSRTransformation transformation) {
addTransformation(ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND, transformation);
addTransformation(ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND, toLeftHand(transformation));
}

public void addFirstPersonTransformation(TRSRTransformation transformation) {
addTransformation(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND, transformation);
addTransformation(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, toLeftHand(transformation));
}

// ForgeBlockStateV1 transforms

private static final TRSRTransformation flipX = new TRSRTransformation(null, null, new Vector3f(-1, 1, 1), null);

protected static TRSRTransformation toLeftHand(TRSRTransformation transform) {
return TRSRTransformation.blockCenterToCorner(flipX.compose(TRSRTransformation.blockCornerToCenter(transform)).compose(flipX));
}

protected static TRSRTransformation getTransformation(float tx, float ty, float tz, float ax, float ay, float az, float s) {
return TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
new Vector3f(tx / 16, ty / 16, tz / 16),
TRSRTransformation.quatFromXYZDegrees(new Vector3f(ax, ay, az)),
new Vector3f(s, s, s),
null));
}

public BaseBakedModel addDefaultBlockTransforms() {
TRSRTransformation thirdperson = getTransformation(0, 2.5f, 0, 75, 45, 0, 0.375f);
addTransformation(ItemCameraTransforms.TransformType.GUI, getTransformation(0, 0, 0, 30, 225, 0, 0.625f));
addTransformation(ItemCameraTransforms.TransformType.GROUND, getTransformation(0, 3, 0, 0, 0, 0, 0.25f));
addTransformation(ItemCameraTransforms.TransformType.FIXED, getTransformation(0, 0, 0, 0, 0, 0, 0.5f));
addThirdPersonTransformation(thirdperson);
addTransformation(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND, getTransformation(0, 0, 0, 0, 45, 0, 0.4f));
addTransformation(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, getTransformation(0, 0, 0, 0, 255, 0, 0.4f));
return this;
}

public BaseBakedModel addDefaultItemTransforms() {
TRSRTransformation thirdperson = getTransformation(0, 3, 1, 0, 0, 0, 0.55f);
TRSRTransformation firstperson = getTransformation(1.13f, 3.2f, 1.13f, 0, -90, 25, 0.68f);
addTransformation(ItemCameraTransforms.TransformType.GROUND, getTransformation(0, 2, 0, 0, 0, 0, 0.5f));
addTransformation(ItemCameraTransforms.TransformType.HEAD, getTransformation(0, 13, 7, 0, 180, 0, 1));
addTransformation(ItemCameraTransforms.TransformType.FIXED, getTransformation(0, 0, 0, 0, 180, 0, 1));
addThirdPersonTransformation(thirdperson);
addFirstPersonTransformation(firstperson);
return this;
}

public BaseBakedModel addDefaultToolTransforms() {
addTransformation(ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND, getTransformation(0, 4, 0.5f, 0, -90, 55, 0.85f));
addTransformation(ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND, getTransformation(0, 4, 0.5f, 0, 90, -55, 0.85f));
addTransformation(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND, getTransformation(1.13f, 3.2f, 1.13f, 0, -90, 25, 0.68f));
addTransformation(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, getTransformation(1.13f, 3.2f, 1.13f, 0, 90, -25, 0.68f));
return this;
}
}

+ 76
- 0
src/main/java/pl/asie/minetestbridge/client/util/CharsetFaceBakery.java View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2015, 2016, 2017, 2018 Adrian Siekierka
*
* This file is part of Charset.
*
* Charset is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Charset is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Charset. If not, see <http://www.gnu.org/licenses/>.
*/

package pl.asie.minetestbridge.client.util;

import net.minecraft.client.renderer.block.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.model.ITransformation;
import org.lwjgl.util.vector.Vector3f;

public class CharsetFaceBakery extends FaceBakery {
public static final CharsetFaceBakery INSTANCE = new CharsetFaceBakery();

private CharsetFaceBakery() {

}

private static final float[] faceBrightness = new float[] {
0.5f, 1.0f, 0.8f, 0.8f, 0.6f, 0.6f
};

public static float getFaceBrightness(EnumFacing facing) {
return facing == null ? 1.0f : faceBrightness[facing.ordinal()];
}

public BakedQuad makeBakedQuad(Vector3f min, Vector3f max, int tintIndex,
TextureAtlasSprite icon, EnumFacing facing, ITransformation rot, boolean uvLocked) {
return makeBakedQuad(min, max, tintIndex, RenderUtils.calculateUV(min, max, facing), icon, facing, rot, uvLocked);
}

public BakedQuad makeBakedQuad(Vector3f min, Vector3f max, int tintIndex, float[] uv,
TextureAtlasSprite icon, EnumFacing facing, ITransformation rot, boolean uvLocked) {
boolean hasColorIndex = tintIndex != -1 && ((tintIndex & 0xFF000000) == 0);
boolean hasColor = tintIndex != -1 && ((tintIndex & 0xFF000000) != 0);

BakedQuad quad = makeBakedQuad(
min, max,
new BlockPartFace(null, hasColorIndex ? tintIndex : -1, "", new BlockFaceUV(uv, 0)),
icon, facing, rot, null, uvLocked, true
);

if (hasColor) {
recolorQuad(quad, tintIndex);
}

return quad;
}

private BakedQuad recolorQuad(BakedQuad quad, int color) {
int c = quad.getFormat().getColorOffset() / 4;
int v = 7;
int[] vertexData = quad.getVertexData();
for (int i = 0; i < 4; i++) {
vertexData[v * i + c] = RenderUtils.multiplyColor(vertexData[v * i + c], color);
}
return quad;
}
}

+ 149
- 0
src/main/java/pl/asie/minetestbridge/client/util/NodeboxBakedModel.java View File

@@ -0,0 +1,149 @@
package pl.asie.minetestbridge.client.util;

import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.Vector3d;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraftforge.common.model.ITransformation;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.lwjgl.util.vector.Vector3f;
import pl.asie.minetestbridge.MinetestBridge;
import pl.asie.minetestbridge.client.ModelRegistry;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class NodeboxBakedModel extends BaseBakedModel {
private TextureAtlasSprite[] sprites;
private List<BakedQuad>[] quads;

public NodeboxBakedModel(String owner, LuaValue table, ITransformation transformation, Function<ResourceLocation, TextureAtlasSprite> textureGetter) {
// TODO: Optimize memory usage
quads = (List<BakedQuad>[]) new List[7];
for (int i = 0; i < 7; i++) quads[i] = new ArrayList<>();

LuaTable tilesTable = table.get("tiles").checktable();
LuaValue nodeboxTable = table.get("node_box");

TextureAtlasSprite[] tilesSprite = new TextureAtlasSprite[tilesTable.length()];
for (int i = 0; i < tilesSprite.length; i++) {
System.out.println(ModelRegistry.getTextureName(owner, tilesTable.get(i + 1)));
tilesSprite[i] = textureGetter.apply(new ResourceLocation(ModelRegistry.getTextureName(owner, tilesTable.get(i + 1))));
}

switch (tilesSprite.length) {
case 1:
default:
sprites = new TextureAtlasSprite[] {
tilesSprite[0], tilesSprite[0], tilesSprite[0], tilesSprite[0], tilesSprite[0], tilesSprite[0]
};
break;
case 2:
sprites = new TextureAtlasSprite[] {
tilesSprite[0], tilesSprite[0], tilesSprite[1], tilesSprite[1], tilesSprite[1], tilesSprite[1]
};
break;
case 3:
sprites = new TextureAtlasSprite[] {
tilesSprite[1], tilesSprite[0], tilesSprite[2], tilesSprite[2], tilesSprite[2], tilesSprite[2]
};
break;
case 6:
sprites = new TextureAtlasSprite[] {
tilesSprite[1], tilesSprite[0], tilesSprite[5], tilesSprite[4], tilesSprite[3], tilesSprite[2]
};
break;
}

String type = nodeboxTable.istable() ? nodeboxTable.get("type").optjstring("regular") : "regular";
if ("regular".equals(type)) {
addCube(transformation, new AxisAlignedBB(0,0,0,16,16,16), 0);
} else if ("fixed".equals(type)) {
LuaValue fixed = nodeboxTable.get("fixed");
if (fixed.istable() && fixed.length() >= 1 && fixed.get(1).istable()) {
for (int i = 0; i < fixed.length(); i++) {
addCube(transformation, fixed.get(i + 1), 0);
}
} else {
addCube(transformation, fixed, 0);
}
} else {
MinetestBridge.logger.warn("Unsupported nodebox type " + type + "!");
addCube(transformation, new AxisAlignedBB(0,0,0,16,16,16), 0);
}

addDefaultBlockTransforms();
}

private void addCube(ITransformation t, LuaValue box, int tintIndex) {
if (box.length() == 6) {
addCube(t, new AxisAlignedBB(
(box.get(1).checkdouble() + 0.5) * 16,
(box.get(2).checkdouble() + 0.5) * 16,
(box.get(3).checkdouble() + 0.5) * 16,
(box.get(4).checkdouble() + 0.5) * 16,
(box.get(5).checkdouble() + 0.5) * 16,
(box.get(6).checkdouble() + 0.5) * 16
), tintIndex);
}
}

private void addCube(ITransformation t, AxisAlignedBB box, int tintIndex) {
Vector3f from = new Vector3f((float) box.minX, (float) box.minY, (float) box.minZ);
Vector3f to = new Vector3f((float) box.maxX, (float) box.maxY, (float) box.maxZ);

for (EnumFacing facing : EnumFacing.VALUES) {
int list = 6;
switch (facing) {
case DOWN:
if (box.minY <= 0.0D) {
list = 0;
}
break;
case UP:
if (box.maxY >= 1.0D) {
list = 1;
}
break;
case NORTH:
if (box.minZ <= 0.0D) {
list = 2;
}
break;
case SOUTH:
if (box.maxZ >= 1.0D) {
list = 3;
}
break;
case WEST:
if (box.minX <= 0.0D) {
list = 4;
}
break;
case EAST:
if (box.maxX <= 0.0D) {
list = 5;
}
break;
}

quads[list].add(RenderUtils.createQuad(from, to, facing, sprites[facing.ordinal()], tintIndex, t));
}
}

@Override
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
return quads[side == null ? 6 : side.ordinal()];
}

@Override
public TextureAtlasSprite getParticleTexture() {
return sprites[0];
}
}

+ 278
- 0
src/main/java/pl/asie/minetestbridge/client/util/RenderUtils.java View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 2015, 2016, 2017, 2018 Adrian Siekierka
*
* This file is part of Charset.
*
* Charset is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Charset is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Charset. If not, see <http://www.gnu.org/licenses/>.
*/

package pl.asie.minetestbridge.client.util;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderItem;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ModelRotation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.resources.IResource;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.ITransformation;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector3f;
import pl.asie.minetestbridge.MinetestBridge;
import pl.asie.minetestbridge.util.EntityUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

public final class RenderUtils {
private static RenderItem renderItem;

private RenderUtils() {

}

public static BakedQuad createQuad(Vector3f from, Vector3f to, @Nonnull EnumFacing facing,
TextureAtlasSprite sprite, int tintIndex, ITransformation transformation) {
Vector3f fFrom = new Vector3f(from);
Vector3f fTo = new Vector3f(to);
EnumFacing.AxisDirection facingDir = facing.getAxisDirection();
switch (facing.getAxis()) {
case X:
fFrom.x = fTo.x = facingDir == EnumFacing.AxisDirection.POSITIVE ? to.x : from.x;
break;
case Y:
fFrom.y = fTo.y = facingDir == EnumFacing.AxisDirection.POSITIVE ? to.y : from.y;
break;
case Z:
fFrom.z = fTo.z = facingDir == EnumFacing.AxisDirection.POSITIVE ? to.z : from.z;
break;
}

return CharsetFaceBakery.INSTANCE.makeBakedQuad(fFrom, fTo, tintIndex, sprite, facing, transformation, true);
}

public static float[] calculateUV(Vector3f from, Vector3f to, EnumFacing facing1) {
if (to.y > 16) {
from = new Vector3f(from);