mirror of
https://github.com/GTNewHorizons/CodeChickenCore.git
synced 2026-10-27 06:43:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb98bdc6d4 | ||
|
|
4e5bcf829c | ||
|
|
678970e48b | ||
|
|
5ad7ebe1ac | ||
|
|
033009fed5 | ||
|
|
acd863e748 | ||
|
|
850e2b9368 | ||
|
|
4713f7aebd | ||
|
|
b999279656 | ||
|
|
1879ba2071 | ||
|
|
9d600169ac | ||
|
|
4e7eb37f3f | ||
|
|
22dfc1360e | ||
|
|
7bf5935f69 | ||
|
|
162de447d5 | ||
|
|
39ed6607a6 | ||
|
|
99b815c12e | ||
|
|
0f37937ada | ||
|
|
c9d29a5c8e | ||
|
|
ea4f68d163 | ||
|
|
549f769747 | ||
|
|
cba2e0f642 | ||
|
|
3740253590 |
No files matched your search
@@ -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
|
||||
@@ -3,3 +3,8 @@
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhconvention'
|
||||
}
|
||||
|
||||
minecraft {
|
||||
//extraRunJvmArguments.add("-Dccc.dev.runtimePublic=true")
|
||||
//extraRunJvmArguments.add("-Dccc.dev.deobfuscate=true")
|
||||
}
|
||||
+17
-3
@@ -14,7 +14,7 @@ modId = CodeChickenCore
|
||||
modGroup = codechicken
|
||||
|
||||
# Whether to use modGroup as the maven publishing group.
|
||||
# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods.
|
||||
# When false, com.github.GTNewHorizons is used.
|
||||
useModGroupForPublishing = false
|
||||
|
||||
# Updates your build.gradle and settings.gradle automatically whenever an update is available.
|
||||
@@ -55,6 +55,9 @@ generateGradleTokenClass = codechicken.core.asm.Tags
|
||||
# Name of the token containing the project's current version to generate/replace.
|
||||
gradleTokenVersion = VERSION
|
||||
|
||||
# [DEPRECATED] Mod Group replacement token.
|
||||
gradleTokenGroupName =
|
||||
|
||||
# [DEPRECATED]
|
||||
# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java
|
||||
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||
@@ -76,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
|
||||
|
||||
@@ -108,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.
|
||||
@@ -131,7 +145,7 @@ modrinthProjectId = codechickencore-unofficial
|
||||
# type can be one of [project, version],
|
||||
# and the name is the Modrinth project or version slug/id of the other mod.
|
||||
# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech
|
||||
# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true
|
||||
# Note: UniMixins is automatically set as a required dependency if usesMixins = true.
|
||||
modrinthRelations =
|
||||
|
||||
# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -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.13-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -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,7 @@ 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\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -203,7 +205,7 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
Vendored
+2
@@ -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,4 +1,5 @@
|
||||
// Add any additional repositiroes for your dependencies here
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.23'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.41'
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package codechicken.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -22,6 +23,7 @@ import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModClassLoader;
|
||||
import cpw.mods.fml.relauncher.CoreModManager;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ClassDiscoverer {
|
||||
|
||||
public IStringMatcher matcher;
|
||||
@@ -35,17 +37,12 @@ public class ClassDiscoverer {
|
||||
for (int i = 0; i < superclasses.length; i++)
|
||||
this.superclasses[i] = superclasses[i].getName().replace('.', '/');
|
||||
|
||||
classes = new ArrayList<Class<?>>();
|
||||
classes = new ArrayList<>();
|
||||
modClassLoader = (ModClassLoader) Loader.instance().getModClassLoader();
|
||||
}
|
||||
|
||||
public ClassDiscoverer(Class<?>... superclasses) {
|
||||
this(new IStringMatcher() {
|
||||
|
||||
public boolean matches(String test) {
|
||||
return true;
|
||||
}
|
||||
}, superclasses);
|
||||
this(test -> true, superclasses);
|
||||
}
|
||||
|
||||
public ArrayList<Class<?>> findClasses() {
|
||||
@@ -63,7 +60,7 @@ public class ClassDiscoverer {
|
||||
byte[] bytes = Launch.classLoader.getClassBytes(classname);
|
||||
if (bytes == null) return;
|
||||
|
||||
ClassNode cnode = ASMHelper.createClassNode(bytes);
|
||||
ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.SKIP_CODE);
|
||||
for (String superclass : superclasses)
|
||||
if (!cnode.interfaces.contains(superclass) && !cnode.superName.equals(superclass)) return;
|
||||
|
||||
@@ -86,7 +83,7 @@ public class ClassDiscoverer {
|
||||
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries())
|
||||
.addAll(CoreModManager.getLoadedCoremods()).build();
|
||||
File[] minecraftSources = modClassLoader.getParentSources();
|
||||
HashSet<String> searchedSources = new HashSet<String>();
|
||||
HashSet<String> searchedSources = new HashSet<>();
|
||||
for (File minecraftSource : minecraftSources) {
|
||||
if (searchedSources.contains(minecraftSource.getAbsolutePath())) continue;
|
||||
searchedSources.add(minecraftSource.getAbsolutePath());
|
||||
@@ -114,21 +111,18 @@ public class ClassDiscoverer {
|
||||
}
|
||||
|
||||
private void readFromZipFile(File file) throws IOException {
|
||||
FileInputStream fileinputstream = new FileInputStream(file);
|
||||
ZipInputStream zipinputstream = new ZipInputStream(fileinputstream);
|
||||
do {
|
||||
ZipEntry zipentry = zipinputstream.getNextEntry();
|
||||
if (zipentry == null) {
|
||||
break;
|
||||
try (ZipFile zipFile = new ZipFile(file)) {
|
||||
Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
|
||||
while (zipEntries.hasMoreElements()) {
|
||||
ZipEntry zipentry = zipEntries.nextElement();
|
||||
String fullname = zipentry.getName().replace('\\', '/');
|
||||
int pos = fullname.lastIndexOf('/');
|
||||
String name = pos == -1 ? fullname : fullname.substring(pos + 1);
|
||||
if (!zipentry.isDirectory() && matcher.matches(name)) {
|
||||
checkAddClass(fullname);
|
||||
}
|
||||
}
|
||||
String fullname = zipentry.getName().replace('\\', '/');
|
||||
int pos = fullname.lastIndexOf('/');
|
||||
String name = pos == -1 ? fullname : fullname.substring(pos + 1);
|
||||
if (!zipentry.isDirectory() && matcher.matches(name)) {
|
||||
checkAddClass(fullname);
|
||||
}
|
||||
} while (true);
|
||||
fileinputstream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void readFromDirectory(File directory, File basedirectory) {
|
||||
|
||||
@@ -5,32 +5,19 @@ import java.lang.reflect.Field;
|
||||
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import cpw.mods.fml.common.asm.transformers.AccessTransformer;
|
||||
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
|
||||
|
||||
// This AccessTransformer will make all minecraft classes public at runtime in MCP just as they are in modloader.
|
||||
// You should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include
|
||||
// access transformers. Such mods are doing the wrong thing and should be fixed.
|
||||
public class CodeChickenAccessTransformer extends AccessTransformer {
|
||||
|
||||
private static boolean makeAllPublic;
|
||||
private static Field f_classNameBiMap;
|
||||
private static final Field f_classNameBiMap;
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
private static Object emptyMap = ImmutableBiMap.of();
|
||||
|
||||
public CodeChickenAccessTransformer() throws IOException {
|
||||
super();
|
||||
loadPublicConfig();
|
||||
}
|
||||
|
||||
private void loadPublicConfig() {
|
||||
if (ObfMapping.obfuscated) return;
|
||||
|
||||
makeAllPublic = CodeChickenCoreModContainer.config.getTag("dev.runtimePublic").setComment(
|
||||
"Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader."
|
||||
+ "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers."
|
||||
+ "\nSuch mods are doing the wrong thing and should be fixed.")
|
||||
.getBooleanValue(false);
|
||||
|
||||
if (!makeAllPublic) return;
|
||||
|
||||
static {
|
||||
try {
|
||||
f_classNameBiMap = FMLDeobfuscatingRemapper.class.getDeclaredField("classNameBiMap");
|
||||
f_classNameBiMap.setAccessible(true);
|
||||
@@ -39,16 +26,18 @@ public class CodeChickenAccessTransformer extends AccessTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
public CodeChickenAccessTransformer() throws IOException {}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||
boolean setPublic = makeAllPublic && name.startsWith("net.minecraft.");
|
||||
boolean setPublic = name.startsWith("net.minecraft.");
|
||||
if (setPublic) setClassMap(name);
|
||||
bytes = super.transform(name, transformedName, bytes);
|
||||
if (setPublic) restoreClassMap();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void restoreClassMap() {
|
||||
private static void restoreClassMap() {
|
||||
try {
|
||||
f_classNameBiMap.set(FMLDeobfuscatingRemapper.INSTANCE, emptyMap);
|
||||
} catch (Exception e) {
|
||||
@@ -56,7 +45,7 @@ public class CodeChickenAccessTransformer extends AccessTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
private void setClassMap(String name) {
|
||||
private static void setClassMap(String name) {
|
||||
try {
|
||||
f_classNameBiMap.set(FMLDeobfuscatingRemapper.INSTANCE, ImmutableBiMap.of(name.replace('.', '/'), ""));
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package codechicken.core.asm;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -13,7 +12,6 @@ import codechicken.core.ClientUtils;
|
||||
import codechicken.core.featurehack.LiquidTextures;
|
||||
import codechicken.core.internal.CCCEventHandler;
|
||||
import codechicken.core.launch.CodeChickenCorePlugin;
|
||||
import codechicken.lib.config.ConfigFile;
|
||||
import cpw.mods.fml.common.DummyModContainer;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.LoadController;
|
||||
@@ -26,14 +24,6 @@ import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
public class CodeChickenCoreModContainer extends DummyModContainer {
|
||||
|
||||
public static ConfigFile config;
|
||||
|
||||
public static void loadConfig() {
|
||||
if (config == null)
|
||||
config = new ConfigFile(new File(CodeChickenCorePlugin.minecraftDir, "config/CodeChickenCore.cfg"))
|
||||
.setComment("CodeChickenCore configuration file.");
|
||||
}
|
||||
|
||||
public CodeChickenCoreModContainer() {
|
||||
super(getModMetadata());
|
||||
}
|
||||
|
||||
@@ -7,35 +7,50 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import codechicken.lib.asm.ASMHelper;
|
||||
import codechicken.lib.asm.ClassHeirachyManager;
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
|
||||
public class DefaultImplementationTransformer implements IClassTransformer {
|
||||
|
||||
private static LaunchClassLoader cl = (LaunchClassLoader) ClassHeirachyManager.class.getClassLoader();
|
||||
private static final HashMap<String, InterfaceImpl> impls = new HashMap<>();
|
||||
|
||||
private static ClassNode getClassNode(String name) {
|
||||
try {
|
||||
return ASMHelper.createClassNode(cl.getClassBytes(name.replace('/', '.')));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
public static void registerDefaultImpl(String iname, String cname) {
|
||||
if (impls.isEmpty()) {
|
||||
String name = DefaultImplementationTransformer.class.getName();
|
||||
FMLRelaunchLog.finer("Registering transformer %s", name);
|
||||
Launch.classLoader.registerTransformer(name);
|
||||
}
|
||||
impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||
if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes;
|
||||
|
||||
ClassNode cnode = ASMHelper.createClassNode(bytes);
|
||||
boolean changed = false;
|
||||
for (String iname : cnode.interfaces) {
|
||||
InterfaceImpl impl = impls.get(iname);
|
||||
if (impl != null) changed |= impl.patch(cnode);
|
||||
}
|
||||
|
||||
return changed ? ASMHelper.createBytes(cnode, 0) : bytes;
|
||||
}
|
||||
|
||||
static class InterfaceImpl {
|
||||
|
||||
public final String iname;
|
||||
public ArrayList<MethodNode> impls = new ArrayList<MethodNode>();
|
||||
public ArrayList<MethodNode> impls = new ArrayList<>();
|
||||
|
||||
public InterfaceImpl(String iname, String cname) {
|
||||
this.iname = iname;
|
||||
HashSet<String> names = new HashSet<String>();
|
||||
HashSet<String> names = new HashSet<>();
|
||||
ClassNode inode = getClassNode(iname);
|
||||
for (MethodNode method : inode.methods) names.add(method.name + method.desc);
|
||||
|
||||
@@ -47,7 +62,7 @@ public class DefaultImplementationTransformer implements IClassTransformer {
|
||||
}
|
||||
|
||||
public boolean patch(ClassNode cnode) {
|
||||
LinkedList<String> names = new LinkedList<String>();
|
||||
LinkedList<String> names = new LinkedList<>();
|
||||
for (MethodNode method : cnode.methods) {
|
||||
ObfMapping m = new ObfMapping(cnode.name, method.name, method.desc).toRuntime();
|
||||
names.add(m.s_name + m.s_desc);
|
||||
@@ -69,25 +84,13 @@ public class DefaultImplementationTransformer implements IClassTransformer {
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
private static HashMap<String, InterfaceImpl> impls = new HashMap<String, InterfaceImpl>();
|
||||
|
||||
public static void registerDefaultImpl(String iname, String cname) {
|
||||
impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||
if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes;
|
||||
|
||||
ClassNode cnode = ASMHelper.createClassNode(bytes);
|
||||
boolean changed = false;
|
||||
for (String iname : cnode.interfaces) {
|
||||
InterfaceImpl impl = impls.get(iname);
|
||||
if (impl != null) changed |= impl.patch(cnode);
|
||||
private static ClassNode getClassNode(String name) {
|
||||
try {
|
||||
return ASMHelper.createClassNode(Launch.classLoader.getClassBytes(name.replace('/', '.')));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return changed ? ASMHelper.createBytes(cnode, 0) : bytes;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package codechicken.core.asm;
|
||||
|
||||
import static codechicken.core.launch.CodeChickenCorePlugin.logger;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -11,7 +9,9 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
@@ -21,14 +21,18 @@ import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import codechicken.core.launch.CodeChickenCorePlugin;
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
|
||||
public class DelegatedTransformer implements IClassTransformer {
|
||||
|
||||
private static ArrayList<IClassTransformer> delegatedTransformers;
|
||||
private static Method m_defineClass;
|
||||
private static Field f_cachedClasses;
|
||||
private static final ArrayList<IClassTransformer> delegatedTransformers;
|
||||
private static final Method m_defineClass;
|
||||
private static final Field f_cachedClasses;
|
||||
private static IClassTransformer[] transformers;
|
||||
|
||||
public DelegatedTransformer() {
|
||||
delegatedTransformers = new ArrayList<IClassTransformer>();
|
||||
static {
|
||||
delegatedTransformers = new ArrayList<>();
|
||||
try {
|
||||
m_defineClass = ClassLoader.class
|
||||
.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
|
||||
@@ -41,14 +45,75 @@ public class DelegatedTransformer implements IClassTransformer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String tname, byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
for (IClassTransformer trans : delegatedTransformers) bytes = trans.transform(name, tname, bytes);
|
||||
return bytes;
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
for (IClassTransformer t : transformers) {
|
||||
basicClass = t.transform(name, transformedName, basicClass);
|
||||
}
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
scanModsForDelegatedTransformers();
|
||||
final int size = delegatedTransformers.size();
|
||||
if (size == 0) {
|
||||
CodeChickenCorePlugin.logger
|
||||
.debug("No delegated transformer found, skipping registration of main DelegatedTransformer.");
|
||||
return;
|
||||
}
|
||||
CodeChickenCorePlugin.logger
|
||||
.debug("Found " + size + " delegated transformers, registering main DelegatedTransformer.");
|
||||
transformers = delegatedTransformers.toArray(new IClassTransformer[0]);
|
||||
String name = DelegatedTransformer.class.getName();
|
||||
FMLRelaunchLog.finer("Registering transformer %s", name);
|
||||
Launch.classLoader.registerTransformer(name);
|
||||
}
|
||||
|
||||
private static void scanModsForDelegatedTransformers() {
|
||||
File modsDir = new File(CodeChickenCorePlugin.minecraftDir, "mods");
|
||||
if (modsDir.exists()) {
|
||||
final File[] files = modsDir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
scanMod(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
File versionModsDir = new File(
|
||||
CodeChickenCorePlugin.minecraftDir,
|
||||
"mods/" + CodeChickenCorePlugin.currentMcVersion);
|
||||
if (versionModsDir.exists()) {
|
||||
final File[] files = versionModsDir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
scanMod(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void scanMod(File file) {
|
||||
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return;
|
||||
|
||||
try {
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
Manifest manifest = jar.getManifest();
|
||||
if (manifest == null) return;
|
||||
Attributes attr = manifest.getMainAttributes();
|
||||
if (attr == null) return;
|
||||
|
||||
String transformer = attr.getValue("CCTransformer");
|
||||
if (transformer != null) {
|
||||
addTransformer(transformer, jar, file);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CodeChickenCorePlugin.logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addTransformer(String transformer, JarFile jar, File jarFile) {
|
||||
logger.debug("Adding CCTransformer: " + transformer);
|
||||
CodeChickenCorePlugin.logger.debug("Adding CCTransformer: " + transformer);
|
||||
try {
|
||||
byte[] bytes;
|
||||
bytes = Launch.classLoader.getClassBytes(transformer);
|
||||
@@ -107,7 +172,7 @@ public class DelegatedTransformer implements IClassTransformer {
|
||||
byte[] depbytes = readFully(jar.getInputStream(entry));
|
||||
defineDependancies(depbytes, jar, jarFile, depStack);
|
||||
|
||||
logger.debug("Defining dependancy: " + dependancy);
|
||||
CodeChickenCorePlugin.logger.debug("Defining dependancy: " + dependancy);
|
||||
|
||||
defineClass(dependancy.replace('/', '.'), depbytes);
|
||||
}
|
||||
@@ -128,7 +193,6 @@ public class DelegatedTransformer implements IClassTransformer {
|
||||
while ((r = stream.read()) != -1) {
|
||||
bos.write(r);
|
||||
}
|
||||
|
||||
return bos.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import codechicken.lib.asm.ASMHelper;
|
||||
import codechicken.lib.asm.ASMInit;
|
||||
import codechicken.lib.asm.CC_ClassWriter;
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import codechicken.obfuscator.IHeirachyEvaluator;
|
||||
@@ -35,15 +34,11 @@ import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator {
|
||||
|
||||
static {
|
||||
ASMInit.init();
|
||||
}
|
||||
|
||||
public static class LoadPlugin implements IFMLLoadingPlugin {
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return new String[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,26 +113,20 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
CodeChickenCoreModContainer.loadConfig();
|
||||
run = new ObfuscationRun(
|
||||
false,
|
||||
ObfMapping.MCPRemapper.getConfFiles(),
|
||||
ObfuscationRun.fillDefaults(new HashMap<String, String>()));
|
||||
run.obf.setHeirachyEvaluator(instance);
|
||||
run.setQuiet().parseMappings();
|
||||
Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";"));
|
||||
|
||||
if (CodeChickenCoreModContainer.config.getTag("dev.deobfuscate")
|
||||
.setComment("set to true to completely deobfuscate mcp names")
|
||||
.getBooleanValue(!ObfMapping.obfuscated)) {
|
||||
run = new ObfuscationRun(
|
||||
false,
|
||||
ObfMapping.MCPRemapper.getConfFiles(),
|
||||
ObfuscationRun.fillDefaults(new HashMap<String, String>()));
|
||||
run.obf.setHeirachyEvaluator(instance);
|
||||
run.setQuiet().parseMappings();
|
||||
Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";"));
|
||||
|
||||
if (ObfMapping.obfuscated) {
|
||||
ObfMapping.loadMCPRemapper();
|
||||
run.setSeargeConstants();
|
||||
getTransformers().add(instance);
|
||||
} else {
|
||||
getTransformers().add(0, instance); // insert transformer as first.
|
||||
}
|
||||
if (ObfMapping.obfuscated) {
|
||||
ObfMapping.loadMCPRemapper();
|
||||
run.setSeargeConstants();
|
||||
getTransformers().add(instance);
|
||||
} else {
|
||||
getTransformers().add(0, instance); // insert transformer as first.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,15 @@ import static codechicken.lib.asm.InsnComparator.findOnce;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import codechicken.core.launch.CodeChickenCorePlugin;
|
||||
import codechicken.lib.asm.ASMBlock;
|
||||
import codechicken.lib.asm.ASMInit;
|
||||
import codechicken.lib.asm.ASMReader;
|
||||
import codechicken.lib.asm.ModularASMTransformer;
|
||||
import codechicken.lib.asm.ModularASMTransformer.MethodReplacer;
|
||||
@@ -20,20 +21,29 @@ import codechicken.lib.asm.ModularASMTransformer.MethodTransformer;
|
||||
import codechicken.lib.asm.ModularASMTransformer.MethodWriter;
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
|
||||
public class TweakTransformer implements IClassTransformer, Opcodes {
|
||||
|
||||
static {
|
||||
ASMInit.init();
|
||||
}
|
||||
|
||||
private static ModularASMTransformer transformer = new ModularASMTransformer();
|
||||
private static Map<String, ASMBlock> blocks = ASMReader.loadResource("/assets/codechickencore/asm/tweaks.asm");
|
||||
private static final ModularASMTransformer transformer = new ModularASMTransformer();
|
||||
private static final Map<String, ASMBlock> blocks = ASMReader
|
||||
.loadResource("/assets/codechickencore/asm/tweaks.asm");
|
||||
public static ConfigTag tweaks;
|
||||
|
||||
public static void load() {
|
||||
CodeChickenCoreModContainer.loadConfig();
|
||||
tweaks = CodeChickenCoreModContainer.config.getTag("tweaks")
|
||||
loadTransformersFromConfig();
|
||||
if (transformer.isEmpty()) {
|
||||
CodeChickenCorePlugin.logger
|
||||
.debug("No tweaks parsed from config, skipping registration of TweakTransformer.");
|
||||
return;
|
||||
}
|
||||
String name = TweakTransformer.class.getName();
|
||||
FMLRelaunchLog.finer("Registering transformer %s", name);
|
||||
Launch.classLoader.registerTransformer(name);
|
||||
}
|
||||
|
||||
private static void loadTransformersFromConfig() {
|
||||
tweaks = CodeChickenCorePlugin.config.getTag("tweaks")
|
||||
.setComment("Various tweaks that can be applied to game mechanics.").useBraces();
|
||||
tweaks.removeTag("persistantLava");
|
||||
|
||||
@@ -103,7 +113,7 @@ public class TweakTransformer implements IClassTransformer, Opcodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String tname, byte[] bytes) {
|
||||
public final byte[] transform(String name, String tname, byte[] bytes) {
|
||||
return transformer.transform(name, bytes);
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,6 @@ import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JOptionPane;
|
||||
@@ -21,48 +18,87 @@ import javax.swing.event.HyperlinkListener;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import codechicken.core.asm.CodeChickenCoreModContainer;
|
||||
import codechicken.core.asm.DelegatedTransformer;
|
||||
import codechicken.core.asm.MCPDeobfuscationTransformer;
|
||||
import codechicken.core.asm.Tags;
|
||||
import codechicken.core.asm.TweakTransformer;
|
||||
import codechicken.lib.config.ConfigFile;
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionParser;
|
||||
import cpw.mods.fml.relauncher.CoreModManager;
|
||||
import cpw.mods.fml.relauncher.FMLInjectionData;
|
||||
import cpw.mods.fml.relauncher.IFMLCallHook;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions;
|
||||
|
||||
@TransformerExclusions(value = { "codechicken.core.asm", "codechicken.obfuscator" })
|
||||
@MCVersion("1.7.10")
|
||||
public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook {
|
||||
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
||||
@IFMLLoadingPlugin.TransformerExclusions({ "codechicken.core.asm", "codechicken.obfuscator", "codechicken.lib.asm",
|
||||
"codechicken.lib.config" })
|
||||
public class CodeChickenCorePlugin implements IFMLLoadingPlugin {
|
||||
|
||||
public static final String mcVersion = "[1.7.10]";
|
||||
|
||||
@Deprecated
|
||||
public static final String version = Tags.VERSION;
|
||||
|
||||
public static ConfigFile config;
|
||||
public static File minecraftDir;
|
||||
public static String currentMcVersion;
|
||||
public static Logger logger = LogManager.getLogger("CodeChickenCore");
|
||||
|
||||
public CodeChickenCorePlugin() {
|
||||
if (minecraftDir != null) return; // get called twice, once for IFMLCallHook
|
||||
|
||||
if (minecraftDir != null) return;
|
||||
minecraftDir = (File) FMLInjectionData.data()[6];
|
||||
currentMcVersion = (String) FMLInjectionData.data()[4];
|
||||
config = new ConfigFile(new File(minecraftDir, "config/CodeChickenCore.cfg"))
|
||||
.setComment("CodeChickenCore configuration file.");
|
||||
if (Boolean.getBoolean("ccc.dev.deobfuscate")) {
|
||||
injectDeobfPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
injectDeobfPlugin();
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
versionCheck(mcVersion, "CodeChickenCore");
|
||||
return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.lib.asm.RedirectorTransformer" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
if (Boolean.getBoolean("ccc.dev.runtimePublic")) {
|
||||
return "codechicken.core.asm.CodeChickenAccessTransformer";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return "codechicken.core.asm.CodeChickenCoreModContainer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
ConfigTag checkRAM = CodeChickenCorePlugin.config.getTag("checks")
|
||||
.setComment("Configuration options for checking various requirements for a modpack.").useBraces();
|
||||
if (checkRAM.getTag("checkRAM")
|
||||
.setComment("If set to true, check RAM available for Minecraft before continuing to load")
|
||||
.getBooleanValue(false)) {
|
||||
systemCheck(checkRAM);
|
||||
}
|
||||
TweakTransformer.load();
|
||||
DelegatedTransformer.load();
|
||||
}
|
||||
|
||||
private void injectDeobfPlugin() {
|
||||
try {
|
||||
Class<?> wrapperClass = Class.forName("cpw.mods.fml.relauncher.CoreModManager$FMLPluginWrapper");
|
||||
Constructor wrapperConstructor = wrapperClass
|
||||
Constructor<?> wrapperConstructor = wrapperClass
|
||||
.getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class);
|
||||
Field f_loadPlugins = CoreModManager.class.getDeclaredField("loadPlugins");
|
||||
wrapperConstructor.setAccessible(true);
|
||||
@@ -76,7 +112,7 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook {
|
||||
0,
|
||||
new String[0]));
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to inject MCPDeobfuscation Transformer", e);
|
||||
logger.error("Failed to inject FMLPluginWrapper for MCPDeobfuscation Transformer", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,74 +222,4 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook {
|
||||
FMLCommonHandler.instance().exitJava(-98, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
versionCheck(mcVersion, "CodeChickenCore");
|
||||
return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.core.asm.TweakTransformer",
|
||||
"codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer",
|
||||
"codechicken.lib.asm.RedirectorTransformer" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return "codechicken.core.asm.CodeChickenAccessTransformer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return "codechicken.core.asm.CodeChickenCoreModContainer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {}
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
CodeChickenCoreModContainer.loadConfig();
|
||||
ConfigTag checkRAM;
|
||||
checkRAM = CodeChickenCoreModContainer.config.getTag("checks")
|
||||
.setComment("Configuration options for checking various requirements for a modpack.").useBraces();
|
||||
if (checkRAM.getTag("checkRAM")
|
||||
.setComment("If set to true, check RAM available for Minecraft before continuing to load")
|
||||
.getBooleanValue(false))
|
||||
systemCheck(checkRAM);
|
||||
TweakTransformer.load();
|
||||
scanCodeChickenMods();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void scanCodeChickenMods() {
|
||||
File modsDir = new File(minecraftDir, "mods");
|
||||
for (File file : modsDir.listFiles()) scanMod(file);
|
||||
File versionModsDir = new File(minecraftDir, "mods/" + currentMcVersion);
|
||||
if (versionModsDir.exists()) for (File file : versionModsDir.listFiles()) scanMod(file);
|
||||
}
|
||||
|
||||
private void scanMod(File file) {
|
||||
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return;
|
||||
|
||||
try {
|
||||
JarFile jar = new JarFile(file);
|
||||
try {
|
||||
Manifest manifest = jar.getManifest();
|
||||
if (manifest == null) return;
|
||||
Attributes attr = manifest.getMainAttributes();
|
||||
if (attr == null) return;
|
||||
|
||||
String transformer = attr.getValue("CCTransformer");
|
||||
if (transformer != null) DelegatedTransformer.addTransformer(transformer, jar, file);
|
||||
} finally {
|
||||
jar.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package codechicken.core.launch;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import cpw.mods.fml.common.versioning.ComparableVersion;
|
||||
import cpw.mods.fml.relauncher.IFMLCallHook;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
|
||||
/**
|
||||
* For autodownloading stuff. This is really unoriginal, mostly ripped off FML, credits to cpw.
|
||||
*/
|
||||
@MCVersion("1.7.10")
|
||||
public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
|
||||
|
||||
public interface IDownloadDisplay {
|
||||
|
||||
void resetProgress(int sizeGuess);
|
||||
|
||||
void setPokeThread(Thread currentThread);
|
||||
|
||||
void updateProgress(int fullLength);
|
||||
|
||||
boolean shouldStopIt();
|
||||
|
||||
void updateProgressString(String string, Object... data);
|
||||
|
||||
Object makeDialog();
|
||||
|
||||
void showErrorDialog(String name, String url);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class Downloader extends JOptionPane implements IDownloadDisplay {
|
||||
|
||||
boolean stopIt;
|
||||
Thread pokeThread;
|
||||
|
||||
private Box makeProgressPanel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JDialog makeDialog() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void requestClose(String message) {}
|
||||
|
||||
@Override
|
||||
public void updateProgressString(String progressUpdate, Object... data) {}
|
||||
|
||||
@Override
|
||||
public void resetProgress(int sizeGuess) {}
|
||||
|
||||
@Override
|
||||
public void updateProgress(int fullLength) {}
|
||||
|
||||
@Override
|
||||
public void setPokeThread(Thread currentThread) {}
|
||||
|
||||
@Override
|
||||
public boolean shouldStopIt() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showErrorDialog(String name, String url) {}
|
||||
}
|
||||
|
||||
public static class DummyDownloader implements IDownloadDisplay {
|
||||
|
||||
@Override
|
||||
public void resetProgress(int sizeGuess) {}
|
||||
|
||||
@Override
|
||||
public void setPokeThread(Thread currentThread) {}
|
||||
|
||||
@Override
|
||||
public void updateProgress(int fullLength) {}
|
||||
|
||||
@Override
|
||||
public boolean shouldStopIt() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProgressString(String string, Object... data) {}
|
||||
|
||||
@Override
|
||||
public Object makeDialog() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showErrorDialog(String name, String url) {}
|
||||
}
|
||||
|
||||
public static class VersionedFile {
|
||||
|
||||
public final Pattern pattern;
|
||||
public final String filename;
|
||||
public final ComparableVersion version;
|
||||
public final String name;
|
||||
|
||||
public VersionedFile(String filename, Pattern pattern) {
|
||||
this.pattern = pattern;
|
||||
this.filename = filename;
|
||||
Matcher m = pattern.matcher(filename);
|
||||
if (m.matches()) {
|
||||
name = m.group(1);
|
||||
version = new ComparableVersion(m.group(2));
|
||||
} else {
|
||||
name = null;
|
||||
version = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches() {
|
||||
return name != null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Dependency {
|
||||
|
||||
public String url;
|
||||
public VersionedFile file;
|
||||
|
||||
public String existing;
|
||||
/**
|
||||
* Flag set to add this dep to the classpath immediately because it is required for a coremod.
|
||||
*/
|
||||
public boolean coreLib;
|
||||
|
||||
public Dependency(String url, VersionedFile file, boolean coreLib) {
|
||||
this.url = url;
|
||||
this.file = file;
|
||||
this.coreLib = coreLib;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DepLoadInst {
|
||||
|
||||
public DepLoadInst() {}
|
||||
|
||||
public void load() {}
|
||||
}
|
||||
|
||||
public static void load() {}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {}
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
load();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -18,10 +18,6 @@ import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
|
||||
*/
|
||||
public class ClassHeirachyManager implements IClassTransformer {
|
||||
|
||||
static {
|
||||
ASMInit.init();
|
||||
}
|
||||
|
||||
public static class SuperCache {
|
||||
|
||||
String superclass;
|
||||
|
||||
@@ -275,17 +275,22 @@ public class ModularASMTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<String, ClassNodeTransformerList> transformers = new HashMap<String, ClassNodeTransformerList>();
|
||||
public HashMap<String, ClassNodeTransformerList> transformers = new HashMap<>();
|
||||
|
||||
public void add(ClassNodeTransformer t) {
|
||||
ClassNodeTransformerList list = transformers.get(t.className());
|
||||
if (list == null) transformers.put(t.className(), list = new ClassNodeTransformerList());
|
||||
if (list == null) {
|
||||
transformers.put(t.className(), list = new ClassNodeTransformerList());
|
||||
}
|
||||
list.add(t);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return transformers.isEmpty();
|
||||
}
|
||||
|
||||
public byte[] transform(String name, byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
|
||||
ClassNodeTransformerList list = transformers.get(name);
|
||||
return list == null ? bytes : list.transform(bytes);
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
@@ -58,7 +59,12 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
"hasBrightness",
|
||||
"brightness",
|
||||
"side",
|
||||
"lc"
|
||||
"lc",
|
||||
"normalAttrib",
|
||||
"colourAttrib",
|
||||
"lightCoordAttrib",
|
||||
"sideAttrib",
|
||||
"lightingAttrib"
|
||||
|
||||
);
|
||||
Collections.addAll(redirectedSimpleMethods, "reset", "pullLightmap", "pushLightmap", "setDynamic", "draw");
|
||||
@@ -90,61 +96,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() == Opcodes.INVOKESTATIC && node instanceof MethodInsnNode mNode) {
|
||||
if (redirectedMethods.contains(mNode.name) && mNode.owner.equals(RenderStateClass)) {
|
||||
mNode.name = mNode.name + "Static";
|
||||
} 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 (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);
|
||||
}
|
||||
} else if (node instanceof MethodInsnNode mNode) {
|
||||
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() == 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;
|
||||
}
|
||||
@@ -153,13 +161,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) {}
|
||||
@@ -168,40 +172,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() {
|
||||
|
||||
@@ -64,15 +64,15 @@ public class Canvas9Seg {
|
||||
|
||||
public void draw(CCRenderState state, int x, int y, int w, int h) {
|
||||
CCRenderState.changeTexture(tex);
|
||||
state.reset();
|
||||
state.startDrawing();
|
||||
state.resetInstance();
|
||||
state.startDrawingInstance();
|
||||
|
||||
int[] sw = new int[] { x, x + seg_w[0], x + w - seg_w[2], x + w };
|
||||
int[] sh = new int[] { y, y + seg_h[0], y + h - seg_h[2], y + h };
|
||||
|
||||
for (int seg = 0; seg < 9; seg++) drawSeg(sw, sh, seg);
|
||||
|
||||
state.draw();
|
||||
state.drawInstance();
|
||||
}
|
||||
|
||||
public void draw(int x, int y, int w, int h) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -128,8 +128,8 @@ public class LightMatrix implements CCRenderState.IVertexOperation {
|
||||
float[] a = ao(lc.side);
|
||||
float f = (a[0] * lc.fa + a[1] * lc.fb + a[2] * lc.fc + a[3] * lc.fd);
|
||||
int[] b = brightness(lc.side);
|
||||
state.setColour(ColourRGBA.multiplyC(state.colour, f));
|
||||
state.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF);
|
||||
state.setColourInstance(ColourRGBA.multiplyC(state.colour, f));
|
||||
state.setBrightnessInstance((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -81,14 +81,14 @@ public class LightModel implements CCRenderState.IVertexOperation {
|
||||
public boolean load(CCRenderState state) {
|
||||
if (!state.computeLighting) return false;
|
||||
|
||||
state.pipeline.addDependency(CCRenderState.normalAttrib);
|
||||
state.pipeline.addDependency(CCRenderState.colourAttrib);
|
||||
state.pipeline.addDependency(CCRenderState.normalAttrib());
|
||||
state.pipeline.addDependency(CCRenderState.colourAttrib());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
state.setColour(apply(state.colour, state.normal));
|
||||
state.setColourInstance(apply(state.colour, state.normal));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,14 +40,14 @@ public class PlanarLightMatrix extends PlanarLightModel {
|
||||
|
||||
@Override
|
||||
public boolean load(CCRenderState state) {
|
||||
state.pipeline.addDependency(CCRenderState.sideAttrib);
|
||||
state.pipeline.addDependency(CCRenderState.sideAttrib());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
super.operate(state);
|
||||
state.setBrightness(brightness(state.side));
|
||||
state.setBrightnessInstance(brightness(state.side));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,14 +20,14 @@ public class PlanarLightModel implements CCRenderState.IVertexOperation {
|
||||
public boolean load(CCRenderState state) {
|
||||
if (!state.computeLighting) return false;
|
||||
|
||||
state.pipeline.addDependency(CCRenderState.sideAttrib);
|
||||
state.pipeline.addDependency(CCRenderState.colourAttrib);
|
||||
state.pipeline.addDependency(CCRenderState.sideAttrib());
|
||||
state.pipeline.addDependency(CCRenderState.colourAttrib());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
state.setColour(ColourRGBA.multiply(state.colour, colours[state.side]));
|
||||
state.setColourInstance(ColourRGBA.multiply(state.colour, colours[state.side]));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,13 +40,13 @@ public class SimpleBrightnessModel implements CCRenderState.IVertexOperation {
|
||||
|
||||
@Override
|
||||
public boolean load(CCRenderState state) {
|
||||
state.pipeline.addDependency(CCRenderState.sideAttrib);
|
||||
state.pipeline.addDependency(CCRenderState.sideAttrib());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
state.setBrightness(sample(state.side));
|
||||
state.setBrightnessInstance(sample(state.side));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -351,9 +351,9 @@ public final class PacketCustom implements MCDataInput, MCDataOutput {
|
||||
|
||||
public PacketCustom writeItemStack(ItemStack stack, boolean large) {
|
||||
if (stack == null) {
|
||||
writeInt(-1);
|
||||
writeShort(-1);
|
||||
} else {
|
||||
writeInt(Item.getIdFromItem(stack.getItem()));
|
||||
writeShort(Item.getIdFromItem(stack.getItem()));
|
||||
if (large) writeInt(stack.stackSize);
|
||||
else writeByte(stack.stackSize);
|
||||
writeShort(stack.getItemDamage());
|
||||
@@ -448,7 +448,7 @@ public final class PacketCustom implements MCDataInput, MCDataOutput {
|
||||
|
||||
public ItemStack readItemStack(boolean large) {
|
||||
ItemStack item = null;
|
||||
int itemID = readInt();
|
||||
short itemID = readShort();
|
||||
|
||||
if (itemID >= 0) {
|
||||
int stackSize = large ? readInt() : readByte();
|
||||
|
||||
@@ -20,12 +20,12 @@ public class BlockRenderer {
|
||||
|
||||
@Override
|
||||
public <T> T getAttributes(CCRenderState.VertexAttribute<T> attr) {
|
||||
return attr == CCRenderState.lightCoordAttrib && lcComputed ? (T) lightCoords : null;
|
||||
return attr == CCRenderState.lightCoordAttrib() && lcComputed ? (T) lightCoords : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAttribute(CCRenderState.VertexAttribute<?> attr) {
|
||||
return attr == CCRenderState.sideAttrib || attr == CCRenderState.lightCoordAttrib && lcComputed;
|
||||
return attr == CCRenderState.sideAttrib() || attr == CCRenderState.lightCoordAttrib() && lcComputed;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -136,12 +136,12 @@ public class BlockRenderer {
|
||||
|
||||
@Override
|
||||
public <T> T getAttributes(VertexAttribute<T> attr) {
|
||||
return attr == CCRenderState.lightCoordAttrib ? (T) lightCoords : null;
|
||||
return attr == CCRenderState.lightCoordAttrib() ? (T) lightCoords : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAttribute(VertexAttribute<?> attr) {
|
||||
return attr == CCRenderState.sideAttrib || attr == CCRenderState.lightCoordAttrib;
|
||||
return attr == CCRenderState.sideAttrib() || attr == CCRenderState.lightCoordAttrib();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,7 +154,7 @@ public class BlockRenderer {
|
||||
|
||||
// public static void renderFullBlock(int sideMask) {
|
||||
public static void renderFullBlock(CCRenderState state, int sideMask) {
|
||||
state.setModel(fullBlock);
|
||||
state.setModelInstance(fullBlock);
|
||||
renderFaces(state, sideMask);
|
||||
}
|
||||
|
||||
@@ -164,15 +164,15 @@ public class BlockRenderer {
|
||||
|
||||
/**
|
||||
* Renders faces of a block-like model based on a sideMask. Eg for side 2, verts 8-11 will be rendered
|
||||
*
|
||||
*
|
||||
* @param sideMask A mask of faces not to render
|
||||
*/
|
||||
// public static void renderFaces(int sideMask) {
|
||||
public static void renderFaces(CCRenderState state, int sideMask) {
|
||||
if (sideMask == 0x3F) return;
|
||||
for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) {
|
||||
state.setVertexRange(s * 4, (s + 1) * 4);
|
||||
state.render();
|
||||
state.setVertexRangeInstance(s * 4, (s + 1) * 4);
|
||||
state.renderInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,17 +184,17 @@ public class BlockRenderer {
|
||||
|
||||
/**
|
||||
* Renders faces of a cuboid with texture coordinates mapped to match a standard minecraft block
|
||||
*
|
||||
*
|
||||
* @param bounds The bounding cuboid to render
|
||||
* @param sideMask A mask of faces not to render
|
||||
*/
|
||||
public static void renderCuboid(CCRenderState state, Cuboid6 bounds, int sideMask) {
|
||||
if (sideMask == 0x3F) return;
|
||||
|
||||
state.setModel(face);
|
||||
state.setModelInstance(face);
|
||||
for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) {
|
||||
face.loadCuboidFace(bounds, s);
|
||||
state.render();
|
||||
state.renderInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
}
|
||||
|
||||
public Vector3[] normals() {
|
||||
return getAttributes(CCRenderState.normalAttrib);
|
||||
return getAttributes(CCRenderState.normalAttrib());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,7 +102,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Each pixel corresponds to one unit of position when generating the model
|
||||
*
|
||||
*
|
||||
* @param i Vertex index to start generating at
|
||||
* @param x1 The minX bound of the box
|
||||
* @param y1 The minY bound of the box
|
||||
@@ -195,7 +195,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Generates a box, uv mapped to be the same as a minecraft block with the same bounds
|
||||
*
|
||||
*
|
||||
* @param i The vertex index to start generating at
|
||||
* @param bounds The bounds of the block, 0 to 1
|
||||
* @return The generated model. When rendering an icon will need to be supplied for the UV transformation.
|
||||
@@ -222,7 +222,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Generates a box, uv mapped to be the same as a minecraft block with the same bounds
|
||||
*
|
||||
*
|
||||
* @param i The vertex index to start generating at
|
||||
* @param x1 minX
|
||||
* @param y1 minY
|
||||
@@ -311,7 +311,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Computes the normals of all faces in the model. Uses the cross product of the vectors along 2 sides of the face
|
||||
*
|
||||
*
|
||||
* @param start The first vertex to generate normals for
|
||||
* @param length The number of vertices to generate normals for. Note this must be a multiple of 3 for triangles or
|
||||
* 4 for quads
|
||||
@@ -321,7 +321,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
if (length % vp != 0 || start % vp != 0)
|
||||
throw new IllegalArgumentException("Cannot generate normals across polygons");
|
||||
|
||||
Vector3[] normals = getOrAllocate(CCRenderState.normalAttrib);
|
||||
Vector3[] normals = getOrAllocate(CCRenderState.normalAttrib());
|
||||
for (int k = 0; k < length; k += vp) {
|
||||
int i = k + start;
|
||||
Vector3 diff1 = verts[i + 1].vec.copy().subtract(verts[i].vec);
|
||||
@@ -336,14 +336,14 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
/**
|
||||
* Computes lighting using the normals add a light model If the model is rotated, the lighting will no longer be
|
||||
* valid
|
||||
*
|
||||
*
|
||||
* @return The model
|
||||
*/
|
||||
public CCModel computeLighting(LightModel light) {
|
||||
Vector3[] normals = normals();
|
||||
int[] colours = getAttributes(CCRenderState.lightingAttrib);
|
||||
int[] colours = getAttributes(CCRenderState.lightingAttrib());
|
||||
if (colours == null) {
|
||||
colours = getOrAllocate(CCRenderState.lightingAttrib);
|
||||
colours = getOrAllocate(CCRenderState.lightingAttrib());
|
||||
Arrays.fill(colours, -1);
|
||||
}
|
||||
for (int k = 0; k < verts.length; k++) colours[k] = light.apply(colours[k], normals[k]);
|
||||
@@ -351,18 +351,18 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
}
|
||||
|
||||
public CCModel setColour(int c) {
|
||||
int[] colours = getOrAllocate(CCRenderState.colourAttrib);
|
||||
int[] colours = getOrAllocate(CCRenderState.colourAttrib());
|
||||
Arrays.fill(colours, c);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the minecraft lighting coordinates for use with a LightMatrix
|
||||
*
|
||||
*
|
||||
* @return The model
|
||||
*/
|
||||
public CCModel computeLightCoords() {
|
||||
LC[] lcs = getOrAllocate(CCRenderState.lightCoordAttrib);
|
||||
LC[] lcs = getOrAllocate(CCRenderState.lightCoordAttrib());
|
||||
Vector3[] normals = normals();
|
||||
for (int i = 0; i < verts.length; i++) lcs[i] = new LC().compute(verts[i].vec, normals[i]);
|
||||
return this;
|
||||
@@ -370,7 +370,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Averages all normals at the same position to produce a smooth lighting effect.
|
||||
*
|
||||
*
|
||||
* @return The model
|
||||
*/
|
||||
public CCModel smoothNormals() {
|
||||
@@ -461,14 +461,14 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Renders vertices start through start+length-1 of the model
|
||||
*
|
||||
*
|
||||
* @param start The first vertex index to render
|
||||
* @param end The vertex index to render until
|
||||
* @param ops Operations to apply
|
||||
*/
|
||||
public void render(CCRenderState state, int start, int end, CCRenderState.IVertexOperation... ops) {
|
||||
state.setPipeline(this, start, end, ops);
|
||||
state.render();
|
||||
state.setPipelineInstance(this, start, end, ops);
|
||||
state.renderInstance();
|
||||
}
|
||||
|
||||
public void render(int start, int end, CCRenderState.IVertexOperation... ops) {
|
||||
@@ -520,7 +520,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Parses vertices, texture coords, normals and polygons from a WaveFront Obj file
|
||||
*
|
||||
*
|
||||
* @param input An input stream to a obj file
|
||||
* @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS)
|
||||
* @param coordSystem The cooridnate system transformation to apply
|
||||
@@ -624,7 +624,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Parses vertices, texture coords, normals and polygons from a WaveFront Obj file
|
||||
*
|
||||
*
|
||||
* @param res The resource for the obj file
|
||||
* @return A map of group names to models
|
||||
*/
|
||||
@@ -634,7 +634,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Parses vertices, texture coords, normals and polygons from a WaveFront Obj file
|
||||
*
|
||||
*
|
||||
* @param res The resource for the obj file
|
||||
* @param coordSystem The cooridnate system transformation to apply
|
||||
* @return A map of group names to models
|
||||
@@ -652,7 +652,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Parses vertices, texture coords, normals and polygons from a WaveFront Obj file
|
||||
*
|
||||
*
|
||||
* @param res The resource for the obj file
|
||||
* @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS)
|
||||
* @param coordSystem The cooridnate system transformation to apply
|
||||
@@ -678,7 +678,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
boolean hasNormals = polys.get(0)[2] > 0;
|
||||
CCModel model = CCModel.newModel(vertexMode, polys.size());
|
||||
if (hasNormals) model.getOrAllocate(CCRenderState.normalAttrib);
|
||||
if (hasNormals) model.getOrAllocate(CCRenderState.normalAttrib());
|
||||
|
||||
for (int i = 0; i < polys.size(); i++) {
|
||||
int[] ai = polys.get(i);
|
||||
@@ -807,7 +807,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Generate models rotated to the other 5 sides of the block
|
||||
*
|
||||
*
|
||||
* @param models An array of 6 models
|
||||
* @param side The side of this model
|
||||
* @param point The rotation point
|
||||
@@ -822,7 +822,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Generate models rotated to the other 3 horizontal of the block
|
||||
*
|
||||
*
|
||||
* @param models An array of 4 models
|
||||
* @param side The side of this model
|
||||
* @param point The rotation point
|
||||
@@ -841,7 +841,7 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
|
||||
|
||||
/**
|
||||
* Generates copies of faces with clockwise vertices
|
||||
*
|
||||
*
|
||||
* @return The model
|
||||
*/
|
||||
public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int destpos, int length) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class CCRenderPipeline {
|
||||
|
||||
public void render() {
|
||||
rebuild();
|
||||
renderState.render();
|
||||
renderState.renderInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ public class CCRenderState {
|
||||
/**
|
||||
* Management class for a vertex attrute such as colour, normal etc This class should handle the loading of the
|
||||
* attrute from an array provided by IVertexSource.getAttributes or the computation of this attrute from others
|
||||
*
|
||||
*
|
||||
* @param <T> The array type for this attrute eg. int[], Vector3[]
|
||||
*/
|
||||
public abstract static class VertexAttribute<T> implements IVertexOperation {
|
||||
@@ -146,7 +146,7 @@ public class CCRenderState {
|
||||
|
||||
/**
|
||||
* Gets an array of vertex attrutes
|
||||
*
|
||||
*
|
||||
* @param attr The vertex attrute to get
|
||||
* @param <T> The attrute array type
|
||||
* @return An array, or null if not computed
|
||||
@@ -169,7 +169,27 @@ public class CCRenderState {
|
||||
}
|
||||
}
|
||||
|
||||
public static VertexAttribute<Vector3[]> normalAttrib = new VertexAttribute<>() {
|
||||
public static VertexAttribute<Vector3[]> normalAttrib() {
|
||||
return instances.get().normalAttrib;
|
||||
}
|
||||
|
||||
public static VertexAttribute<int[]> colourAttrib() {
|
||||
return instances.get().colourAttrib;
|
||||
}
|
||||
|
||||
public static VertexAttribute<LC[]> lightCoordAttrib() {
|
||||
return instances.get().lightCoordAttrib;
|
||||
}
|
||||
|
||||
public static VertexAttribute<int[]> sideAttrib() {
|
||||
return instances.get().sideAttrib;
|
||||
}
|
||||
|
||||
public static VertexAttribute<int[]> lightingAttrib() {
|
||||
return instances.get().lightingAttrib;
|
||||
}
|
||||
|
||||
public VertexAttribute<Vector3[]> normalAttrib = new VertexAttribute<>() {
|
||||
|
||||
private Vector3[] normalRef;
|
||||
|
||||
@@ -193,11 +213,11 @@ public class CCRenderState {
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
if (normalRef != null) state.setNormal(normalRef[state.vertexIndex]);
|
||||
else state.setNormal(Rotation.axes[state.side]);
|
||||
if (normalRef != null) state.setNormalInstance(normalRef[state.vertexIndex]);
|
||||
else state.setNormalInstance(Rotation.axes[state.side]);
|
||||
}
|
||||
};
|
||||
public static VertexAttribute<int[]> colourAttrib = new VertexAttribute<>() {
|
||||
public VertexAttribute<int[]> colourAttrib = new VertexAttribute<>() {
|
||||
|
||||
private int[] colourRef;
|
||||
|
||||
@@ -214,11 +234,12 @@ public class CCRenderState {
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
if (colourRef != null) state.setColour(ColourRGBA.multiply(state.baseColour, colourRef[state.vertexIndex]));
|
||||
else state.setColour(state.baseColour);
|
||||
if (colourRef != null)
|
||||
state.setColourInstance(ColourRGBA.multiply(state.baseColour, colourRef[state.vertexIndex]));
|
||||
else state.setColourInstance(state.baseColour);
|
||||
}
|
||||
};
|
||||
public static VertexAttribute<int[]> lightingAttrib = new VertexAttribute<>() {
|
||||
public VertexAttribute<int[]> lightingAttrib = new VertexAttribute<>() {
|
||||
|
||||
private int[] colourRef;
|
||||
|
||||
@@ -241,10 +262,10 @@ public class CCRenderState {
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
state.setColour(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex]));
|
||||
state.setColourInstance(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex]));
|
||||
}
|
||||
};
|
||||
public static VertexAttribute<int[]> sideAttrib = new VertexAttribute<>() {
|
||||
public VertexAttribute<int[]> sideAttrib = new VertexAttribute<>() {
|
||||
|
||||
private int[] sideRef;
|
||||
|
||||
@@ -271,7 +292,7 @@ public class CCRenderState {
|
||||
/**
|
||||
* Uses the position of the lightmatrix to compute LC if not provided
|
||||
*/
|
||||
public static VertexAttribute<LC[]> lightCoordAttrib = new VertexAttribute<>() {
|
||||
public VertexAttribute<LC[]> lightCoordAttrib = new VertexAttribute<>() {
|
||||
|
||||
private LC[] lcRef;
|
||||
private final Vector3 vec = new Vector3(); // for computation
|
||||
@@ -326,11 +347,15 @@ public class CCRenderState {
|
||||
public boolean hasBrightness;
|
||||
public int brightness;
|
||||
|
||||
// attrute storage
|
||||
// attribute storage
|
||||
public int side;
|
||||
public LC lc = new LC();
|
||||
|
||||
public void reset() {
|
||||
public static void reset() {
|
||||
instance().resetInstance();
|
||||
}
|
||||
|
||||
public void resetInstance() {
|
||||
model = null;
|
||||
pipeline.reset();
|
||||
useNormals = hasNormal = hasBrightness = hasColour = false;
|
||||
@@ -338,27 +363,27 @@ public class CCRenderState {
|
||||
baseColour = alphaOverride = -1;
|
||||
}
|
||||
|
||||
public void setPipeline(IVertexOperation... ops) {
|
||||
public void setPipelineInstance(IVertexOperation... ops) {
|
||||
pipeline.setPipeline(ops);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setPipelineStatic(IVertexOperation... ops) {
|
||||
instance().setPipeline(ops);
|
||||
public static void setPipeline(IVertexOperation... ops) {
|
||||
instance().setPipelineInstance(ops);
|
||||
}
|
||||
|
||||
public void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) {
|
||||
public void setPipelineInstance(IVertexSource model, int start, int end, IVertexOperation... ops) {
|
||||
pipeline.reset();
|
||||
setModel(model, start, end);
|
||||
setModelInstance(model, start, end);
|
||||
pipeline.setPipeline(ops);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setPipelineStatic(IVertexSource model, int start, int end, IVertexOperation... ops) {
|
||||
instance().setPipeline(model, start, end, ops);
|
||||
public static void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) {
|
||||
instance().setPipelineInstance(model, start, end, ops);
|
||||
}
|
||||
|
||||
public void bindModel(IVertexSource model) {
|
||||
public void bindModelInstance(IVertexSource model) {
|
||||
if (this.model != model) {
|
||||
this.model = model;
|
||||
pipeline.rebuild();
|
||||
@@ -366,74 +391,74 @@ public class CCRenderState {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void bindModelStatic(IVertexSource model) {
|
||||
instance().bindModel(model);
|
||||
public static void bindModel(IVertexSource model) {
|
||||
instance().bindModelInstance(model);
|
||||
}
|
||||
|
||||
public void setModel(IVertexSource source) {
|
||||
setModel(source, 0, source.getVertices().length);
|
||||
public void setModelInstance(IVertexSource source) {
|
||||
setModelInstance(source, 0, source.getVertices().length);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setModelStatic(IVertexSource source) {
|
||||
instance().setModel(source);
|
||||
public static void setModel(IVertexSource source) {
|
||||
instance().setModelInstance(source);
|
||||
}
|
||||
|
||||
public void setModel(IVertexSource source, int start, int end) {
|
||||
bindModel(source);
|
||||
setVertexRange(start, end);
|
||||
public void setModelInstance(IVertexSource source, int start, int end) {
|
||||
bindModelInstance(source);
|
||||
setVertexRangeInstance(start, end);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setModelStatic(IVertexSource source, int start, int end) {
|
||||
instance().setModel(source, start, end);
|
||||
public static void setModel(IVertexSource source, int start, int end) {
|
||||
instance().setModelInstance(source, start, end);
|
||||
}
|
||||
|
||||
public void setVertexRange(int start, int end) {
|
||||
public void setVertexRangeInstance(int start, int end) {
|
||||
firstVertexIndex = start;
|
||||
lastVertexIndex = end;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setVertexRangeStatic(int start, int end) {
|
||||
instance().setVertexRange(start, end);
|
||||
public static void setVertexRange(int start, int end) {
|
||||
instance().setVertexRangeInstance(start, end);
|
||||
}
|
||||
|
||||
public void render(IVertexOperation... ops) {
|
||||
setPipeline(ops);
|
||||
render();
|
||||
public void renderInstance(IVertexOperation... ops) {
|
||||
setPipelineInstance(ops);
|
||||
renderInstance();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void renderStatic(IVertexOperation... ops) {
|
||||
instance().render(ops);
|
||||
public static void render(IVertexOperation... ops) {
|
||||
instance().renderInstance(ops);
|
||||
}
|
||||
|
||||
public void render() {
|
||||
public void renderInstance() {
|
||||
Vertex5[] verts = model.getVertices();
|
||||
for (vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) {
|
||||
model.prepareVertex(this);
|
||||
vert.set(verts[vertexIndex]);
|
||||
runPipeline();
|
||||
writeVert();
|
||||
runPipelineInstance();
|
||||
writeVertInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void renderStatic() {
|
||||
instance().render();
|
||||
public static void render() {
|
||||
instance().renderInstance();
|
||||
}
|
||||
|
||||
public void runPipeline() {
|
||||
public void runPipelineInstance() {
|
||||
pipeline.operate();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void runPipelineStatic() {
|
||||
instance().runPipeline();
|
||||
public static void runPipeline() {
|
||||
instance().runPipelineInstance();
|
||||
}
|
||||
|
||||
public void writeVert() {
|
||||
public void writeVertInstance() {
|
||||
if (hasNormal) Tessellator.instance.setNormal((float) normal.x, (float) normal.y, (float) normal.z);
|
||||
if (hasColour) Tessellator.instance.setColorRGBA(
|
||||
colour >>> 24,
|
||||
@@ -445,71 +470,83 @@ public class CCRenderState {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void writeVertStatic() {
|
||||
instance().writeVert();
|
||||
public static void writeVert() {
|
||||
instance().writeVertInstance();
|
||||
}
|
||||
|
||||
public void setNormal(double x, double y, double z) {
|
||||
public void setNormalInstance(double x, double y, double z) {
|
||||
hasNormal = true;
|
||||
normal.set(x, y, z);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setNormalStatic(double x, double y, double z) {
|
||||
instance().setNormal(x, y, z);
|
||||
public static void setNormal(double x, double y, double z) {
|
||||
instance().setNormalInstance(x, y, z);
|
||||
}
|
||||
|
||||
public void setNormal(Vector3 n) {
|
||||
public void setNormalInstance(Vector3 n) {
|
||||
hasNormal = true;
|
||||
normal.set(n);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setNormalStatic(Vector3 n) {
|
||||
instance().setNormal(n);
|
||||
public static void setNormal(Vector3 n) {
|
||||
instance().setNormalInstance(n);
|
||||
}
|
||||
|
||||
public void setColour(int c) {
|
||||
public void setColourInstance(int c) {
|
||||
hasColour = true;
|
||||
colour = c;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setColourStatic(int c) {
|
||||
instance().setColour(c);
|
||||
public static void setColour(int c) {
|
||||
instance().setColourInstance(c);
|
||||
}
|
||||
|
||||
public void setBrightness(int b) {
|
||||
public void setBrightnessInstance(int b) {
|
||||
hasBrightness = true;
|
||||
brightness = b;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setBrightnessStatic(int b) {
|
||||
instance().setBrightness(b);
|
||||
public static void setBrightness(int b) {
|
||||
instance().setBrightnessInstance(b);
|
||||
}
|
||||
|
||||
public void setBrightness(IBlockAccess world, int x, int y, int z) {
|
||||
setBrightness(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z));
|
||||
public void setBrightnessInstance(IBlockAccess world, int x, int y, int z) {
|
||||
setBrightnessInstance(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setBrightnessStatic(IBlockAccess world, int x, int y, int z) {
|
||||
instance().setBrightness(world, x, y, z);
|
||||
public static void setBrightness(IBlockAccess world, int x, int y, int z) {
|
||||
instance().setBrightnessInstance(world, x, y, z);
|
||||
}
|
||||
|
||||
public void pullLightmap() {
|
||||
setBrightness((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX);
|
||||
public static void pullLightmap() {
|
||||
instance().pullLightmapInstance();
|
||||
}
|
||||
|
||||
public void pushLightmap() {
|
||||
public void pullLightmapInstance() {
|
||||
setBrightnessInstance((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX);
|
||||
}
|
||||
|
||||
public static void pushLightmap() {
|
||||
instance().pushLightmapInstance();
|
||||
}
|
||||
|
||||
public void pushLightmapInstance() {
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness & 0xFFFF, brightness >>> 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compact helper for setting dynamic rendering context. Uses normals and doesn't compute lighting
|
||||
*/
|
||||
public void setDynamic() {
|
||||
public static void setDynamic() {
|
||||
instance().setDynamicInstance();
|
||||
}
|
||||
|
||||
public void setDynamicInstance() {
|
||||
useNormals = true;
|
||||
computeLighting = false;
|
||||
}
|
||||
@@ -522,16 +559,16 @@ public class CCRenderState {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
|
||||
}
|
||||
|
||||
public void startDrawing() {
|
||||
startDrawing(7);
|
||||
public void startDrawingInstance() {
|
||||
startDrawingInstance(7);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void startDrawingStatic() {
|
||||
instance().startDrawing();
|
||||
public static void startDrawing() {
|
||||
instance().startDrawingInstance();
|
||||
}
|
||||
|
||||
public void startDrawing(int mode) {
|
||||
public void startDrawingInstance(int mode) {
|
||||
Tessellator.instance.startDrawing(mode);
|
||||
if (hasColour) Tessellator.instance.setColorRGBA(
|
||||
colour >>> 24,
|
||||
@@ -542,11 +579,15 @@ public class CCRenderState {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void startDrawingStatic(int mode) {
|
||||
instance().startDrawing(mode);
|
||||
public static void startDrawing(int mode) {
|
||||
instance().startDrawingInstance(mode);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
public static void draw() {
|
||||
Tessellator.instance.draw();
|
||||
}
|
||||
|
||||
public void drawInstance() {
|
||||
Tessellator.instance.draw();
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class ColourMultiplier implements CCRenderState.IVertexOperation {
|
||||
@Override
|
||||
public boolean load(CCRenderState state) {
|
||||
if (colour == -1) {
|
||||
state.setColour(-1);
|
||||
state.setColourInstance(-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ColourMultiplier implements CCRenderState.IVertexOperation {
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
state.setColour(ColourRGBA.multiply(state.colour, colour));
|
||||
state.setColourInstance(ColourRGBA.multiply(state.colour, colour));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -259,7 +301,7 @@ public class RenderUtils {
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Fluid fluid = stack.getFluid();
|
||||
state.setColour(fluid.getColor(stack) << 8 | alpha);
|
||||
state.setColourInstance(fluid.getColor(stack) << 8 | alpha);
|
||||
TextureUtils.bindAtlas(fluid.getSpriteNumber());
|
||||
return TextureUtils.safeIcon(fluid.getIcon(stack));
|
||||
}
|
||||
@@ -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.startDrawing();
|
||||
renderFluidCuboid(state, bound, tex, res);
|
||||
state.draw();
|
||||
state.startDrawingInstance();
|
||||
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.startDrawing();
|
||||
renderFluidQuad(
|
||||
new Vector3(rect.x, rect.y + rect.h, 0),
|
||||
new Vector3(rect.w, 0, 0),
|
||||
new Vector3(0, -rect.h, 0),
|
||||
tex,
|
||||
res);
|
||||
state.draw();
|
||||
state.startDrawingInstance();
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -14,14 +14,14 @@ public abstract class Transformation extends ITransformation<Vector3, Transforma
|
||||
|
||||
/**
|
||||
* Applies this transformation to a normal (doesn't translate)
|
||||
*
|
||||
*
|
||||
* @param normal The normal to transform
|
||||
*/
|
||||
public abstract void applyN(Vector3 normal);
|
||||
|
||||
/**
|
||||
* Applies this transformation to a matrix as a multiplication on the right hand side.
|
||||
*
|
||||
*
|
||||
* @param mat The matrix to combine this transformation with
|
||||
*/
|
||||
public abstract void apply(Matrix4 mat);
|
||||
@@ -39,14 +39,14 @@ public abstract class Transformation extends ITransformation<Vector3, Transforma
|
||||
|
||||
@Override
|
||||
public boolean load(CCRenderState state) {
|
||||
state.pipeline.addRequirement(CCRenderState.normalAttrib.operationID());
|
||||
state.pipeline.addRequirement(CCRenderState.normalAttrib().operationID());
|
||||
return !isRedundant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(CCRenderState state) {
|
||||
apply(state.vert.vec);
|
||||
if (CCRenderState.normalAttrib.active) applyN(state.normal);
|
||||
if (CCRenderState.normalAttrib().active) applyN(state.normal);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -79,17 +79,25 @@ public class WorldExtensionManager {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onChunkWatch(Watch event) {
|
||||
Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos);
|
||||
for (WorldExtension extension : worldMap.get(event.player.worldObj))
|
||||
extension.watchChunk(chunk, event.player);
|
||||
WorldExtension[] extensions = worldMap.get(event.player.worldObj);
|
||||
|
||||
if (extensions != null) {
|
||||
Chunk chunk = event.player.worldObj
|
||||
.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos);
|
||||
for (WorldExtension extension : extensions) extension.watchChunk(chunk, event.player);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void onChunkUnWatch(UnWatch event) {
|
||||
Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos);
|
||||
for (WorldExtension extension : worldMap.get(event.player.worldObj))
|
||||
extension.unwatchChunk(chunk, event.player);
|
||||
WorldExtension[] extensions = worldMap.get(event.player.worldObj);
|
||||
|
||||
if (extensions != null) {
|
||||
Chunk chunk = event.player.worldObj
|
||||
.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos);
|
||||
for (WorldExtension extension : extensions) extension.unwatchChunk(chunk, event.player);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -110,7 +118,7 @@ public class WorldExtensionManager {
|
||||
}
|
||||
|
||||
private static boolean initialised;
|
||||
private static ArrayList<WorldExtensionInstantiator> extensionIntialisers = new ArrayList<WorldExtensionInstantiator>();
|
||||
private static ArrayList<WorldExtensionInstantiator> extensionIntialisers = new ArrayList<>();
|
||||
|
||||
public static void registerWorldExtension(WorldExtensionInstantiator init) {
|
||||
if (!initialised) init();
|
||||
@@ -125,7 +133,7 @@ public class WorldExtensionManager {
|
||||
FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler());
|
||||
}
|
||||
|
||||
private static HashMap<World, WorldExtension[]> worldMap = new HashMap<World, WorldExtension[]>();
|
||||
private static HashMap<World, WorldExtension[]> worldMap = new HashMap<>();
|
||||
|
||||
private static void onWorldLoad(World world) {
|
||||
WorldExtension[] extensions = new WorldExtension[extensionIntialisers.size()];
|
||||
|
||||
@@ -4,13 +4,15 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.commons.RemappingClassAdapter;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
@@ -181,7 +183,40 @@ public class ObfuscationRun implements ILogStreams {
|
||||
|
||||
public void remap(ClassNode cnode, ClassVisitor cv) {
|
||||
cstMappper.transform(cnode);
|
||||
cnode.accept(new RemappingClassAdapter(cv, obfMapper));
|
||||
cnode.accept(newRemapper(cv, obfMapper));
|
||||
}
|
||||
|
||||
private static ClassVisitor newRemapper(ClassVisitor visitor, Remapper remapper) {
|
||||
try {
|
||||
return theConstructor.newInstance(visitor, remapper);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Constructor<? extends ClassVisitor> theConstructor;
|
||||
|
||||
static {
|
||||
Class<? extends ClassVisitor> remapperClass;
|
||||
try {
|
||||
// noinspection unchecked
|
||||
remapperClass = (Class<? extends ClassVisitor>) Class.forName("org.objectweb.asm.commons.ClassRemapper");
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
// noinspection unchecked
|
||||
remapperClass = (Class<? extends ClassVisitor>) Class
|
||||
.forName("org.objectweb.asm.commons.RemappingClassAdapter");
|
||||
} catch (ClassNotFoundException ex) {
|
||||
RuntimeException err = new RuntimeException(ex);
|
||||
err.addSuppressed(e);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
try {
|
||||
theConstructor = remapperClass.getConstructor(ClassVisitor.class, Remapper.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getParents(ClassNode cnode) {
|
||||
|
||||
Reference in new issue
Block a user