Compare commits

..
9 Commits
Author SHA1 Message Date
glowredman 22dfc1360e Allow colorful Tooltips (#24) 2024-11-13 06:47:10 +00:00
Maya 7bf5935f69 add issue templates 2024-11-11 04:15:39 -06:00
Alexdoru 162de447d5 Change ASM dump folder (#21)
* minor changes to RedirectorTransformer and class dumping

* don't print the stacktrace when failing to write class
2024-10-06 11:49:00 +00:00
Martin Robertz 39ed6607a6 update 2024-10-06 13:35:38 +02:00
Alexdoru 99b815c12e Reduce RAM allocations during rendering (#22)
* edit doc for fluid rendering method + clamp fillRate of the tank between 0 and 1

* init all static fields in the static block

* remove object instantiation that is never used in the following method and assign local variables

* reduce object allocation spam in CCModelLibrary.getRenderMatrix

* fix error in local V value

* remove all object instantiation during rendering to minimize RAM allocation in RenderUtils
2024-10-06 13:33:56 +02:00
Martin Robertz 0f37937ada update 2024-09-01 22:46:57 +02:00
Alexdoru c9d29a5c8e fix logic of the ClassConstantPoolParser (#20) 2024-09-01 22:19:33 +02:00
tth05 ea4f68d163 Add map to provide fast access to all config tags in sub-tree (#18) 2024-07-18 21:37:30 +07:00
Dream Master 549f769747 update 2024-07-17 16:47:04 +07:00
16 changed files with 500 additions and 281 deletions

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
name: Report Bug
description: "Report a bug."
body:
- type: markdown
attributes:
value: "A bug/crash report with sufficient information and logs to reproduce and track down."
- type: input
id: discord
attributes:
label: Your GTNH Discord Username
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
placeholder: "Example: Fake#1234"
- type: input
id: version
attributes:
label: Mod Version
description: "What version of the Mod are you using?"
placeholder: "Example: 1.0.0"
validations:
required: true
- type: textarea
id: report
attributes:
label: Bug Report
description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log."
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
validations:
required: true
- type: dropdown
id: java
attributes:
label: Java Version
description: What Java version are you using? It's worth mentioning that if you play on Java9+ you should try update to latest minor release (e.g. prefer Java 17.0.6 over 17.0.2) of that version.
options:
- Java 8
- Java 9
- Java 11
- Java 17
- Java 19
- Java 20
- Java 21
- Other (Please Specify)
validations:
required: true
- type: textarea
id: modlist
attributes:
label: Mod List or GTNH Pack Version
description: "List of mods, ideally a minimal reproducible set (can be retrieved from latest.log). If using GTNH please indicate pack version and any changed mods, not the entire modlist."
placeholder: "List of mods or GTNH Pack version goes here"
validations:
required: true
- type: checkboxes
id: final
attributes:
label: Final Checklist
description: Certify that you read things
options:
- label: "I have searched the issues and haven't found a similar issue."
required: true
@@ -0,0 +1,28 @@
name: Feature Request
description: "Request a feature."
body:
- type: markdown
attributes:
value: "Please use this form to request features. We ask you check if it was already requested though"
- type: input
id: discord
attributes:
label: Your GTNH Discord Username
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
placeholder: "Example: Wumpus#1234"
- type: textarea
id: request
attributes:
label: Feature Request
description: "Relevant information, as well as relevant images"
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
validations:
required: true
- type: checkboxes
id: final
attributes:
label: Final Checklist
description: Certify that you read things
options:
- label: "I have searched the issues and haven't found a similar issue."
required: true
+12 -1
View File
@@ -79,6 +79,11 @@ accessTransformersFile =
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
usesMixins = false
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
# Mixin classes will have access to "main" classes, but not the other way around.
separateMixinSourceSet =
# Adds some debug arguments like verbose output and class export.
usesMixinDebug = false
@@ -111,9 +116,15 @@ minimizeShadowedDependencies = true
# If disabled, won't rename the shadowed classes.
relocateShadowedDependencies = true
# Adds the GTNH maven, CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
includeWellKnownRepositories = true
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
# list of strings, with the acceptable keys being(case does not matter):
# cursemaven
# modrinth
excludeWellKnownRepositories =
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
+5 -2
View File
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Vendored
+2
View File
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.23'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.29'
}
@@ -83,7 +83,7 @@ public class ClassConstantPoolParser {
if (strLen == bytes.length) {
for (int j = index + 3; j < index + 3 + strLen; j++) {
if (basicClass[j] != bytes[j - (index + 3)]) {
break label;
continue label;
}
}
return true;
@@ -23,11 +23,12 @@ import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.util.ASMifier;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;
public class RedirectorTransformer implements IClassTransformer {
import codechicken.core.launch.CodeChickenCorePlugin;
public class RedirectorTransformer implements IClassTransformer, Opcodes {
private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("ccl.dumpClass", "false"));
private static final String RenderStateClass = "codechicken/lib/render/CCRenderState";
@@ -90,66 +91,63 @@ public class RedirectorTransformer implements IClassTransformer {
cr.accept(cn, 0);
boolean changed = false;
// spotless:off
for (MethodNode mn : cn.methods) {
for (AbstractInsnNode node : mn.instructions.toArray()) {
if (node instanceof FieldInsnNode fNode) {
if (node.getOpcode() == Opcodes.GETSTATIC && redirectedFields.contains(fNode.name)
&& fNode.owner.equals(RenderStateClass)) {
mn.instructions.insertBefore(
fNode,
new MethodInsnNode(
Opcodes.INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;"));
fNode.setOpcode(Opcodes.GETFIELD);
if (node.getOpcode() == GETSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) {
mn.instructions.insertBefore(fNode,
new MethodInsnNode(
INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
fNode.setOpcode(GETFIELD);
changed = true;
} else if (node.getOpcode() == Opcodes.PUTSTATIC
&& (redirectedFields.contains(fNode.name) && fNode.owner.equals(RenderStateClass))) {
InsnList beforePut = new InsnList();
beforePut.add(
new MethodInsnNode(
Opcodes.INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;"));
beforePut.add(new InsnNode(Opcodes.SWAP));
mn.instructions.insertBefore(fNode, beforePut);
fNode.setOpcode(Opcodes.PUTFIELD);
changed = true;
}
} else if (node.getOpcode() == PUTSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) {
InsnList list = new InsnList();
list.add(new MethodInsnNode(
INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
list.add(new InsnNode(SWAP));
mn.instructions.insertBefore(fNode, list);
fNode.setOpcode(PUTFIELD);
changed = true;
}
} else if (node instanceof MethodInsnNode mNode) {
if (node.getOpcode() == Opcodes.INVOKESTATIC && redirectedSimpleMethods.contains(mNode.name)
&& mNode.owner.equals(RenderStateClass)) {
mn.instructions.insertBefore(
mNode,
new MethodInsnNode(
Opcodes.INVOKESTATIC,
mNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;"));
mNode.setOpcode(Opcodes.INVOKEVIRTUAL);
if (node.getOpcode() == INVOKESTATIC && RenderStateClass.equals(mNode.owner) && redirectedSimpleMethods.contains(mNode.name)) {
mn.instructions.insertBefore(mNode,
new MethodInsnNode(
INVOKESTATIC,
mNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
mNode.setOpcode(INVOKEVIRTUAL);
mNode.name = mNode.name + "Instance";
changed = true;
} else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL && mNode.owner.equals(RenderStateClass)
&& (redirectedSimpleMethods.contains(mNode.name)
|| redirectedMethods.contains(mNode.name))) {
// Handle mods that updated to previously new API
mNode.name = mNode.name + "Instance";
changed = true;
}
} else if (node.getOpcode() == INVOKEVIRTUAL && RenderStateClass.equals(mNode.owner)
&& (redirectedSimpleMethods.contains(mNode.name) || redirectedMethods.contains(mNode.name))) {
// Handle mods that updated to previously new API
mNode.name = mNode.name + "Instance";
changed = true;
}
}
}
}
// spotless:on
if (changed) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
final byte[] bytes = cw.toByteArray();
if (DUMP_CLASSES) {
saveTransformedClass(bytes, transformedName);
saveTransformedClass(basicClass, transformedName + "_original");
saveTransformedClass(basicClass, transformedName + "_PRE");
saveTransformedClass(bytes, transformedName + "_POST");
}
return bytes;
}
@@ -158,13 +156,9 @@ public class RedirectorTransformer implements IClassTransformer {
private File outputDir = null;
private void saveTransformedClass(final byte[] data, final String transformedName) {
if (!DUMP_CLASSES) {
return;
}
private void saveTransformedClass(final byte[] data, final String classname) {
if (outputDir == null) {
outputDir = new File(Launch.minecraftHome, "ASM_REDIRECTOR");
outputDir = new File(Launch.minecraftHome, "ASM_CCL" + File.separatorChar + "REDIRECTOR");
try {
FileUtils.deleteDirectory(outputDir);
} catch (IOException ignored) {}
@@ -173,40 +167,34 @@ public class RedirectorTransformer implements IClassTransformer {
outputDir.mkdirs();
}
}
final String fileName = transformedName.replace('.', File.separatorChar);
final String fileName = classname.replace('.', File.separatorChar);
final File classFile = new File(outputDir, fileName + ".class");
final File bytecodeFile = new File(outputDir, fileName + "_BYTE.txt");
final File asmifiedFile = new File(outputDir, fileName + "_ASM.txt");
final File outDir = classFile.getParentFile();
if (!outDir.exists()) {
// noinspection ResultOfMethodCallIgnored
outDir.mkdirs();
}
if (classFile.exists()) {
// noinspection ResultOfMethodCallIgnored
classFile.delete();
}
try (final OutputStream output = Files.newOutputStream(classFile.toPath())) {
output.write(data);
CodeChickenCorePlugin.logger.info("Saved class (byte[]) to " + classFile.toPath());
} catch (IOException e) {
e.printStackTrace();
CodeChickenCorePlugin.logger.error("Could not save class (byte[]) " + classname);
}
if (bytecodeFile.exists()) {
// noinspection ResultOfMethodCallIgnored
bytecodeFile.delete();
}
try (final OutputStream output = Files.newOutputStream(bytecodeFile.toPath())) {
final ClassReader classReader = new ClassReader(data);
classReader.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(output)), 0);
CodeChickenCorePlugin.logger.info("Saved class (bytecode) to " + bytecodeFile.toPath());
} catch (IOException e) {
e.printStackTrace();
}
if (asmifiedFile.exists()) {
asmifiedFile.delete();
}
try (final OutputStream output = Files.newOutputStream(asmifiedFile.toPath())) {
final ClassReader classReader = new ClassReader(data);
classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(output)), 0);
} catch (IOException e) {
e.printStackTrace();
CodeChickenCorePlugin.logger.error("Could not save class (bytecode) " + classname);
}
}
}
@@ -6,8 +6,10 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TreeMap;
public abstract class ConfigTagParent {
@@ -21,25 +23,30 @@ public abstract class ConfigTagParent {
}
public int compare(ConfigTag o1, ConfigTag o2) {
if (o1.position != o2.position) return compareInt(o1.position, o2.position);
if (o1.position != o2.position) return Integer.compare(o1.position, o2.position);
if (o1.brace != o2.brace) return o1.brace ? 1 : -1; // braced one goes after
switch (sortMode) {
case 1:
if (o1.value == o2.value) return 0;
if (o1.value == null) return 1;
if (o2.value == null) return -1;
return o1.value.compareTo(o2.value);
default:
return o1.name.compareTo(o2.name);
if (sortMode == 1) {
if (Objects.equals(o1.value, o2.value)) return 0;
if (o1.value == null) return 1;
if (o2.value == null) return -1;
return o1.value.compareTo(o2.value);
} else {
return o1.name.compareTo(o2.name);
}
}
private int compareInt(int a, int b) {
return a == b ? 0 : a < b ? -1 : 1;
}
}
private TreeMap<String, ConfigTag> childtags = new TreeMap<String, ConfigTag>();
/**
* The immediate child tags of this tag
*/
private final TreeMap<String, ConfigTag> childtags = new TreeMap<>();
/**
* A map of all tags in the tree, meaning all tags in this tag and all tags in child tags (recursively). Allows for
* quick access to any tag in the tree, without the need to traverse the tree part by part.
*/
private final Map<String, ConfigTag> allTagsInTree = new HashMap<>();
public String comment;
/**
* 0 = name, 1 = value
@@ -88,7 +95,7 @@ public abstract class ConfigTagParent {
}
public boolean containsTag(String tagname) {
return getTag(tagname, false) != null;
return allTagsInTree.get(tagname) != null;
}
public ConfigTag getNewTag(String tagname) {
@@ -96,6 +103,12 @@ public abstract class ConfigTagParent {
}
public ConfigTag getTag(String tagname, boolean create) {
ConfigTag tag = allTagsInTree.get(tagname);
if (tag == null && create) return getTagRecursive(tagname, create);
return tag;
}
public ConfigTag getTagRecursive(String tagname, boolean create) {
int dotpos = tagname.indexOf(".");
String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos);
ConfigTag basetag = childtags.get(basetagname);
@@ -115,6 +128,8 @@ public abstract class ConfigTagParent {
}
public boolean removeTag(String tagname) {
removeChildFromFlatMap(tagname);
ConfigTag tag = getTag(tagname, false);
if (tag == null) return false;
@@ -131,6 +146,22 @@ public abstract class ConfigTagParent {
public void addChild(ConfigTag tag) {
childtags.put(tag.name, tag);
addChildToFlatMap(tag.name, tag);
}
private void addChildToFlatMap(String path, ConfigTag tag) {
allTagsInTree.put(path, tag);
// Stupid cast but these two garbage classes are interlinked anyway
if ((this instanceof ConfigTag t) && t.parent != null) t.parent.addChildToFlatMap(t.name + "." + path, tag);
}
private void removeChildFromFlatMap(String path) {
allTagsInTree.remove(path);
// Stupid cast but these two garbage classes are interlinked anyway
if ((this instanceof ConfigTag t) && t.parent != null) t.parent.removeChildFromFlatMap(t.name + "." + path);
}
public <T extends ConfigTag> ArrayList<T> getSortedTagList() {
+23 -13
View File
@@ -162,6 +162,11 @@ public class GuiDraw {
}
public static void drawMultilineTip(FontRenderer font, int x, int y, List<String> list) {
drawMultilineTip(font, x, y, list, 0xf0100010, 0xf0100010, 0x505000ff, 0x5028007F);
}
public static void drawMultilineTip(FontRenderer font, int x, int y, List<String> list, int bgStart, int bgEnd,
int borderStart, int borderEnd) {
if (list.isEmpty()) return;
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
@@ -189,7 +194,7 @@ public class GuiDraw {
y = (int) MathHelper.clip(y, 8, displaySize().height - 8 - h);
gui.incZLevel(300);
drawTooltipBox(x - 4, y - 4, w + 7, h + 7);
drawTooltipBox(x - 4, y - 4, w + 7, h + 7, bgStart, bgEnd, borderStart, borderEnd);
for (String s : list) {
ITooltipLineHandler line = getTipLine(s);
if (line != null) {
@@ -210,18 +215,23 @@ public class GuiDraw {
}
public static void drawTooltipBox(int x, int y, int w, int h) {
int bg = 0xf0100010;
drawGradientRect(x + 1, y, w - 1, 1, bg, bg);
drawGradientRect(x + 1, y + h, w - 1, 1, bg, bg);
drawGradientRect(x + 1, y + 1, w - 1, h - 1, bg, bg); // center
drawGradientRect(x, y + 1, 1, h - 1, bg, bg);
drawGradientRect(x + w, y + 1, 1, h - 1, bg, bg);
int grad1 = 0x505000ff;
int grad2 = 0x5028007F;
drawGradientRect(x + 1, y + 2, 1, h - 3, grad1, grad2);
drawGradientRect(x + w - 1, y + 2, 1, h - 3, grad1, grad2);
drawTooltipBox(x, y, w, h, 0xf0100010, 0xf0100010, 0x505000ff, 0x5028007F);
}
drawGradientRect(x + 1, y + 1, w - 1, 1, grad1, grad1);
drawGradientRect(x + 1, y + h - 1, w - 1, 1, grad2, grad2);
public static void drawTooltipBox(int x, int y, int w, int h, int bgStart, int bgEnd, int borderStart,
int borderEnd) {
// spotless:off
// draw background
drawGradientRect(x + 1, y, w - 1, 1, bgStart, bgStart); // top
drawGradientRect(x + 1, y + h, w - 1, 1, bgEnd, bgEnd); // bottom
drawGradientRect(x + 1, y + 1, w - 1, h - 1, bgStart, bgEnd); // center
drawGradientRect(x, y + 1, 1, h - 1, bgStart, bgEnd); // left
drawGradientRect(x + w, y + 1, 1, h - 1, bgStart, bgEnd); // right
// draw inner border
drawGradientRect(x + 1, y + 2, 1, h - 3, borderStart, borderEnd); // left
drawGradientRect(x + w - 1, y + 2, 1, h - 3, borderStart, borderEnd); // right
drawGradientRect(x + 1, y + 1, w - 1, 1, borderStart, borderStart); // top
drawGradientRect(x + 1, y + h - 1, w - 1, 1, borderEnd, borderEnd); // bottom
// spotless:on
}
}
@@ -5,7 +5,6 @@ import static codechicken.lib.math.MathHelper.phi;
import codechicken.lib.vec.Matrix4;
import codechicken.lib.vec.Quat;
import codechicken.lib.vec.Rotation;
import codechicken.lib.vec.Scale;
import codechicken.lib.vec.Vector3;
public class CCModelLibrary {
@@ -82,7 +81,12 @@ public class CCModelLibrary {
i++;
}
@Deprecated
public static Matrix4 getRenderMatrix(Vector3 position, Rotation rotation, double scale) {
return new Matrix4().translate(position).apply(new Scale(scale)).apply(rotation);
return new Matrix4().translate(position).scale(scale).apply(rotation);
}
public static Matrix4 getRenderMatrix(double posX, double posY, double posZ, Rotation rotation, double scale) {
return new Matrix4().translate(posX, posY, posZ).scale(scale).apply(rotation);
}
}
@@ -13,6 +13,7 @@ import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraftforge.client.IItemRenderer;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.fluids.Fluid;
@@ -26,87 +27,130 @@ import codechicken.lib.vec.Vector3;
public class RenderUtils {
static Vector3[] vectors = new Vector3[8];
static RenderItem uniformRenderItem = new RenderItem() {
public boolean shouldBob() {
return false;
}
};
static RenderItem uniformRenderItem;
static EntityItem entityItem;
static {
for (int i = 0; i < vectors.length; i++) vectors[i] = new Vector3();
uniformRenderItem = new RenderItem() {
public boolean shouldBob() {
return false;
}
};
uniformRenderItem.setRenderManager(RenderManager.instance);
entityItem = new EntityItem(null);
entityItem.hoverStart = 0;
}
@Deprecated
public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon,
double res) {
// spotless:off
renderFluidQuad(
point2,
vectors[0].set(point4).subtract(point1),
vectors[1].set(point1).subtract(point2),
icon,
res);
point2.x, point2.y, point2.z,
point4.x - point1.x, point4.y - point1.y, point4.z - point1.z,
point1.x - point2.x, point1.y - point2.y, point1.z - point2.z,
icon, res);
}
/**
* Draws a tessellated quadrilateral bottom to top, left to right
*
*
* @param base The bottom left corner of the quad
* @param wide The bottom of the quad
* @param high The left side of the quad
* @param res Units per icon
*/
@Deprecated
public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) {
Tessellator t = Tessellator.instance;
renderFluidQuad(
base.x, base.y, base.z,
wide.x, wide.y, wide.z,
wide.x, wide.y, wide.z,
icon, res);
}
double u1 = icon.getMinU();
/**
* Draws a tessellated quadrilateral bottom to top, left to right
* <p>
* base : The bottom left corner of the quad
* <p>
* wide : The bottom of the quad
* <p>
* high : The left side of the quad
* <p>
* res : Units per icon
*/
public static void renderFluidQuad(
double baseX, double baseY, double baseZ,
double wideX, double wideY, double wideZ,
double highX, double highY, double highZ,
IIcon icon, double res) {
Tessellator tessellator = Tessellator.instance;
double u = icon.getMinU();
double du = icon.getMaxU() - icon.getMinU();
double v2 = icon.getMaxV();
double v = icon.getMinV();
double dv = icon.getMaxV() - icon.getMinV();
double wlen = wide.mag();
double hlen = high.mag();
double wideLen = Math.sqrt(wideX * wideX + wideY * wideY + wideZ * wideZ);
double highLen = Math.sqrt(highX * highX + highY * highY + highZ * highZ);
double x = 0;
while (x < wlen) {
double rx = wlen - x;
while (x < wideLen) {
double rx = wideLen - x;
if (rx > res) rx = res;
double y = 0;
while (y < hlen) {
double ry = hlen - y;
while (y < highLen) {
double ry = highLen - y;
if (ry > res) ry = res;
Vector3 dx1 = vectors[2].set(wide).multiply(x / wlen);
Vector3 dx2 = vectors[3].set(wide).multiply((x + rx) / wlen);
Vector3 dy1 = vectors[4].set(high).multiply(y / hlen);
Vector3 dy2 = vectors[5].set(high).multiply((y + ry) / hlen);
final double mult1 = x / wideLen;
double dx1X = wideX * mult1;
double dx1Y = wideY * mult1;
double dx1Z = wideZ * mult1;
t.addVertexWithUV(
base.x + dx1.x + dy2.x,
base.y + dx1.y + dy2.y,
base.z + dx1.z + dy2.z,
u1,
v2 - ry / res * dv);
t.addVertexWithUV(base.x + dx1.x + dy1.x, base.y + dx1.y + dy1.y, base.z + dx1.z + dy1.z, u1, v2);
t.addVertexWithUV(
base.x + dx2.x + dy1.x,
base.y + dx2.y + dy1.y,
base.z + dx2.z + dy1.z,
u1 + rx / res * du,
v2);
t.addVertexWithUV(
base.x + dx2.x + dy2.x,
base.y + dx2.y + dy2.y,
base.z + dx2.z + dy2.z,
u1 + rx / res * du,
v2 - ry / res * dv);
final double mult2 = (x + rx) / wideLen;
double dx2X = wideX * mult2;
double dx2Y = wideY * mult2;
double dx2Z = wideZ * mult2;
final double mult3 = y / highLen;
double dy1X = highX * mult3;
double dy1Y = highY * mult3;
double dy1Z = highZ * mult3;
final double mult4 = (y + ry) / highLen;
double dy2X = highX * mult4;
double dy2Y = highY * mult4;
double dy2Z = highZ * mult4;
tessellator.addVertexWithUV(
baseX + dx1X + dy2X,
baseY + dx1Y + dy2Y,
baseZ + dx1Z + dy2Z,
u,
v + ry / res * dv);
tessellator.addVertexWithUV(
baseX + dx1X + dy1X,
baseY + dx1Y + dy1Y,
baseZ + dx1Z + dy1Z,
u,
v);
tessellator.addVertexWithUV(
baseX + dx2X + dy1X,
baseY + dx2Y + dy1Y,
baseZ + dx2Z + dy1Z,
u + rx / res * du,
v);
tessellator.addVertexWithUV(
baseX + dx2X + dy2X,
baseY + dx2Y + dy2Y,
baseZ + dx2Z + dy2Z,
u + rx / res * du,
v + ry / res * dv);
y += ry;
}
@@ -115,132 +159,130 @@ public class RenderUtils {
}
}
public static void translateToWorldCoords(Entity entity, float frame) {
double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * frame;
double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * frame;
double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * frame;
public static void translateToWorldCoords(Entity entity, float partialTicks) {
double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks;
double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks;
double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks;
GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ);
}
public static void drawCuboidOutline(Cuboid6 c) {
Tessellator var2 = Tessellator.instance;
var2.startDrawing(3);
var2.addVertex(c.min.x, c.min.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.max.z);
var2.addVertex(c.min.x, c.min.y, c.max.z);
var2.addVertex(c.min.x, c.min.y, c.min.z);
var2.draw();
var2.startDrawing(3);
var2.addVertex(c.min.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.max.y, c.max.z);
var2.addVertex(c.min.x, c.max.y, c.max.z);
var2.addVertex(c.min.x, c.max.y, c.min.z);
var2.draw();
var2.startDrawing(1);
var2.addVertex(c.min.x, c.min.y, c.min.z);
var2.addVertex(c.min.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.min.z);
var2.addVertex(c.max.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.max.z);
var2.addVertex(c.max.x, c.max.y, c.max.z);
var2.addVertex(c.min.x, c.min.y, c.max.z);
var2.addVertex(c.min.x, c.max.y, c.max.z);
var2.draw();
Tessellator tess = Tessellator.instance;
tess.startDrawing(3);
tess.addVertex(c.min.x, c.min.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.max.z);
tess.addVertex(c.min.x, c.min.y, c.max.z);
tess.addVertex(c.min.x, c.min.y, c.min.z);
tess.draw();
tess.startDrawing(3);
tess.addVertex(c.min.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.max.y, c.max.z);
tess.addVertex(c.min.x, c.max.y, c.max.z);
tess.addVertex(c.min.x, c.max.y, c.min.z);
tess.draw();
tess.startDrawing(1);
tess.addVertex(c.min.x, c.min.y, c.min.z);
tess.addVertex(c.min.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.min.z);
tess.addVertex(c.max.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.max.z);
tess.addVertex(c.max.x, c.max.y, c.max.z);
tess.addVertex(c.min.x, c.min.y, c.max.z);
tess.addVertex(c.min.x, c.max.y, c.max.z);
tess.draw();
}
public static void renderFluidCuboid(CCRenderState state, Cuboid6 bound, IIcon tex, double res) {
renderFluidQuad( // bottom
new Vector3(bound.min.x, bound.min.y, bound.min.z),
new Vector3(bound.max.x, bound.min.y, bound.min.z),
new Vector3(bound.max.x, bound.min.y, bound.max.z),
new Vector3(bound.min.x, bound.min.y, bound.max.z),
tex,
res);
renderFluidQuad( // top
new Vector3(bound.min.x, bound.max.y, bound.min.z),
new Vector3(bound.min.x, bound.max.y, bound.max.z),
new Vector3(bound.max.x, bound.max.y, bound.max.z),
new Vector3(bound.max.x, bound.max.y, bound.min.z),
tex,
res);
renderFluidQuad( // -x
new Vector3(bound.min.x, bound.max.y, bound.min.z),
new Vector3(bound.min.x, bound.min.y, bound.min.z),
new Vector3(bound.min.x, bound.min.y, bound.max.z),
new Vector3(bound.min.x, bound.max.y, bound.max.z),
tex,
res);
renderFluidQuad( // +x
new Vector3(bound.max.x, bound.max.y, bound.max.z),
new Vector3(bound.max.x, bound.min.y, bound.max.z),
new Vector3(bound.max.x, bound.min.y, bound.min.z),
new Vector3(bound.max.x, bound.max.y, bound.min.z),
tex,
res);
renderFluidQuad( // -z
new Vector3(bound.max.x, bound.max.y, bound.min.z),
new Vector3(bound.max.x, bound.min.y, bound.min.z),
new Vector3(bound.min.x, bound.min.y, bound.min.z),
new Vector3(bound.min.x, bound.max.y, bound.min.z),
tex,
res);
renderFluidQuad( // +z
new Vector3(bound.min.x, bound.max.y, bound.max.z),
new Vector3(bound.min.x, bound.min.y, bound.max.z),
new Vector3(bound.max.x, bound.min.y, bound.max.z),
new Vector3(bound.max.x, bound.max.y, bound.max.z),
tex,
res);
renderFluidCuboid(bound, tex, res);
}
public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) {
renderFluidCuboid(CCRenderState.instance(), bound, tex, res);
final double minX = bound.min.x;
final double minY = bound.min.y;
final double minZ = bound.min.z;
final double maxX = bound.max.x;
final double maxY = bound.max.y;
final double maxZ = bound.max.z;
renderFluidQuad( // bottom
minX, minY, minZ,
maxX - minX, 0, 0,
0, 0, maxZ - minZ,
tex, res);
renderFluidQuad( // top
minX, maxY, minZ,
0, 0, maxZ - minZ,
maxX - minX, 0, 0,
tex, res);
renderFluidQuad( // -x
minX, maxY, minZ,
0, minY - maxY, 0,
0, 0, maxZ - minZ,
tex, res);
renderFluidQuad( // +x
maxX, maxY, maxZ,
0, minY - maxY, 0,
0, 0, minZ - maxZ,
tex, res);
renderFluidQuad( // -z
maxX, maxY, minZ,
0, minY - maxY, 0,
minX - maxX, 0, 0,
tex, res);
renderFluidQuad( // +z
minX, maxY, maxZ,
0, minY - maxY, 0,
maxX - minX, 0, 0,
tex, res);
}
// spotless:on
public static void renderBlockOverlaySide(int x, int y, int z, int side, double tx1, double tx2, double ty1,
double ty2) {
double[] points = new double[] { x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009 };
Tessellator tessellator = Tessellator.instance;
final double minX = x - 0.009;
final double maxX = x + 1.009;
final double minY = y - 0.009;
final double maxY = y + 1.009;
final double minZ = z - 0.009;
final double maxZ = z + 1.009;
switch (side) {
case 0:
tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2);
tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2);
tessellator.addVertexWithUV(minX, minY, minZ, tx1, ty1);
tessellator.addVertexWithUV(maxX, minY, minZ, tx2, ty1);
tessellator.addVertexWithUV(maxX, minY, maxZ, tx2, ty2);
tessellator.addVertexWithUV(minX, minY, maxZ, tx1, ty2);
break;
case 1:
tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty2);
tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty2);
tessellator.addVertexWithUV(maxX, maxY, minZ, tx2, ty1);
tessellator.addVertexWithUV(minX, maxY, minZ, tx1, ty1);
tessellator.addVertexWithUV(minX, maxY, maxZ, tx1, ty2);
tessellator.addVertexWithUV(maxX, maxY, maxZ, tx2, ty2);
break;
case 2:
tessellator.addVertexWithUV(points[0], points[3], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[1], points[3], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[4], tx1, ty2);
tessellator.addVertexWithUV(points[0], points[2], points[4], tx2, ty2);
tessellator.addVertexWithUV(minX, maxY, minZ, tx2, ty1);
tessellator.addVertexWithUV(maxX, maxY, minZ, tx1, ty1);
tessellator.addVertexWithUV(maxX, minY, minZ, tx1, ty2);
tessellator.addVertexWithUV(minX, minY, minZ, tx2, ty2);
break;
case 3:
tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty1);
tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2);
tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2);
tessellator.addVertexWithUV(maxX, maxY, maxZ, tx2, ty1);
tessellator.addVertexWithUV(minX, maxY, maxZ, tx1, ty1);
tessellator.addVertexWithUV(minX, minY, maxZ, tx1, ty2);
tessellator.addVertexWithUV(maxX, minY, maxZ, tx2, ty2);
break;
case 4:
tessellator.addVertexWithUV(points[0], points[3], points[5], tx2, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty2);
tessellator.addVertexWithUV(points[0], points[2], points[5], tx2, ty2);
tessellator.addVertexWithUV(minX, maxY, maxZ, tx2, ty1);
tessellator.addVertexWithUV(minX, maxY, minZ, tx1, ty1);
tessellator.addVertexWithUV(minX, minY, minZ, tx1, ty2);
tessellator.addVertexWithUV(minX, minY, maxZ, tx2, ty2);
break;
case 5:
tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[1], points[3], points[5], tx1, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[5], tx1, ty2);
tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty2);
tessellator.addVertexWithUV(maxX, maxY, minZ, tx2, ty1);
tessellator.addVertexWithUV(maxX, maxY, maxZ, tx1, ty1);
tessellator.addVertexWithUV(maxX, minY, maxZ, tx1, ty2);
tessellator.addVertexWithUV(maxX, minY, minZ, tx2, ty2);
break;
}
}
@@ -276,66 +318,76 @@ public class RenderUtils {
GL11.glDisable(GL11.GL_BLEND);
}
public static double fluidDensityToAlpha(double density) {
return Math.pow(density, 0.4);
public static double fluidDensityToAlpha(double d) {
return Math.pow(d, 0.4);
}
/**
* Renders a fluid within a bounding box. If the fluid is a liquid it will render as a normal tank with height equal
* to density/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to density.
* to fillRate/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to fillRate.
* Warning, bound will be mutated if the fluid is a liquid
*
* @param stack The fluid to render.
* @param bound The box within which the fluid is contained.
* @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids
* this determines the height.
* @param res The resolution to render at.
*
* @param stack The fluid to render.
* @param bound The bounding box within which the fluid is contained.
* @param fillRate The volume of fluid / the capacity of the tank. This is a double between 0 and 1.
* @param res The resolution to render at.
*/
public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cuboid6 bound, double density,
public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cuboid6 bound, double fillRate,
double res) {
if (!shouldRenderFluid(stack)) return;
fillRate = MathHelper.clamp_double(fillRate, 0d, 1d);
int alpha = 255;
if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255);
else bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * density;
if (stack.getFluid().isGaseous()) {
alpha = (int) (fluidDensityToAlpha(fillRate) * 255);
} else {
bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * fillRate;
}
IIcon tex = prepareFluidRender(state, stack, alpha);
state.startDrawingInstance();
renderFluidCuboid(state, bound, tex, res);
renderFluidCuboid(bound, tex, res);
state.drawInstance();
postFluidRender();
}
public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) {
renderFluidCuboid(CCRenderState.instance(), stack, bound, density, res);
/**
* Renders a fluid within a bounding box. If the fluid is a liquid it will render as a normal tank with height equal
* to fillRate/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to fillRate.
* Warning, bound will be mutated if the fluid is a liquid
*
* @param stack The fluid to render.
* @param bound The bounding box within which the fluid is contained.
* @param fillRate The volume of fluid / the capacity of the tank. This is a double between 0 and 1.
* @param res The resolution to render at.
*/
public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double fillRate, double res) {
renderFluidCuboid(CCRenderState.instance(), stack, bound, fillRate, res);
}
public static void renderFluidGauge(CCRenderState state, FluidStack stack, Rectangle4i rect, double density,
public static void renderFluidGauge(CCRenderState state, FluidStack stack, Rectangle4i rect, double fillRate,
double res) {
if (!shouldRenderFluid(stack)) return;
fillRate = MathHelper.clamp_double(fillRate, 0d, 1d);
int alpha = 255;
if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255);
else {
int height = (int) (rect.h * density);
if (stack.getFluid().isGaseous()) {
alpha = (int) (fluidDensityToAlpha(fillRate) * 255);
} else {
int height = (int) (rect.h * fillRate);
rect.y += rect.h - height;
rect.h = height;
}
IIcon tex = prepareFluidRender(state, stack, alpha);
state.startDrawingInstance();
renderFluidQuad(
new Vector3(rect.x, rect.y + rect.h, 0),
new Vector3(rect.w, 0, 0),
new Vector3(0, -rect.h, 0),
tex,
res);
renderFluidQuad(rect.x, rect.y + rect.h, 0, rect.w, 0, 0, 0, -rect.h, 0, tex, res);
state.drawInstance();
postFluidRender();
}
public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) {
renderFluidGauge(CCRenderState.instance(), stack, rect, density, res);
public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double fillRate, double res) {
renderFluidGauge(CCRenderState.instance(), stack, rect, fillRate, res);
}
/**
@@ -347,7 +399,7 @@ public class RenderUtils {
/**
* Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately
*
*
* @param spin The spin angle of the item around the y axis in degrees
*/
public static void renderItemUniform(ItemStack item, double spin) {
+29 -1
View File
@@ -19,7 +19,10 @@ public class Matrix4 extends Transformation implements Copyable<Matrix4> {
.asDoubleBuffer();
// m<row><column>
public double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33;
public double m00, m01, m02, m03;
public double m10, m11, m12, m13;
public double m20, m21, m22, m23;
public double m30, m31, m32, m33;
public Matrix4() {
m00 = m11 = m22 = m33 = 1;
@@ -65,6 +68,15 @@ public class Matrix4 extends Transformation implements Copyable<Matrix4> {
return this;
}
public Matrix4 translate(double x, double y, double z) {
m03 += m00 * x + m01 * y + m02 * z;
m13 += m10 * x + m11 * y + m12 * z;
m23 += m20 * x + m21 * y + m22 * z;
m33 += m30 * x + m31 * y + m32 * z;
return this;
}
public Matrix4 scale(Vector3 vec) {
m00 *= vec.x;
m10 *= vec.x;
@@ -82,6 +94,22 @@ public class Matrix4 extends Transformation implements Copyable<Matrix4> {
return this;
}
public Matrix4 scale(double scale) {
m00 *= scale;
m10 *= scale;
m20 *= scale;
m30 *= scale;
m01 *= scale;
m11 *= scale;
m21 *= scale;
m31 *= scale;
m02 *= scale;
m12 *= scale;
m22 *= scale;
m32 *= scale;
return this;
}
public Matrix4 rotate(double angle, Vector3 axis) {
double c = Math.cos(angle);
double s = Math.sin(angle);
@@ -29,10 +29,10 @@ public class Vector3 implements Copyable<Vector3> {
public Vector3() {}
public Vector3(double d, double d1, double d2) {
x = d;
y = d1;
z = d2;
public Vector3(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3(Vector3 vec) {
@@ -398,7 +398,7 @@ public class Vector3 implements Copyable<Vector3> {
/**
* Equals method with tolerance
*
*
* @return true if this is equal to v within +-1E-5
*/
public boolean equalsT(Vector3 v) {