diff --git a/codechicken/lib/asm/ASMHelper.java b/codechicken/lib/asm/ASMHelper.java index 63dd0ed..d8f4e73 100644 --- a/codechicken/lib/asm/ASMHelper.java +++ b/codechicken/lib/asm/ASMHelper.java @@ -23,45 +23,42 @@ import com.google.common.collect.Multimap; import codechicken.lib.asm.InstructionComparator.InsnListSection; public class ASMHelper -{ +{ public static class CodeBlock { public Label start = new Label(); public Label end = new Label(); } - + public static class ForBlock extends CodeBlock { public Label cmp = new Label(); public Label inc = new Label(); public Label body = new Label(); } - + public static abstract class MethodAltercator { public final ObfMapping method; - - public MethodAltercator(ObfMapping method) - { - this.method = method; + + public MethodAltercator(ObfMapping method) { + this.method = method.toClassloading(); } - + public abstract void alter(MethodNode mv); } - + public static abstract class MethodWriter { public final int access; public final ObfMapping method; public final String[] exceptions; - public MethodWriter(int access, ObfMapping method) - { + public MethodWriter(int access, ObfMapping method) { this(access, method, null); } - - public MethodWriter(int access, ObfMapping method, String[] exceptions) - { + + public MethodWriter(int access, ObfMapping method, String[] exceptions) { this.access = access; this.method = method; this.exceptions = exceptions; @@ -69,69 +66,60 @@ public class ASMHelper public abstract void write(MethodNode mv); } - + public static class MethodInjector { public final ObfMapping method; public final InsnList needle; public final InsnList injection; public final boolean before; - - public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) - { + + public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) { this.method = method; this.needle = needle; this.injection = injection; this.before = before; } } - - public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) - { - for(MethodNode mnode : cnode.methods) - if(methodmap.matches(mnode)) + + public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) { + for (MethodNode mnode : cnode.methods) + if (methodmap.matches(mnode)) return mnode; return null; } - public static FieldNode findField(ObfMapping fieldmap, ClassNode cnode) - { - for(FieldNode fnode : cnode.fields) - if(fieldmap.matches(fnode)) + public static FieldNode findField(ObfMapping fieldmap, ClassNode cnode) { + for (FieldNode fnode : cnode.fields) + if (fieldmap.matches(fnode)) return fnode; return null; } - public static ClassNode createClassNode(byte[] bytes) - { + public static ClassNode createClassNode(byte[] bytes) { return createClassNode(bytes, 0); } - - public static ClassNode createClassNode(byte[] bytes, int flags) - { + + public static ClassNode createClassNode(byte[] bytes, int flags) { ClassNode cnode = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(cnode, flags); return cnode; } - public static byte[] createBytes(ClassNode cnode, int flags) - { + public static byte[] createBytes(ClassNode cnode, int flags) { ClassWriter cw = new CC_ClassWriter(flags); cnode.accept(cw); return cw.toByteArray(); } - - public static byte[] writeMethods(String name, byte[] bytes, Multimap writers) - { - if(writers.containsKey(name)) - { + + public static byte[] writeMethods(String name, byte[] bytes, Multimap writers) { + if (writers.containsKey(name)) { ClassNode cnode = createClassNode(bytes); - - for(MethodWriter mw : writers.get(name)) - { + + for (MethodWriter mw : writers.get(name)) { MethodNode mv = findMethod(mw.method, cnode); - if(mv == null) + if (mv == null) mv = (MethodNode) cnode.visitMethod(mw.access, mw.method.s_name, mw.method.s_desc, null, mw.exceptions); mv.access = mw.access; @@ -143,41 +131,33 @@ public class ASMHelper } return bytes; } - - public static byte[] injectMethods(String name, byte[] bytes, Multimap injectors) - { - if(injectors.containsKey(name)) - { + + public static byte[] injectMethods(String name, byte[] bytes, Multimap injectors) { + if (injectors.containsKey(name)) { ClassNode cnode = createClassNode(bytes); - - for(MethodInjector injector : injectors.get(name)) - { + + for (MethodInjector injector : injectors.get(name)) { MethodNode method = findMethod(injector.method, cnode); - if(method == null) - throw new RuntimeException("Method not found: "+injector.method); + if (method == null) + throw new RuntimeException("Method not found: " + injector.method); System.out.println("Injecting into " + injector.method + "\n" + printInsnList(injector.injection)); - + List callNodes; - if(injector.before) + if (injector.before) callNodes = InstructionComparator.insnListFindStart(method.instructions, injector.needle); else callNodes = InstructionComparator.insnListFindEnd(method.instructions, injector.needle); - - if(callNodes.size() == 0) - { - throw new RuntimeException("Needle not found in Haystack: " + injector.method+"\n" + printInsnList(injector.needle)); + + if (callNodes.size() == 0) { + throw new RuntimeException("Needle not found in Haystack: " + injector.method + "\n" + printInsnList(injector.needle)); } - - for(AbstractInsnNode node : callNodes) - { - if(injector.before) - { - System.out.println("Injected before: "+printInsn(node)); + + for (AbstractInsnNode node : callNodes) { + if (injector.before) { + System.out.println("Injected before: " + printInsn(node)); method.instructions.insertBefore(node, cloneInsnList(injector.injection)); - } - else - { - System.out.println("Injected after: "+printInsn(node)); + } else { + System.out.println("Injected after: " + printInsn(node)); method.instructions.insert(node, cloneInsnList(injector.injection)); } } @@ -187,144 +167,126 @@ public class ASMHelper } return bytes; } - - public static String printInsnList(InsnList list) - { - InsnListPrinter p = new InsnListPrinter(); + + public static String printInsnList(InsnList list) { + InsnListPrinter p = new InsnListPrinter(); p.visitInsnList(list); return p.textString(); } - - public static String printInsn(AbstractInsnNode insn) - { + + public static String printInsn(AbstractInsnNode insn) { InsnListPrinter p = new InsnListPrinter(); p.visitInsn(insn); return p.textString(); } - - public static Map cloneLabels(InsnList insns) - { + + public static Map cloneLabels(InsnList insns) { HashMap labelMap = new HashMap(); - for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) - if(insn.getType() == 8) + for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) + if (insn.getType() == 8) labelMap.put((LabelNode) insn, new LabelNode()); return labelMap; } - - public static InsnList cloneInsnList(InsnList insns) - { + + public static InsnList cloneInsnList(InsnList insns) { return cloneInsnList(cloneLabels(insns), insns); } - - public static InsnList cloneInsnList(Map labelMap, InsnList insns) - { + + public static InsnList cloneInsnList(Map labelMap, InsnList insns) { InsnList clone = new InsnList(); - for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) + for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) clone.add(insn.clone(labelMap)); - + return clone; } - - public static List cloneTryCatchBlocks(Map labelMap, List tcblocks) - { + + public static List cloneTryCatchBlocks(Map labelMap, List tcblocks) { ArrayList clone = new ArrayList(); - for(TryCatchBlockNode node : tcblocks) + for (TryCatchBlockNode node : tcblocks) clone.add(new TryCatchBlockNode( - labelMap.get(node.start), - labelMap.get(node.end), - labelMap.get(node.handler), + labelMap.get(node.start), + labelMap.get(node.end), + labelMap.get(node.handler), node.type)); - + return clone; } - - public static List cloneLocals(Map labelMap, List locals) - { + + public static List cloneLocals(Map labelMap, List locals) { ArrayList clone = new ArrayList(); - for(LocalVariableNode node : locals) + for (LocalVariableNode node : locals) clone.add(new LocalVariableNode( - node.name, node.desc, node.signature, - labelMap.get(node.start), - labelMap.get(node.end), + node.name, node.desc, node.signature, + labelMap.get(node.start), + labelMap.get(node.end), node.index)); - + return clone; } - - public static void copy(MethodNode src, MethodNode dst) - { + + public static void copy(MethodNode src, MethodNode dst) { Map labelMap = cloneLabels(src.instructions); dst.instructions = cloneInsnList(labelMap, src.instructions); dst.tryCatchBlocks = cloneTryCatchBlocks(labelMap, src.tryCatchBlocks); - if(src.localVariables != null) + if (src.localVariables != null) dst.localVariables = cloneLocals(labelMap, src.localVariables); dst.visibleAnnotations = src.visibleAnnotations; dst.invisibleAnnotations = src.invisibleAnnotations; dst.visitMaxs(src.maxStack, src.maxLocals); } - public static byte[] alterMethods(String name, byte[] bytes, HashMultimap altercators) - { - if(altercators.containsKey(name)) - { + public static byte[] alterMethods(String name, byte[] bytes, HashMultimap altercators) { + if (altercators.containsKey(name)) { ClassNode cnode = createClassNode(bytes); - - for(MethodAltercator injector : altercators.get(name)) - { + + for (MethodAltercator injector : altercators.get(name)) { MethodNode method = findMethod(injector.method, cnode); - if(method == null) - throw new RuntimeException("Method not found: "+injector.method); - + if (method == null) + throw new RuntimeException("Method not found: " + injector.method); + injector.alter(method); } - + bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); } return bytes; } - - public static String printInsnList(InsnListSection subsection) - { - InsnListPrinter p = new InsnListPrinter(); + + public static String printInsnList(InsnListSection subsection) { + InsnListPrinter p = new InsnListPrinter(); p.visitInsnList(subsection); return p.textString(); } - public static int getLocal(List list, String name) - { + public static int getLocal(List list, String name) { int found = -1; - for(LocalVariableNode node : list) - { - if(node.name.equals(name)) - { - if(found >= 0) - throw new RuntimeException("Duplicate local variable: "+name+" not coded to handle this scenario."); - + for (LocalVariableNode node : list) { + if (node.name.equals(name)) { + if (found >= 0) + throw new RuntimeException("Duplicate local variable: " + name + " not coded to handle this scenario."); + found = node.index; } } return found; } - public static void replaceMethodCode(MethodNode original, MethodNode replacement) - { + public static void replaceMethodCode(MethodNode original, MethodNode replacement) { original.instructions.clear(); - if(original.localVariables != null) + if (original.localVariables != null) original.localVariables.clear(); - if(original.tryCatchBlocks != null) + if (original.tryCatchBlocks != null) original.tryCatchBlocks.clear(); replacement.accept(original); } - public static void removeBlock(InsnList insns, InsnListSection block) - { + public static void removeBlock(InsnList insns, InsnListSection block) { AbstractInsnNode insn = block.first; - while(true) - { + while (true) { AbstractInsnNode next = insn.getNext(); insns.remove(insn); - if(insn == block.last) + if (insn == block.last) break; insn = next; } diff --git a/codechicken/lib/asm/ASMReader.java b/codechicken/lib/asm/ASMReader.java index e43de99..fd15f1e 100644 --- a/codechicken/lib/asm/ASMReader.java +++ b/codechicken/lib/asm/ASMReader.java @@ -301,14 +301,14 @@ public class ASMReader insn = new VarInsnNode(opcode, Integer.parseInt(split[1])); break; case TYPE_INSN: - insn = new ObfMapping(split[1]).toInsn(opcode); + insn = new ObfMapping(split[1]).toClassloading().toInsn(opcode); break; case FIELD_INSN: case METHOD_INSN: StringBuilder sb = new StringBuilder(); for(int i = 1; i < split.length; i++) sb.append(split[i]); - insn = ObfMapping.fromDesc(sb.toString()).toInsn(opcode); + insn = ObfMapping.fromDesc(sb.toString()).toClassloading().toInsn(opcode); break; case INVOKE_DYNAMIC_INSN: throw new Exception("Found INVOKEDYNAMIC while reading"); diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java index 846e8cf..0aabd5a 100644 --- a/codechicken/lib/asm/ObfMapping.java +++ b/codechicken/lib/asm/ObfMapping.java @@ -1,8 +1,12 @@ package codechicken.lib.asm; import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; -import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraft.launchwrapper.Launch; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.Remapper; @@ -19,219 +23,235 @@ import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; public class ObfMapping { - /** - * CCC will deal with this. - */ - public static Remapper runtimeMapper = FMLDeobfuscatingRemapper.INSTANCE; - public static Remapper mcpMapper = null; - - public static final boolean obfuscated; - - static + public static class ObfRemapper extends Remapper { - boolean obf = true; - try - { - obf = ((LaunchClassLoader)ObfMapping.class.getClassLoader()).getClassBytes("net.minecraft.world.World") == null; + private HashMap fields = new HashMap(); + private HashMap funcs = new HashMap(); + + public ObfRemapper() { + try { + Field rawFieldMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawFieldMaps"); + Field rawMethodMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawMethodMaps"); + rawFieldMapsField.setAccessible(true); + rawMethodMapsField.setAccessible(true); + Map> rawFieldMaps = (Map>) rawFieldMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); + Map> rawMethodMaps = (Map>) rawMethodMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); + + if(rawFieldMaps == null) + throw new IllegalStateException("codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage"); + + for(Map map : rawFieldMaps.values()) + for(Entry entry : map.entrySet()) + if(entry.getValue().startsWith("field")) + fields.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf(':'))); + for(Map map : rawMethodMaps.values()) + for(Entry entry : map.entrySet()) + if(entry.getValue().startsWith("func")) + funcs.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf('('))); + + } catch (Exception e) { + throw new RuntimeException(e); + } } - catch(IOException iox) {} + + @Override + public String mapMethodName(String owner, String name, String desc) { + String s = funcs.get(name); + return s == null ? name : s; + } + + @Override + public String mapFieldName(String owner, String name, String desc) { + String s = fields.get(name); + return s == null ? name : s; + } + + @Override + public String map(String typeName) { + return FMLDeobfuscatingRemapper.INSTANCE.unmap(typeName); + } + } + + public static ObfRemapper obfMapper = new ObfRemapper(); + public static Remapper mcpMapper = null; + + public static final boolean obfuscated; + + static { + boolean obf = true; + try { + obf = Launch.classLoader.getClassBytes("net.minecraft.world.World") == null; + } catch (IOException ignored) {} obfuscated = obf; } - + public String s_owner; public String s_name; public String s_desc; - - public boolean runtime; - - public ObfMapping(String owner) - { + + public ObfMapping(String owner) { this(owner, "", ""); } - - public ObfMapping(String owner, String name, String desc) - { + + public ObfMapping(String owner, String name, String desc) { this.s_owner = owner; this.s_name = name; this.s_desc = desc; - if(s_owner.contains(".")) + if (s_owner.contains(".")) throw new IllegalArgumentException(s_owner); - - if(mcpMapper != null) - map(mcpMapper); } - - public ObfMapping(ObfMapping descmap, String subclass) - { + + public ObfMapping(ObfMapping descmap, String subclass) { this(subclass, descmap.s_name, descmap.s_desc); } - public static ObfMapping fromDesc(String s) - { + public static ObfMapping fromDesc(String s) { int lastDot = s.lastIndexOf('.'); - if(lastDot < 0) + if (lastDot < 0) return new ObfMapping(s, "", ""); int sep = s.indexOf('(');//methods int sep_end = sep; - if(sep < 0) { + if (sep < 0) { sep = s.indexOf(' ');//some stuffs - sep_end = sep+1; + sep_end = sep + 1; } - if(sep < 0) { + if (sep < 0) { sep = s.indexOf(':');//fields - sep_end = sep+1; + sep_end = sep + 1; } - if(sep < 0) + if (sep < 0) return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1), ""); - return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot+1, sep), s.substring(sep_end)); + return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1, sep), s.substring(sep_end)); } - - public ObfMapping subclass(String subclass) - { + + public ObfMapping subclass(String subclass) { return new ObfMapping(this, subclass); } - public boolean matches(MethodNode node) - { + public boolean matches(MethodNode node) { return s_name.equals(node.name) && s_desc.equals(node.desc); } - - public boolean matches(MethodInsnNode node) - { + + public boolean matches(MethodInsnNode node) { return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc); } - public AbstractInsnNode toInsn(int opcode) - { - if(isClass()) + public AbstractInsnNode toInsn(int opcode) { + if (isClass()) return new TypeInsnNode(opcode, s_owner); - else if(isMethod()) + else if (isMethod()) return new MethodInsnNode(opcode, s_owner, s_name, s_desc); else return new FieldInsnNode(opcode, s_owner, s_name, s_desc); } - - public void visitTypeInsn(MethodVisitor mv, int opcode) - { + + public void visitTypeInsn(MethodVisitor mv, int opcode) { mv.visitTypeInsn(opcode, s_owner); } - - public void visitMethodInsn(MethodVisitor mv, int opcode) - { + + public void visitMethodInsn(MethodVisitor mv, int opcode) { mv.visitMethodInsn(opcode, s_owner, s_name, s_desc); } - public void visitFieldInsn(MethodVisitor mv, int opcode) - { + public void visitFieldInsn(MethodVisitor mv, int opcode) { mv.visitFieldInsn(opcode, s_owner, s_name, s_desc); } - public boolean isClass(String name) - { + public boolean isClass(String name) { return name.replace('.', '/').equals(s_owner); } - public boolean matches(String name, String desc) - { + public boolean matches(String name, String desc) { return s_name.equals(name) && s_desc.equals(desc); } - public boolean matches(FieldNode node) - { + public boolean matches(FieldNode node) { return s_name.equals(node.name) && s_desc.equals(node.desc); } - - public boolean matches(FieldInsnNode node) - { + + public boolean matches(FieldInsnNode node) { return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc); } - public String javaClass() - { + public String javaClass() { return s_owner.replace('/', '.'); } - + @Override - public boolean equals(Object obj) - { - if(!(obj instanceof ObfMapping)) + public boolean equals(Object obj) { + if (!(obj instanceof ObfMapping)) return false; - - ObfMapping desc = (ObfMapping)obj; + + ObfMapping desc = (ObfMapping) obj; return s_owner.equals(desc.s_owner) && s_name.equals(desc.s_name) && s_desc.equals(desc.s_desc); } - + @Override - public int hashCode() - { + public int hashCode() { return Objects.hashCode(s_desc, s_name, s_owner); } - + @Override - public String toString() - { - if(s_name.length() == 0) - return "["+s_owner+"]"; - if(s_desc.length() == 0) - return "["+s_owner+"."+s_name+"]"; - return "["+(isMethod() ? methodDesc() : fieldDesc())+"]"; + public String toString() { + if (s_name.length() == 0) + return "[" + s_owner + "]"; + if (s_desc.length() == 0) + return "[" + s_owner + "." + s_name + "]"; + return "[" + (isMethod() ? methodDesc() : fieldDesc()) + "]"; } - public String methodDesc() - { - return s_owner+"."+s_name+s_desc; + public String methodDesc() { + return s_owner + "." + s_name + s_desc; } - public String fieldDesc() - { - return s_owner+"."+s_name+":"+s_desc; + public String fieldDesc() { + return s_owner + "." + s_name + ":" + s_desc; } - - public boolean isClass() - { + + public boolean isClass() { return s_name.length() == 0; } - - public boolean isMethod() - { + + public boolean isMethod() { return s_desc.contains("("); } - - public boolean isField() - { + + public boolean isField() { return !isClass() && !isMethod(); } - - public ObfMapping map(Remapper mapper) - { - if(isMethod()) + + public ObfMapping map(Remapper mapper) { + if(mapper == null) + return this; + + if (isMethod()) s_name = mapper.mapMethodName(s_owner, s_name, s_desc); - else if(isField()) + else if (isField()) s_name = mapper.mapFieldName(s_owner, s_name, s_desc); - + s_owner = mapper.mapType(s_owner); - - if(isMethod()) + + if (isMethod()) s_desc = mapper.mapMethodDesc(s_desc); - else if(s_desc.length() > 0) + else if (s_desc.length() > 0) s_desc = mapper.mapDesc(s_desc); - + return this; } - - public ObfMapping toRuntime() - { - if(!runtime) - map(runtimeMapper); - - runtime = true; + + public ObfMapping toRuntime() { + map(mcpMapper); return this; } - - public ObfMapping copy() - { + + public ObfMapping toClassloading() { + map(obfuscated ? obfMapper : mcpMapper); + return this; + } + + public ObfMapping copy() { return new ObfMapping(s_owner, s_name, s_desc); } } diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java index 41cf7a3..3fa78c2 100644 --- a/codechicken/lib/colour/Colour.java +++ b/codechicken/lib/colour/Colour.java @@ -1,5 +1,6 @@ package codechicken.lib.colour; +import codechicken.lib.util.Copyable; import org.lwjgl.opengl.GL11; import codechicken.lib.math.MathHelper; @@ -7,7 +8,7 @@ import codechicken.lib.math.MathHelper; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public abstract class Colour +public abstract class Colour implements Copyable { public byte r; public byte g; diff --git a/codechicken/lib/colour/ColourRGBA.java b/codechicken/lib/colour/ColourRGBA.java index 54baf91..61d4a29 100644 --- a/codechicken/lib/colour/ColourRGBA.java +++ b/codechicken/lib/colour/ColourRGBA.java @@ -1,40 +1,49 @@ package codechicken.lib.colour; -public class ColourRGBA extends Colour -{ - public ColourRGBA(int colour) - { +public class ColourRGBA extends Colour { + public ColourRGBA(int colour) { super((colour >> 24) & 0xFF, (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF); } - public ColourRGBA(double r, double g, double b, double a) - { + public ColourRGBA(double r, double g, double b, double a) { super((int) (255 * r), (int) (255 * g), (int) (255 * b), (int) (255 * a)); } - public ColourRGBA(int r, int g, int b, int a) - { + public ColourRGBA(int r, int g, int b, int a) { super(r, g, b, a); } - public ColourRGBA(ColourRGBA colour) - { + public ColourRGBA(ColourRGBA colour) { super(colour); } - public int pack() - { + public int pack() { return pack(this); } @Override - public Colour copy() - { + public Colour copy() { return new ColourRGBA(this); } - public static int pack(Colour colour) - { - return (colour.r&0xFF) << 24 | (colour.g&0xFF) << 16 | (colour.b&0xFF) << 8 | (colour.a&0xFF); + public static int pack(Colour colour) { + return (colour.r & 0xFF) << 24 | (colour.g & 0xFF) << 16 | (colour.b & 0xFF) << 8 | (colour.a & 0xFF); + } + + public static int multiply(int c1, int c2) { + if(c1 == -1) return c2; + if(c2 == -1) return c1; + int r = (((c1 >>> 24) * (c2 >>> 24)) & 0xFF00) << 16; + int g = (((c1 >> 16 & 0xFF) * (c2 >> 16 & 0xFF)) & 0xFF00) << 8; + int b = ((c1 >> 8 & 0xFF) * (c2 >> 8 & 0xFF)) & 0xFF00; + int a = ((c1 & 0xFF) * (c2 & 0xFF)) >> 8; + return r|g|b|a; + } + + public static int multiplyC(int c, float f) { + int r = (int) ((c >>> 24) * f); + int g = (int) ((c >> 16 & 0xFF) * f); + int b = (int) ((c >> 8 & 0xFF) * f); + return r<<24 | g<<16 | b<<8 | c&0xFF; } } diff --git a/codechicken/lib/config/ConfigFile.java b/codechicken/lib/config/ConfigFile.java index 6b84756..3e6e5e1 100644 --- a/codechicken/lib/config/ConfigFile.java +++ b/codechicken/lib/config/ConfigFile.java @@ -8,146 +8,118 @@ import java.io.IOException; import java.io.PrintWriter; public class ConfigFile extends ConfigTagParent -{ - public ConfigFile(File file) - { - if(!file.exists()) - { - try - { +{ + public ConfigFile(File file) { + try { + if(!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + if (!file.exists()) file.createNewFile(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + } catch (IOException e) { + throw new RuntimeException(e); } this.file = file; newlinemode = 2; loadConfig(); } - - private void loadConfig() - { + + private void loadConfig() { loading = true; BufferedReader reader; - try - { + try { reader = new BufferedReader(new FileReader(file)); - - while(true) - { + + while (true) { reader.mark(2000); String line = reader.readLine(); - if(line != null && line.startsWith("#")) - { - if(comment == null || comment.equals("")) + if (line != null && line.startsWith("#")) { + if (comment == null || comment.equals("")) comment = line.substring(1); else - comment = comment+"\n"+line.substring(1); - } - else - { + comment = comment + "\n" + line.substring(1); + } else { reader.reset(); break; } } loadChildren(reader); reader.close(); - - } - catch(IOException e) - { + + } catch (IOException e) { throw new RuntimeException(e); } - + loading = false; } - + @Override - public ConfigFile setComment(String header) - { + public ConfigFile setComment(String header) { super.setComment(header); return this; } - + @Override - public ConfigFile setSortMode(int mode) - { + public ConfigFile setSortMode(int mode) { super.setSortMode(mode); return this; } - + @Override - public String getNameQualifier() - { + public String getNameQualifier() { return ""; } - - public static String readLine(BufferedReader reader) throws IOException - { + + public static String readLine(BufferedReader reader) throws IOException { String line = reader.readLine(); - if(line != null) + if (line != null) return line.replace("\t", ""); return line; } - - public static String formatLine(String line) - { + + public static String formatLine(String line) { line = line.replace("\t", ""); - if(line.startsWith("#")) - { + if (line.startsWith("#")) { return line; - } - else if(line.contains("=")) - { - line = line.substring(0, line.indexOf("=")).replace(" ", "")+line.substring(line.indexOf("=")); + } else if (line.contains("=")) { + line = line.substring(0, line.indexOf("=")).replace(" ", "") + line.substring(line.indexOf("=")); return line; - } - else - { + } else { line = line.replace(" ", ""); return line; } } - - public static void writeLine(PrintWriter writer, String line, int tabs) - { - for(int i = 0; i < tabs; i++) + + public static void writeLine(PrintWriter writer, String line, int tabs) { + for (int i = 0; i < tabs; i++) writer.print('\t'); - + writer.println(line); } - - public void saveConfig() - { - if(loading) + + public void saveConfig() { + if (loading) return; - + PrintWriter writer; - try - { + try { writer = new PrintWriter(file); - } - catch(FileNotFoundException e) - { + } catch (FileNotFoundException e) { throw new RuntimeException(e); } - + writeComment(writer, 0); ConfigFile.writeLine(writer, "", 0); saveTagTree(writer, 0, ""); writer.flush(); writer.close(); } - - public boolean isLoading() - { + + public boolean isLoading() { return loading; } - + public File file; private boolean loading; - + public static final byte[] lineend = new byte[]{0xD, 0xA}; } diff --git a/codechicken/lib/data/MCDataInput.java b/codechicken/lib/data/MCDataInput.java index d1169bd..fda1d45 100644 --- a/codechicken/lib/data/MCDataInput.java +++ b/codechicken/lib/data/MCDataInput.java @@ -12,11 +12,13 @@ public interface MCDataInput public short readShort(); public int readUShort(); public byte readByte(); - public int readUByte(); + public short readUByte(); public double readDouble(); public float readFloat(); public boolean readBoolean(); public char readChar(); + public int readVarShort(); + public int readVarInt(); public byte[] readByteArray(int length); public String readString(); public BlockCoord readCoord(); diff --git a/codechicken/lib/data/MCDataOutput.java b/codechicken/lib/data/MCDataOutput.java index 40d694e..fbe6710 100644 --- a/codechicken/lib/data/MCDataOutput.java +++ b/codechicken/lib/data/MCDataOutput.java @@ -15,6 +15,8 @@ public interface MCDataOutput public MCDataOutput writeFloat(float f); public MCDataOutput writeBoolean(boolean b); public MCDataOutput writeChar(char c); + public MCDataOutput writeVarInt(int i); + public MCDataOutput writeVarShort(int s); public MCDataOutput writeByteArray(byte[] array); public MCDataOutput writeString(String s); public MCDataOutput writeCoord(int x, int y, int z); diff --git a/codechicken/lib/data/MCOutputStreamWrapper.java b/codechicken/lib/data/MCOutputStreamWrapper.java index 71e5163..f8d94c5 100644 --- a/codechicken/lib/data/MCOutputStreamWrapper.java +++ b/codechicken/lib/data/MCOutputStreamWrapper.java @@ -3,6 +3,7 @@ package codechicken.lib.data; import java.io.DataOutputStream; import java.io.IOException; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; @@ -122,7 +123,31 @@ public class MCOutputStreamWrapper implements MCDataOutput } return this; } - + + @Override + public MCDataOutput writeVarInt(int i) { + while ((i & 0x80) != 0) + { + writeByte(i & 0x7F | 0x80); + i >>>= 7; + } + + writeByte(i); + return this; + } + + @Override + public MCDataOutput writeVarShort(int s) { + int low = s & 0x7FFF; + int high = (s & 0x7F8000) >> 15; + if (high != 0) + low |= 0x8000; + writeShort(low); + if (high != 0) + writeByte(high); + return this; + } + public MCOutputStreamWrapper writeByteArray(byte[] barray) { try @@ -174,16 +199,12 @@ public class MCOutputStreamWrapper implements MCDataOutput return this; } - public MCOutputStreamWrapper writeItemStack(ItemStack stack, boolean large) - { - if (stack == null) - { + public MCOutputStreamWrapper writeItemStack(ItemStack stack, boolean large) { + if (stack == null) { writeShort(-1); - } - else - { - writeShort(stack.itemID); - if(large) + } else { + writeShort(Item.getIdFromItem(stack.getItem())); + if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); diff --git a/codechicken/lib/data/NBTDataWrapper.java b/codechicken/lib/data/NBTDataWrapper.java deleted file mode 100644 index 19cf013..0000000 --- a/codechicken/lib/data/NBTDataWrapper.java +++ /dev/null @@ -1,246 +0,0 @@ -package codechicken.lib.data; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagByte; -import net.minecraft.nbt.NBTTagByteArray; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagDouble; -import net.minecraft.nbt.NBTTagFloat; -import net.minecraft.nbt.NBTTagInt; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagLong; -import net.minecraft.nbt.NBTTagShort; -import net.minecraft.nbt.NBTTagString; -import net.minecraftforge.fluids.FluidStack; -import codechicken.lib.vec.BlockCoord; - -public class NBTDataWrapper implements MCDataInput, MCDataOutput -{ - private NBTTagList readList; - private int readTag = 0; - private NBTTagList writeList; - - public NBTDataWrapper(NBTTagList input) - { - readList = input; - } - - public NBTDataWrapper() - { - writeList = new NBTTagList(); - } - - public NBTTagList toTag() - { - return writeList; - } - - @Override - public NBTDataWrapper writeLong(long l) - { - writeList.appendTag(new NBTTagLong(null, l)); - return this; - } - - @Override - public NBTDataWrapper writeInt(int i) - { - writeList.appendTag(new NBTTagInt(null, i)); - return this; - } - - @Override - public NBTDataWrapper writeShort(int s) - { - writeList.appendTag(new NBTTagShort(null, (short) s)); - return this; - } - - @Override - public NBTDataWrapper writeByte(int b) - { - writeList.appendTag(new NBTTagByte(null, (byte) b)); - return this; - } - - @Override - public NBTDataWrapper writeDouble(double d) - { - writeList.appendTag(new NBTTagDouble(null, d)); - return this; - } - - @Override - public NBTDataWrapper writeFloat(float f) - { - writeList.appendTag(new NBTTagFloat(null, f)); - return this; - } - - @Override - public NBTDataWrapper writeBoolean(boolean b) - { - writeList.appendTag(new NBTTagByte(null, (byte) (b ? 1 : 0))); - return this; - } - - @Override - public NBTDataWrapper writeChar(char c) - { - writeList.appendTag(new NBTTagShort(null, (short)c)); - return this; - } - - @Override - public NBTDataWrapper writeByteArray(byte[] array) - { - writeList.appendTag(new NBTTagByteArray(null, array)); - return this; - } - - @Override - public NBTDataWrapper writeString(String s) - { - writeList.appendTag(new NBTTagString(null, s)); - return this; - } - - @Override - public NBTDataWrapper writeCoord(int x, int y, int z) - { - writeInt(x); - writeInt(y); - writeInt(z); - return this; - } - - @Override - public NBTDataWrapper writeCoord(BlockCoord coord) - { - writeCoord(coord.x, coord.y, coord.z); - return this; - } - - @Override - public NBTDataWrapper writeNBTTagCompound(NBTTagCompound tag) - { - writeList.appendTag(tag); - return this; - } - - @Override - public NBTDataWrapper writeItemStack(ItemStack stack) - { - writeList.appendTag(stack.writeToNBT(new NBTTagCompound())); - return this; - } - - @Override - public NBTDataWrapper writeFluidStack(FluidStack liquid) - { - writeList.appendTag(liquid.writeToNBT(new NBTTagCompound())); - return this; - } - - @Override - public long readLong() - { - return ((NBTTagLong)readTag()).data; - } - - @Override - public int readInt() - { - return ((NBTTagInt)readTag()).data; - } - - @Override - public short readShort() - { - return ((NBTTagShort)readTag()).data; - } - - @Override - public int readUShort() - { - return ((NBTTagShort)readTag()).data & 0xFFFF; - } - - @Override - public byte readByte() - { - return ((NBTTagByte)readTag()).data; - } - - @Override - public int readUByte() - { - return ((NBTTagByte)readTag()).data & 0xFF; - } - - @Override - public double readDouble() - { - return ((NBTTagDouble)readTag()).data; - } - - @Override - public float readFloat() - { - return ((NBTTagFloat)readTag()).data; - } - - @Override - public boolean readBoolean() - { - return ((NBTTagByte)readTag()).data != 0; - } - - @Override - public char readChar() - { - return (char)((NBTTagShort)readTag()).data; - } - - @Override - public byte[] readByteArray(int length) - { - return ((NBTTagByteArray)readTag()).byteArray; - } - - @Override - public String readString() - { - return ((NBTTagString)readTag()).data; - } - - @Override - public BlockCoord readCoord() - { - return new BlockCoord(readInt(), readInt(), readInt()); - } - - @Override - public NBTTagCompound readNBTTagCompound() - { - return (NBTTagCompound)readTag(); - } - - @Override - public ItemStack readItemStack() - { - return ItemStack.loadItemStackFromNBT(readNBTTagCompound()); - } - - @Override - public FluidStack readFluidStack() - { - return FluidStack.loadFluidStackFromNBT(readNBTTagCompound()); - } - - private NBTBase readTag() - { - return readList.tagAt(readTag++); - } -} diff --git a/codechicken/lib/gui/Canvas9Seg.java b/codechicken/lib/gui/Canvas9Seg.java index b558197..055bb42 100644 --- a/codechicken/lib/gui/Canvas9Seg.java +++ b/codechicken/lib/gui/Canvas9Seg.java @@ -65,7 +65,7 @@ public class Canvas9Seg public void draw(int x, int y, int w, int h) { CCRenderState.changeTexture(tex); CCRenderState.reset(); - CCRenderState.startDrawing(7); + CCRenderState.startDrawing(); 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}; diff --git a/codechicken/lib/gui/GuiDraw.java b/codechicken/lib/gui/GuiDraw.java new file mode 100644 index 0000000..b930d26 --- /dev/null +++ b/codechicken/lib/gui/GuiDraw.java @@ -0,0 +1,223 @@ +package codechicken.lib.gui; + +import java.awt.Dimension; +import java.awt.Point; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import net.minecraft.util.EnumChatFormatting; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import codechicken.lib.math.MathHelper; +import codechicken.lib.render.CCRenderState; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.util.ResourceLocation; + +public class GuiDraw +{ + public static class GuiHook extends Gui + { + public void setZLevel(float f) { + zLevel = f; + } + + public float getZLevel() { + return zLevel; + } + + public void incZLevel(float f) { + zLevel += f; + } + + @Override + public void drawGradientRect(int par1, int par2, int par3, int par4, int par5, int par6) { + super.drawGradientRect(par1, par2, par3, par4, par5, par6); + } + } + + public static final GuiHook gui = new GuiHook(); + public static FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + public static TextureManager renderEngine = Minecraft.getMinecraft().renderEngine; + + public static void drawRect(int x, int y, int w, int h, int colour) { + drawGradientRect(x, y, w, h, colour, colour); + } + + public static void drawGradientRect(int x, int y, int w, int h, int colour1, int colour2) { + gui.drawGradientRect(x, y, x + w, y + h, colour1, colour2); + } + + public static void drawTexturedModalRect(int x, int y, int tx, int ty, int w, int h) { + gui.drawTexturedModalRect(x, y, tx, ty, w, h); + } + + public static void drawString(String text, int x, int y, int colour, boolean shadow) { + if (shadow) + fontRenderer.drawStringWithShadow(text, x, y, colour); + else + fontRenderer.drawString(text, x, y, colour); + } + + public static void drawString(String text, int x, int y, int colour) { + drawString(text, x, y, colour, true); + } + + public static void drawStringC(String text, int x, int y, int w, int h, int colour, boolean shadow) { + drawString(text, x + (w - getStringWidth(text)) / 2, y + (h - 8) / 2, colour, shadow); + } + + public static void drawStringC(String text, int x, int y, int w, int h, int colour) { + drawStringC(text, x, y, w, h, colour, true); + } + + public static void drawStringC(String text, int x, int y, int colour, boolean shadow) { + drawString(text, x - getStringWidth(text) / 2, y, colour, shadow); + } + + public static void drawStringC(String text, int x, int y, int colour) { + drawStringC(text, x, y, colour, true); + } + + public static void drawStringR(String text, int x, int y, int colour, boolean shadow) { + drawString(text, x - getStringWidth(text), y, colour, shadow); + } + + public static void drawStringR(String text, int x, int y, int colour) { + drawStringR(text, x, y, colour, true); + } + + + public static int getStringWidth(String s) { + if (s == null || s.equals("")) + return 0; + return fontRenderer.getStringWidth(EnumChatFormatting.getTextWithoutFormattingCodes(s)); + } + + public static Dimension displaySize() { + Minecraft mc = Minecraft.getMinecraft(); + ScaledResolution res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight); + return new Dimension(res.getScaledWidth(), res.getScaledHeight()); + } + + public static Dimension displayRes() { + Minecraft mc = Minecraft.getMinecraft(); + return new Dimension(mc.displayWidth, mc.displayHeight); + } + + public static Point getMousePosition() { + Dimension size = displaySize(); + Dimension res = displayRes(); + return new Point(Mouse.getX() * size.width / res.width, size.height - Mouse.getY() * size.height / res.height - 1); + } + + public static void changeTexture(String s) { + CCRenderState.changeTexture(s); + } + + public static void changeTexture(ResourceLocation r) { + CCRenderState.changeTexture(r); + } + + public static void drawTip(int x, int y, String text) { + drawMultilineTip(x, y, Arrays.asList(text)); + } + + /** + * Append a string in the tooltip list with TOOLTIP_LINESPACE to have a small gap between it and the next line + */ + public static final String TOOLTIP_LINESPACE = "\u00A7h"; + /** + * Have a string in the tooltip list with TOOLTIP_HANDLER + getTipLineId(handler) for a custom handler + */ + public static final String TOOLTIP_HANDLER = "\u00A7x"; + private static List tipLineHandlers = new ArrayList(); + + public static interface ITooltipLineHandler + { + public Dimension getSize(); + + public void draw(int x, int y); + } + + public static int getTipLineId(ITooltipLineHandler handler) { + tipLineHandlers.add(handler); + return tipLineHandlers.size()-1; + } + + public static ITooltipLineHandler getTipLine(String line) { + if(!line.startsWith(TOOLTIP_HANDLER)) + return null; + return tipLineHandlers.get(Integer.parseInt(line.substring(2))); + } + + public static void drawMultilineTip(int x, int y, List list) { + if (list.isEmpty()) + return; + + GL11.glDisable(GL12.GL_RESCALE_NORMAL); + GL11.glDisable(GL11.GL_DEPTH_TEST); + RenderHelper.disableStandardItemLighting(); + + int w = 0; + int h = -2; + for (int i = 0; i < list.size(); i++) { + String s = list.get(i); + ITooltipLineHandler line = getTipLine(s); + Dimension d = line != null ? + line.getSize() : + new Dimension(getStringWidth(s), list.get(i).endsWith(TOOLTIP_LINESPACE) && i + 1 < list.size() ? 12 : 10); + w = Math.max(w, d.width); + h += d.height; + } + + if (x < 8) x = 8; + else if (x > displaySize().width - w - 8) x -= 24 + w;//flip side of cursor + y = (int) MathHelper.clip(y, 8, displaySize().height - 8 - h); + + gui.incZLevel(300); + drawTooltipBox(x - 4, y - 4, w + 7, h + 7); + for (String s : list) { + ITooltipLineHandler line = getTipLine(s); + if(line != null) { + line.draw(x, y); + y += line.getSize().height; + } + else { + fontRenderer.drawStringWithShadow(s, x, y, -1); + y += s.endsWith(TOOLTIP_LINESPACE) ? 12 : 10; + } + } + + tipLineHandlers.clear(); + gui.incZLevel(-300); + + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + RenderHelper.enableGUIStandardItemLighting(); + } + + 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); + + drawGradientRect(x + 1, y + 1, w - 1, 1, grad1, grad1); + drawGradientRect(x + 1, y + h - 1, w - 1, 1, grad2, grad2); + } +} diff --git a/codechicken/lib/inventory/InventoryCopy.java b/codechicken/lib/inventory/InventoryCopy.java index 8bcfdd5..5843404 100644 --- a/codechicken/lib/inventory/InventoryCopy.java +++ b/codechicken/lib/inventory/InventoryCopy.java @@ -76,11 +76,11 @@ public class InventoryCopy implements IInventory public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; - onInventoryChanged(); + markDirty(); } @Override - public String getInvName() + public String getInventoryName() { return "copy"; } @@ -91,12 +91,13 @@ public class InventoryCopy implements IInventory return true; } - public void openChest() + @Override + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -106,9 +107,8 @@ public class InventoryCopy implements IInventory return 64; } - @Override - public void onInventoryChanged() + public void markDirty() { } @@ -119,7 +119,7 @@ public class InventoryCopy implements IInventory } @Override - public boolean isInvNameLocalized() + public boolean hasCustomInventoryName() { return true; } diff --git a/codechicken/lib/inventory/InventoryNBT.java b/codechicken/lib/inventory/InventoryNBT.java index a6e338c..45aa54f 100644 --- a/codechicken/lib/inventory/InventoryNBT.java +++ b/codechicken/lib/inventory/InventoryNBT.java @@ -28,7 +28,7 @@ public class InventoryNBT implements IInventory private void readNBT() { if(tag.hasKey("items")) - InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items")); + InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items", 10)); } @Override @@ -59,11 +59,11 @@ public class InventoryNBT implements IInventory public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; - onInventoryChanged(); + markDirty(); } @Override - public String getInvName() + public String getInventoryName() { return "NBT"; } @@ -75,7 +75,7 @@ public class InventoryNBT implements IInventory } @Override - public void onInventoryChanged() + public void markDirty() { writeNBT(); } @@ -87,12 +87,12 @@ public class InventoryNBT implements IInventory } @Override - public void openChest() + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -103,7 +103,7 @@ public class InventoryNBT implements IInventory } @Override - public boolean isInvNameLocalized() + public boolean hasCustomInventoryName() { return true; } diff --git a/codechicken/lib/inventory/InventorySimple.java b/codechicken/lib/inventory/InventorySimple.java index 12b1c8e..4481c23 100644 --- a/codechicken/lib/inventory/InventorySimple.java +++ b/codechicken/lib/inventory/InventorySimple.java @@ -83,11 +83,11 @@ public class InventorySimple implements IInventory public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; - onInventoryChanged(); + markDirty(); } @Override - public String getInvName() + public String getInventoryName() { return name; } @@ -105,12 +105,12 @@ public class InventorySimple implements IInventory } @Override - public void openChest() + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -121,13 +121,13 @@ public class InventorySimple implements IInventory } @Override - public boolean isInvNameLocalized() + public boolean hasCustomInventoryName() { return true; } @Override - public void onInventoryChanged() + public void markDirty() { } } diff --git a/codechicken/lib/inventory/InventoryUtils.java b/codechicken/lib/inventory/InventoryUtils.java index 921b3df..7f063e1 100644 --- a/codechicken/lib/inventory/InventoryUtils.java +++ b/codechicken/lib/inventory/InventoryUtils.java @@ -5,44 +5,54 @@ import com.google.common.base.Objects; import codechicken.lib.vec.Vector3; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryLargeChest; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagInt; import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagShort; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.world.World; -import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.common.util.ForgeDirection; public class InventoryUtils { + /** + * Constructor for ItemStack with tag + */ + public static ItemStack newItemStack(Item item, int size, int damage, NBTTagCompound tag) { + ItemStack stack = new ItemStack(item, size, damage); + stack.stackTagCompound = tag; + return stack; + } + + /** + * Gets the actual damage of an item without asking the Item + */ + public static int actualDamage(ItemStack stack) { + return Items.diamond.getDamage(stack); + } + /** * Static default implementation for IInventory method */ - public static ItemStack decrStackSize(IInventory inv, int slot, int size) - { + public static ItemStack decrStackSize(IInventory inv, int slot, int size) { ItemStack item = inv.getStackInSlot(slot); - - if(item != null) - { - if(item.stackSize <= size) - { - ItemStack itemstack = item; + + if (item != null) { + if (item.stackSize <= size) { inv.setInventorySlotContents(slot, null); - inv.onInventoryChanged(); - return itemstack; + inv.markDirty(); + return item; } ItemStack itemstack1 = item.splitStack(size); - if(item.stackSize == 0) - { + if (item.stackSize == 0) inv.setInventorySlotContents(slot, null); - } - inv.onInventoryChanged(); + + inv.markDirty(); return itemstack1; } return null; @@ -51,8 +61,7 @@ public class InventoryUtils /** * Static default implementation for IInventory method */ - public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) - { + public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); inv.setInventorySlotContents(slot, null); return stack; @@ -61,56 +70,50 @@ public class InventoryUtils /** * @return The quantity of items from addition that can be added to base */ - public static int incrStackSize(ItemStack base, ItemStack addition) - { + public static int incrStackSize(ItemStack base, ItemStack addition) { if (canStack(base, addition)) return incrStackSize(base, addition.stackSize); - + return 0; } - + /** * @return The quantity of items from addition that can be added to base */ - public static int incrStackSize(ItemStack base, int addition) - { + public static int incrStackSize(ItemStack base, int addition) { int totalSize = base.stackSize + addition; if (totalSize <= base.getMaxStackSize()) return addition; else if (base.stackSize < base.getMaxStackSize()) return base.getMaxStackSize() - base.stackSize; - + return 0; } /** * NBT item saving function */ - public static NBTTagList writeItemStacksToTag(ItemStack[] items) - { + public static NBTTagList writeItemStacksToTag(ItemStack[] items) { return writeItemStacksToTag(items, 64); } /** * NBT item saving function with support for stack sizes > 32K */ - public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity) - { + public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity) { NBTTagList tagList = new NBTTagList(); - for(int i = 0; i < items.length; i++) - { - if (items[i] != null) - { + for (int i = 0; i < items.length; i++) { + if (items[i] != null) { NBTTagCompound tag = new NBTTagCompound(); tag.setShort("Slot", (short) i); items[i].writeToNBT(tag); - - if(maxQuantity > Short.MAX_VALUE) + + if (maxQuantity > Short.MAX_VALUE) tag.setInteger("Quantity", items[i].stackSize); - else if(maxQuantity > Byte.MAX_VALUE) + else if (maxQuantity > Byte.MAX_VALUE) tag.setShort("Quantity", (short) items[i].stackSize); - + tagList.appendTag(tag); } } @@ -120,29 +123,20 @@ public class InventoryUtils /** * NBT item loading function with support for stack sizes > 32K */ - public static void readItemStacksFromTag(ItemStack[] items, NBTTagList tagList) - { - for(int i = 0; i < tagList.tagCount(); i++) - { - NBTTagCompound tag = (NBTTagCompound) tagList.tagAt(i); + public static void readItemStacksFromTag(ItemStack[] items, NBTTagList tagList) { + for (int i = 0; i < tagList.tagCount(); i++) { + NBTTagCompound tag = tagList.getCompoundTagAt(i); int b = tag.getShort("Slot"); items[b] = ItemStack.loadItemStackFromNBT(tag); - if(tag.hasKey("Quantity")) - { - NBTBase qtag = tag.getTag("Quantity"); - if(qtag instanceof NBTTagInt) - items[b].stackSize = ((NBTTagInt)qtag).data; - else if(qtag instanceof NBTTagShort) - items[b].stackSize = ((NBTTagShort)qtag).data; - } + if (tag.hasKey("Quantity")) + items[b].stackSize = ((NBTBase.NBTPrimitive) tag.getTag("Quantity")).func_150287_d(); } } /** * Spawns an itemstack in the world at a location */ - public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) - { + public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) { EntityItem item = new EntityItem(world, dropLocation.x, dropLocation.y, dropLocation.z, stack); item.motionX = world.rand.nextGaussian() * 0.05; item.motionY = world.rand.nextGaussian() * 0.05 + 0.2F; @@ -153,11 +147,10 @@ public class InventoryUtils /** * Copies an itemstack with a new quantity */ - public static ItemStack copyStack(ItemStack stack, int quantity) - { - if(stack == null) + public static ItemStack copyStack(ItemStack stack, int quantity) { + if (stack == null) return null; - + stack = stack.copy(); stack.stackSize = quantity; return stack; @@ -166,102 +159,87 @@ public class InventoryUtils /** * Gets the maximum quantity of an item that can be inserted into inv */ - public static int getInsertibleQuantity(InventoryRange inv, ItemStack stack) - { + public static int getInsertibleQuantity(InventoryRange inv, ItemStack stack) { int quantity = 0; stack = copyStack(stack, Integer.MAX_VALUE); - for(int slot : inv.slots) - quantity+=fitStackInSlot(inv, slot, stack); - + for (int slot : inv.slots) + quantity += fitStackInSlot(inv, slot, stack); + return quantity; } - public static int getInsertibleQuantity(IInventory inv, ItemStack stack) - { + public static int getInsertibleQuantity(IInventory inv, ItemStack stack) { return getInsertibleQuantity(new InventoryRange(inv), stack); } - - public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) - { + + public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) { ItemStack base = inv.inv.getStackInSlot(slot); - if(!canStack(base, stack) || !inv.canInsertItem(slot, stack)) + if (!canStack(base, stack) || !inv.canInsertItem(slot, stack)) return 0; - int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit()-base.stackSize) : inv.inv.getInventoryStackLimit(); + int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit() - base.stackSize) : inv.inv.getInventoryStackLimit(); return Math.min(fit, stack.stackSize); } - public static int fitStackInSlot(IInventory inv, int slot, ItemStack stack) - { + public static int fitStackInSlot(IInventory inv, int slot, ItemStack stack) { return fitStackInSlot(new InventoryRange(inv), slot, stack); } /** - * @param simulate. If set to true, no items will actually be inserted + * @param simulate If set to true, no items will actually be inserted * @return The number of items unable to be inserted */ - public static int insertItem(InventoryRange inv, ItemStack stack, boolean simulate) - { + public static int insertItem(InventoryRange inv, ItemStack stack, boolean simulate) { stack = stack.copy(); - for(int pass = 0; pass < 2; pass++) - { - for(int slot : inv.slots) - { + for (int pass = 0; pass < 2; pass++) { + for (int slot : inv.slots) { ItemStack base = inv.inv.getStackInSlot(slot); int fit = fitStackInSlot(inv, slot, stack); - if(fit == 0) + if (fit == 0) continue; - - if(base != null) - { - stack.stackSize-=fit; - if(!simulate) - { - base.stackSize+=fit; + + if (base != null) { + stack.stackSize -= fit; + if (!simulate) { + base.stackSize += fit; inv.inv.setInventorySlotContents(slot, base); } - } - else if(pass == 1) - { - if(!simulate) + } else if (pass == 1) { + if (!simulate) inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); - stack.stackSize-=fit; + stack.stackSize -= fit; } - if(stack.stackSize == 0) + if (stack.stackSize == 0) return 0; } } return stack.stackSize; } - public static int insertItem(IInventory inv, ItemStack stack, boolean simulate) - { + public static int insertItem(IInventory inv, ItemStack stack, boolean simulate) { return insertItem(new InventoryRange(inv), stack, simulate); } /** * Gets the stack in slot if it can be extracted */ - public static ItemStack getExtractableStack(InventoryRange inv, int slot) - { + public static ItemStack getExtractableStack(InventoryRange inv, int slot) { ItemStack stack = inv.inv.getStackInSlot(slot); - if(stack == null || !inv.canExtractItem(slot, stack)) + if (stack == null || !inv.canExtractItem(slot, stack)) return null; return stack; } - public static ItemStack getExtractableStack(IInventory inv, int slot) - { + public static ItemStack getExtractableStack(IInventory inv, int slot) { return getExtractableStack(new InventoryRange(inv), slot); } - public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) - { - if(stack1 == null || stack2 == null) + public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) { + if (stack1 == null || stack2 == null) return stack1 == stack2; - return stack1.itemID == stack2.itemID + return stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage() && stack1.stackSize == stack2.stackSize && Objects.equal(stack1.getTagCompound(), stack2.getTagCompound()); @@ -270,53 +248,46 @@ public class InventoryUtils /** * Gets an IInventory from a coordinate with support for double chests */ - public static IInventory getInventory(World world, int x, int y, int z) - { - TileEntity tile = world.getBlockTileEntity(x, y, z); - if(!(tile instanceof IInventory)) + public static IInventory getInventory(World world, int x, int y, int z) { + TileEntity tile = world.getTileEntity(x, y, z); + if (!(tile instanceof IInventory)) return null; - - if(tile instanceof TileEntityChest) + + if (tile instanceof TileEntityChest) return getChest((TileEntityChest) tile); - return (IInventory)tile; - + return (IInventory) tile; + } - + public static final ForgeDirection[] chestSides = new ForgeDirection[]{ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.NORTH, ForgeDirection.SOUTH}; - public static IInventory getChest(TileEntityChest chest) - { - for(ForgeDirection fside : chestSides) - { - if(chest.worldObj.getBlockId(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ) == chest.getBlockType().blockID) - return new InventoryLargeChest("container.chestDouble", - (TileEntityChest)chest.worldObj.getBlockTileEntity(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ), chest); + + public static IInventory getChest(TileEntityChest chest) { + for (ForgeDirection fside : chestSides) { + if (chest.getWorldObj().getBlock(chest.xCoord + fside.offsetX, chest.yCoord + fside.offsetY, chest.zCoord + fside.offsetZ) == chest.getBlockType()) + return new InventoryLargeChest("container.chestDouble", + (TileEntityChest) chest.getWorldObj().getTileEntity(chest.xCoord + fside.offsetX, chest.yCoord + fside.offsetY, chest.zCoord + fside.offsetZ), chest); } return chest; } - public static boolean canStack(ItemStack stack1, ItemStack stack2) - { - return stack1 == null || stack2 == null || - (stack1.itemID == stack2.itemID && - (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && - ItemStack.areItemStackTagsEqual(stack2, stack1)) && - stack1.isStackable(); + public static boolean canStack(ItemStack stack1, ItemStack stack2) { + return stack1 == null || stack2 == null || + (stack1.getItem() == stack2.getItem() && + (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && + ItemStack.areItemStackTagsEqual(stack2, stack1)) && + stack1.isStackable(); } /** * Consumes one item from slot in inv with support for containers. */ - public static void consumeItem(IInventory inv, int slot) - { + public static void consumeItem(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); Item item = stack.getItem(); - if(item.hasContainerItem()) - { - ItemStack container = item.getContainerItemStack(stack); + if (item.hasContainerItem(stack)) { + ItemStack container = item.getContainerItem(stack); inv.setInventorySlotContents(slot, container); - } - else - { + } else { inv.decrStackSize(slot, 1); } } @@ -324,8 +295,7 @@ public class InventoryUtils /** * Gets the size of the stack in a slot. Returns 0 on null stacks */ - public static int stackSize(IInventory inv, int slot) - { + public static int stackSize(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); return stack == null ? 0 : stack.stackSize; } @@ -333,21 +303,30 @@ public class InventoryUtils /** * Drops all items from inv using getStackInSlotOnClosing */ - public static void dropOnClose(EntityPlayer player, IInventory inv) - { - for (int i = 0; i < inv.getSizeInventory(); i++) - { + public static void dropOnClose(EntityPlayer player, IInventory inv) { + for (int i = 0; i < inv.getSizeInventory(); i++) { ItemStack stack = inv.getStackInSlotOnClosing(i); if (stack != null) - player.dropPlayerItem(stack); + player.dropPlayerItemWithRandomChoice(stack, false); } } - /** - * Gets the actual damage of an item without asking the Item - */ - public static int actualDamage(ItemStack stack) - { - return Item.diamond.getDamage(stack); + public static NBTTagCompound savePersistant(ItemStack stack, NBTTagCompound tag) { + stack.writeToNBT(tag); + tag.removeTag("id"); + tag.setString("name", Item.itemRegistry.getNameForObject(stack.getItem())); + return tag; + } + + public static ItemStack loadPersistant(NBTTagCompound tag) { + String name = tag.getString("name"); + Item item = (Item) Item.itemRegistry.getObject(name); + if(item == null) return null; + int count = tag.hasKey("Count") ? tag.getByte("Count") : 1; + int damage = tag.hasKey("Damage") ? tag.getShort("Damage") : 0; + ItemStack stack = new ItemStack(item, count, damage); + if(tag.hasKey("tag", 10)) + stack.stackTagCompound = tag.getCompoundTag("tag"); + return stack; } } diff --git a/codechicken/lib/inventory/ItemKey.java b/codechicken/lib/inventory/ItemKey.java index e52a923..0adb687 100644 --- a/codechicken/lib/inventory/ItemKey.java +++ b/codechicken/lib/inventory/ItemKey.java @@ -1,9 +1,12 @@ package codechicken.lib.inventory; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import com.google.common.base.Objects; +import net.minecraftforge.oredict.OreDictionary; + import static codechicken.lib.inventory.InventoryUtils.*; /** @@ -11,55 +14,52 @@ import static codechicken.lib.inventory.InventoryUtils.*; */ public class ItemKey implements Comparable { - public ItemStack item; + public ItemStack stack; private int hashcode = 0; - - public ItemKey(ItemStack k) - { - item = k; + + public ItemKey(ItemStack k) { + stack = k; } - public ItemKey(int id, int damage) - { - this(new ItemStack(id, 1, damage)); + public ItemKey(Item item, int damage) { + this(new ItemStack(item, 1, damage)); } - - public ItemKey(int id, int damage, NBTTagCompound compound) - { - this(id, damage); - item.setTagCompound(compound); + + public ItemKey(Item item, NBTTagCompound tag) { + this(item, OreDictionary.WILDCARD_VALUE, tag); + } + + public ItemKey(Item item, int damage, NBTTagCompound tag) { + this(item, damage); + stack.setTagCompound(tag); } @Override - public boolean equals(Object obj) - { - if(!(obj instanceof ItemKey)) + public boolean equals(Object obj) { + if (!(obj instanceof ItemKey)) return false; - - ItemKey k = (ItemKey)obj; - return item.itemID == k.item.itemID && - actualDamage(item) == actualDamage(k.item) && - Objects.equal(item.stackTagCompound, k.item.stackTagCompound); + + ItemKey k = (ItemKey) obj; + return stack.getItem() == k.stack.getItem() && + actualDamage(stack) == actualDamage(k.stack) && + Objects.equal(stack.stackTagCompound, k.stack.stackTagCompound); } - + @Override - public int hashCode() - { - return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(item.itemID, actualDamage(item), item.stackTagCompound)); + public int hashCode() { + return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(stack.getItem(), actualDamage(stack), stack.stackTagCompound)); } - - public int compareInt(int a, int b) - { + + public int compareInt(int a, int b) { return a == b ? 0 : a < b ? -1 : 1; } @Override - public int compareTo(ItemKey o) - { - if(item.itemID != o.item.itemID) - return compareInt(item.itemID, o.item.itemID); - if(actualDamage(item) != actualDamage(o.item)) - return compareInt(actualDamage(item), actualDamage(o.item)); + public int compareTo(ItemKey o) { + if (stack.getItem() != o.stack.getItem()) + return compareInt(Item.getIdFromItem(stack.getItem()), Item.getIdFromItem(o.stack.getItem())); + if (actualDamage(stack) != actualDamage(o.stack)) + return compareInt(actualDamage(stack), actualDamage(o.stack)); return 0; } } diff --git a/codechicken/lib/lang/LangUtil.java b/codechicken/lib/lang/LangUtil.java deleted file mode 100644 index 767887b..0000000 --- a/codechicken/lib/lang/LangUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -package codechicken.lib.lang; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.SortedSet; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.Language; -import net.minecraft.client.resources.Resource; -import net.minecraft.client.resources.ResourceManager; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.StatCollector; - -import cpw.mods.fml.common.registry.LanguageRegistry; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -/** - * Easy localisation access. - */ -public class LangUtil -{ - public static LangUtil instance = new LangUtil(null); - - public String prefix; - - public LangUtil(String prefix) - { - this.prefix = prefix; - } - - public static String translateG(String s, Object... format) - { - return instance.translate(s, format); - } - - public String translate(String s, Object... format) - { - if(prefix != null && !s.startsWith(prefix+".")) - s = prefix+"."+s; - String ret = LanguageRegistry.instance().getStringLocalization(s); - if(ret.length() == 0) - ret = LanguageRegistry.instance().getStringLocalization(s, "en_US"); - if(ret.length() == 0) - ret = StatCollector.translateToLocal(s); - if(ret.length() == 0) - return s; - if(format.length > 0) - ret = String.format(ret, format); - return ret; - } - - public void addLangFile(InputStream resource, String lang) throws IOException - { - LanguageRegistry reg = LanguageRegistry.instance(); - BufferedReader reader = new BufferedReader(new InputStreamReader(resource, "UTF-8")); - while(true) - { - String read = reader.readLine(); - if(read == null) - break; - - int equalIndex = read.indexOf('='); - if(equalIndex == -1) - continue; - String key = read.substring(0, equalIndex); - String value = read.substring(equalIndex+1); - if(prefix != null) - key = prefix+"."+key; - reg.addStringLocalization(key, lang, value); - } - } - - @SideOnly(Side.CLIENT) - public static LangUtil loadLangDir(String domain) - { - return new LangUtil(domain).addLangDir(new ResourceLocation(domain, "lang")); - } - - @SideOnly(Side.CLIENT) - public LangUtil addLangDir(ResourceLocation dir) - { - ResourceManager resManager = Minecraft.getMinecraft().getResourceManager(); - for(Language lang : (SortedSet)Minecraft.getMinecraft().getLanguageManager().getLanguages()) - { - String langID = lang.getLanguageCode(); - Resource langRes; - try - { - langRes = resManager.getResource(new ResourceLocation(dir.getResourceDomain(), dir.getResourcePath()+'/'+langID+".lang")); - } - catch(Exception e) - { - continue; - } - try - { - addLangFile(langRes.getInputStream(), langID); - } - catch(IOException e) - { - System.err.println("Failed to load lang resource. domain="+prefix+", resource="+langRes); - e.printStackTrace(); - } - } - - return this; - } -} diff --git a/codechicken/lib/lighting/CCRBModel.java b/codechicken/lib/lighting/CCRBModel.java deleted file mode 100644 index a3074b0..0000000 --- a/codechicken/lib/lighting/CCRBModel.java +++ /dev/null @@ -1,31 +0,0 @@ -package codechicken.lib.lighting; - -import codechicken.lib.render.CCModel; -import codechicken.lib.render.Vertex5; - -public class CCRBModel extends CCModel -{ - public LC[] lightCoefficents; - - /** - * Lighting sides and coefficients are computed for each vertex of the model. All faces must be axis planar and all verts are assumed to be in the range (0,0,0) to (1,1,1) - */ - public CCRBModel(CCModel m) - { - super(m.vertexMode); - verts = new Vertex5[m.verts.length]; - copy(m, 0, this, 0, m.verts.length); - if(normals == null) - computeNormals(); - if(colours == null) - setColour(-1); - computeLighting(); - } - - private void computeLighting() - { - lightCoefficents = new LC[verts.length]; - for(int k = 0; k < verts.length; k++) - lightCoefficents[k] = LC.compute(verts[k].vec, normals[k]); - } -} diff --git a/codechicken/lib/lighting/LC.java b/codechicken/lib/lighting/LC.java index baa3ab7..c2409fb 100644 --- a/codechicken/lib/lighting/LC.java +++ b/codechicken/lib/lighting/LC.java @@ -1,59 +1,89 @@ package codechicken.lib.lighting; import codechicken.lib.render.CCModel; +import codechicken.lib.util.Copyable; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -public class LC +public class LC implements Copyable { - public LC(int s, float e, float f, float g, float h) - { - side = s; - fa = e; - fb = f; - fc = g; - fd = h; - } - public int side; public float fa; public float fb; public float fc; public float fd; - - public static LC compute(Vector3 vec, Vector3 normal) - { + + public LC() { + this(0, 0, 0, 0, 0); + } + + public LC(int s, float a, float b, float c, float d) { + side = s; + fa = a; + fb = b; + fc = c; + fd = d; + } + + public LC set(int s, float a, float b, float c, float d) { + side = s; + fa = a; + fb = b; + fc = c; + fd = d; + return this; + } + + public LC set(LC lc) { + return set(lc.side, lc.fa, lc.fb, lc.fc, lc.fd); + } + + public LC compute(Vector3 vec, Vector3 normal) { int side = CCModel.findSide(normal); - if(side < 0) - return new LC(12, 1, 0, 0, 0); + if (side < 0) + return set(12, 1, 0, 0, 0); return compute(vec, side); } - - public static LC compute(Vector3 vec, int side) - { + + public LC compute(Vector3 vec, int side) { boolean offset = false; - switch(side) - { - case 0: offset = vec.y <= 0; break; - case 1: offset = vec.y >= 1; break; - case 2: offset = vec.z <= 0; break; - case 3: offset = vec.z >= 1; break; - case 4: offset = vec.x <= 0; break; - case 5: offset = vec.x >= 1; break; + switch (side) { + case 0: + offset = vec.y <= 0; + break; + case 1: + offset = vec.y >= 1; + break; + case 2: + offset = vec.z <= 0; + break; + case 3: + offset = vec.z >= 1; + break; + case 4: + offset = vec.x <= 0; + break; + case 5: + offset = vec.x >= 1; + break; } - if(!offset) - side+=6; + if (!offset) + side += 6; return computeO(vec, side); } - public static LC computeO(Vector3 vec, int side) - { - Vector3 v1 = Rotation.axes[((side&0xE)+3)%6]; - Vector3 v2 = Rotation.axes[((side&0xE)+5)%6]; + public LC computeO(Vector3 vec, int side) { + Vector3 v1 = Rotation.axes[((side & 0xE) + 3) % 6]; + Vector3 v2 = Rotation.axes[((side & 0xE) + 5) % 6]; float d1 = (float) vec.scalarProject(v1); - float d2 = 1-d1; + float d2 = 1 - d1; float d3 = (float) vec.scalarProject(v2); - float d4 = 1-d3; - return new LC(side, d2*d4, d2*d3, d1*d4, d1*d3); + float d4 = 1 - d3; + return set(side, d2 * d4, d2 * d3, d1 * d4, d1 * d3); + } + + @Override + public LC copy() { + return new LC(side, fa, fb, fc, fd); } } \ No newline at end of file diff --git a/codechicken/lib/lighting/LazyLightMatrix.java b/codechicken/lib/lighting/LazyLightMatrix.java deleted file mode 100644 index 3c957cd..0000000 --- a/codechicken/lib/lighting/LazyLightMatrix.java +++ /dev/null @@ -1,28 +0,0 @@ -package codechicken.lib.lighting; - -import net.minecraft.world.IBlockAccess; -import codechicken.lib.vec.BlockCoord; - -public class LazyLightMatrix -{ - private BlockCoord pos = new BlockCoord(); - private IBlockAccess access; - private boolean computed = false; - private LightMatrix lightMatrix = new LightMatrix(); - - public LightMatrix lightMatrix() - { - if(computed) - return lightMatrix; - computed = true; - lightMatrix.computeAt(access, pos.x, pos.y, pos.z); - return lightMatrix; - } - - public void setPos(IBlockAccess access, int x, int y, int z) - { - computed = false; - this.access = access; - pos.set(x, y, z); - } -} \ No newline at end of file diff --git a/codechicken/lib/lighting/LightMatrix.java b/codechicken/lib/lighting/LightMatrix.java index 882ea0b..54cf902 100644 --- a/codechicken/lib/lighting/LightMatrix.java +++ b/codechicken/lib/lighting/LightMatrix.java @@ -1,30 +1,31 @@ package codechicken.lib.lighting; -import codechicken.lib.render.CCModel; +import codechicken.lib.colour.ColourRGBA; import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.IVertexModifier; -import codechicken.lib.render.UV; import codechicken.lib.vec.BlockCoord; import codechicken.lib.vec.Vector3; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.Tessellator; import net.minecraft.world.IBlockAccess; /** * Note that when using the class as a vertex transformer, the vertices are assumed to be within the BB (x, y, z) -> (x+1, y+1, z+1) */ -public class LightMatrix implements IVertexModifier +public class LightMatrix implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); + public int computed = 0; public float[][] ao = new float[13][4]; public int[][] brightness = new int[13][4]; + + public IBlockAccess access; public BlockCoord pos = new BlockCoord(); - + + private int sampled = 0; private float[] aSamples = new float[27]; private int[] bSamples = new int[27]; - private Vector3 v_temp = new Vector3(); - + /** * The 9 positions in the sample array for each side, sides >= 6 are centered on sample 13 (the block itself) */ @@ -73,137 +74,88 @@ public class LightMatrix implements IVertexModifier } System.out.println(Arrays.deepToString(ssamplem)); }*/ - - public void computeAt(IBlockAccess a, int x, int y, int z) - { + + public void locate(IBlockAccess a, int x, int y, int z) { + access = a; pos.set(x, y, z); computed = 0; - //inc x, inc z, inc y - sample( 0, aSamples, bSamples, a, x-1, y-1, z-1); - sample( 1, aSamples, bSamples, a, x , y-1, z-1); - sample( 2, aSamples, bSamples, a, x+1, y-1, z-1); - sample( 3, aSamples, bSamples, a, x-1, y-1, z ); - sample( 4, aSamples, bSamples, a, x , y-1, z ); - sample( 5, aSamples, bSamples, a, x+1, y-1, z ); - sample( 6, aSamples, bSamples, a, x-1, y-1, z+1); - sample( 7, aSamples, bSamples, a, x , y-1, z+1); - sample( 8, aSamples, bSamples, a, x+1, y-1, z+1); - sample( 9, aSamples, bSamples, a, x-1, y , z-1); - sample(10, aSamples, bSamples, a, x , y , z-1); - sample(11, aSamples, bSamples, a, x+1, y , z-1); - sample(12, aSamples, bSamples, a, x-1, y , z ); - sample(13, aSamples, bSamples, a, x , y , z ); - sample(14, aSamples, bSamples, a, x+1, y , z ); - sample(15, aSamples, bSamples, a, x-1, y , z+1); - sample(16, aSamples, bSamples, a, x , y , z+1); - sample(17, aSamples, bSamples, a, x+1, y , z+1); - sample(18, aSamples, bSamples, a, x-1, y+1, z-1); - sample(19, aSamples, bSamples, a, x , y+1, z-1); - sample(20, aSamples, bSamples, a, x+1, y+1, z-1); - sample(21, aSamples, bSamples, a, x-1, y+1, z ); - sample(22, aSamples, bSamples, a, x , y+1, z ); - sample(23, aSamples, bSamples, a, x+1, y+1, z ); - sample(24, aSamples, bSamples, a, x-1, y+1, z+1); - sample(25, aSamples, bSamples, a, x , y+1, z+1); - sample(26, aSamples, bSamples, a, x+1, y+1, z+1); + sampled = 0; } - - public int[] brightness(int side) - { + + public void sample(int i) { + if ((sampled & 1 << i) == 0) { + int x = pos.x + (i % 3) - 1; + int y = pos.y + (i / 9) - 1; + int z = pos.z + (i / 3 % 3) - 1; + Block b = access.getBlock(x, y, z); + bSamples[i] = access.getLightBrightnessForSkyBlocks(x, y, z, b.getLightValue(access, x, y, z)); + aSamples[i] = b.getAmbientOcclusionLightValue(); + } + } + + public int[] brightness(int side) { sideSample(side); return brightness[side]; } - - public float[] ao(int side) - { + + public float[] ao(int side) { sideSample(side); return ao[side]; } - - public void sideSample(int side) - { - if((computed&1<>2 & 0xFF00FF; + return (a + b + c + d) >> 2 & 0xFF00FF; } - public void setColour(Tessellator tess, LC lc, int c) - { - float[] a = ao(lc.side); - float f = (a[0]*lc.fa + a[1]*lc.fb + a[2]*lc.fc + a[3]*lc.fd); - CCRenderState.vertexColour((int)((c>>>24)*f), (int)((c>>16&0xFF)*f), (int)((c>>8&0xFF)*f), (c&0xFF)); - } - - public void setBrightness(Tessellator tess, LC lc) - { - int[] b = brightness(lc.side); - tess.setBrightness((int)(b[0]*lc.fa + b[1]*lc.fb + b[2]*lc.fc+b[3]*lc.fd) & 0xFF00FF); - } - @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - LC lc; - if(m instanceof CCRBModel) - lc = ((CCRBModel)m).lightCoefficents[i]; - else - lc = LC.compute(v_temp.set(vec).add(-pos.x, -pos.y, -pos.z), normal); - - setColour(tess, lc, (m == null || m.colours == null) ? -1 : m.colours[i]); - setBrightness(tess, lc); - } - - @Override - public boolean needsNormals() - { + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.lightCoordAttrib); return true; } + + @Override + public void operate() { + LC lc = CCRenderState.lc; + 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); + CCRenderState.setColour(ColourRGBA.multiplyC(CCRenderState.colour, f)); + CCRenderState.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF); + } + + @Override + public int operationID() { + return operationIndex; + } } \ No newline at end of file diff --git a/codechicken/lib/lighting/LightModel.java b/codechicken/lib/lighting/LightModel.java index 831298d..88bf784 100644 --- a/codechicken/lib/lighting/LightModel.java +++ b/codechicken/lib/lighting/LightModel.java @@ -3,60 +3,55 @@ package codechicken.lib.lighting; import net.minecraft.client.renderer.Tessellator; import codechicken.lib.render.CCModel; import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.IVertexModifier; -import codechicken.lib.render.UV; +import codechicken.lib.render.uv.UV; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -public class LightModel implements IVertexModifier +public class LightModel implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); + public static class Light { public Vector3 ambient = new Vector3(); public Vector3 diffuse = new Vector3(); public Vector3 position; - - public Light(Vector3 pos) - { + + public Light(Vector3 pos) { position = pos.copy().normalize(); } - - public Light setDiffuse(Vector3 vec) - { + + public Light setDiffuse(Vector3 vec) { diffuse.set(vec); return this; } - - public Light setAmbient(Vector3 vec) - { + + public Light setAmbient(Vector3 vec) { ambient.set(vec); return this; } } public static LightModel standardLightModel; - static - { + static { standardLightModel = new LightModel() .setAmbient(new Vector3(0.4, 0.4, 0.4)) .addLight(new Light(new Vector3(0.2, 1, -0.7)) - .setDiffuse(new Vector3(0.6, 0.6, 0.6))) + .setDiffuse(new Vector3(0.6, 0.6, 0.6))) .addLight(new Light(new Vector3(-0.2, 1, 0.7)) - .setDiffuse(new Vector3(0.6, 0.6, 0.6))); + .setDiffuse(new Vector3(0.6, 0.6, 0.6))); } private Vector3 ambient = new Vector3(); private Light[] lights = new Light[8]; private int lightCount; - - public LightModel addLight(Light light) - { + + public LightModel addLight(Light light) { lights[lightCount++] = light; return this; } - - public LightModel setAmbient(Vector3 vec) - { + + public LightModel setAmbient(Vector3 vec) { ambient.set(vec); return this; } @@ -66,46 +61,48 @@ public class LightModel implements IVertexModifier * @param normal The normal at the vertex * @return The lighting applied colour */ - public int apply(int colour, Vector3 normal) - { + public int apply(int colour, Vector3 normal) { Vector3 n_colour = ambient.copy(); - for(int l = 0; l < lightCount; l++) - { + for (int l = 0; l < lightCount; l++) { Light light = lights[l]; double n_l = light.position.dotProduct(normal); double f = n_l > 0 ? 1 : 0; - n_colour.x += light.ambient.x + f*light.diffuse.x*n_l; - n_colour.y += light.ambient.y + f*light.diffuse.y*n_l; - n_colour.z += light.ambient.z + f*light.diffuse.z*n_l; + n_colour.x += light.ambient.x + f * light.diffuse.x * n_l; + n_colour.y += light.ambient.y + f * light.diffuse.y * n_l; + n_colour.z += light.ambient.z + f * light.diffuse.z * n_l; } - if(n_colour.x > 1) + if (n_colour.x > 1) n_colour.x = 1; - if(n_colour.y > 1) + if (n_colour.y > 1) n_colour.y = 1; - if(n_colour.z > 1) + if (n_colour.z > 1) n_colour.z = 1; - - n_colour.multiply((colour >>> 24)/255D, (colour >> 16 & 0xFF)/255D, (colour >> 8 & 0xFF)/255D); - return (int)(n_colour.x*255)<<24 | (int)(n_colour.y*255)<<16 | (int)(n_colour.z*255)<<8 | colour&0xFF; + + n_colour.multiply((colour >>> 24) / 255D, (colour >> 16 & 0xFF) / 255D, (colour >> 8 & 0xFF) / 255D); + return (int) (n_colour.x * 255) << 24 | (int) (n_colour.y * 255) << 16 | (int) (n_colour.z * 255) << 8 | colour & 0xFF; } - + @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - CCRenderState.setColour(apply((m == null || m.colours == null) ? -1 : m.colours[i], normal)); - } - - @Override - public boolean needsNormals() - { + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.normalAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); return true; } - - public PlanarLightModel reducePlanar() - { + + @Override + public void operate() { + CCRenderState.setColour(apply(CCRenderState.colour, CCRenderState.normal)); + } + + @Override + public int operationID() { + return operationIndex; + } + + public PlanarLightModel reducePlanar() { int[] colours = new int[6]; - for(int i = 0; i < 6; i++) + for (int i = 0; i < 6; i++) colours[i] = apply(-1, Rotation.axes[i]); return new PlanarLightModel(colours); } diff --git a/codechicken/lib/lighting/PlanarLightModel.java b/codechicken/lib/lighting/PlanarLightModel.java index f6f5b51..942521f 100644 --- a/codechicken/lib/lighting/PlanarLightModel.java +++ b/codechicken/lib/lighting/PlanarLightModel.java @@ -1,42 +1,35 @@ package codechicken.lib.lighting; -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.colour.Colour; import codechicken.lib.colour.ColourRGBA; -import codechicken.lib.render.CCModel; import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.IVertexModifier; -import codechicken.lib.render.UV; -import codechicken.lib.vec.Vector3; /** * Faster precomputed version of LightModel that only works for axis planar sides */ -public class PlanarLightModel implements IVertexModifier +public class PlanarLightModel implements CCRenderState.IVertexOperation { public static PlanarLightModel standardLightModel = LightModel.standardLightModel.reducePlanar(); - - public ColourRGBA[] colours; - - public PlanarLightModel(int[] colours) - { - this.colours = new ColourRGBA[6]; - for(int i = 0; i < 6; i++) - this.colours[i] = new ColourRGBA(colours[i]); + + public int[] colours; + + public PlanarLightModel(int[] colours) { + this.colours = colours; } @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - ColourRGBA light = colours[CCModel.findSide(normal)]; - int colour = (m == null || m.colours == null) ? -1 : m.colours[i]; - Colour res = new ColourRGBA(colour).multiply(light); - CCRenderState.vertexColour(res.r&0xFF, res.g&0xFF, res.b&0xFF, res.a&0xFF) ; - } - - @Override - public boolean needsNormals() - { + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); return true; } + + @Override + public void operate() { + CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colours[CCRenderState.side])); + } + + @Override + public int operationID() { + return LightModel.operationIndex; + } } diff --git a/codechicken/lib/packet/MetaPacket.java b/codechicken/lib/packet/MetaPacket.java deleted file mode 100644 index a3c2945..0000000 --- a/codechicken/lib/packet/MetaPacket.java +++ /dev/null @@ -1,91 +0,0 @@ -package codechicken.lib.packet; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -import codechicken.lib.asm.ObfMapping; - -import net.minecraft.network.packet.NetHandler; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.Packet250CustomPayload; - -/** - * A class that facilitates sending of multiple packets one after the other. - * It first sends an empty 250 packet and then it's payloads. - */ -public class MetaPacket extends Packet250CustomPayload -{ - static - { - try - { - String fieldName = new ObfMapping("net/minecraft/network/packet/Packet", "packetClassToIdMap", "Ljava/util/Map;").toRuntime().s_name; - Field field = Packet.class.getDeclaredField(fieldName); - field.setAccessible(true); - Map, Integer> packetClassToIdMap = (Map, Integer>) field.get(null); - packetClassToIdMap.put(MetaPacket.class, 250); - } - catch(Exception e) - { - throw new RuntimeException(e); - } - } - - public ArrayList packets = new ArrayList(); - - public MetaPacket(Packet... packets) - { - super("", null); - - for(Packet p : packets) - this.packets.add(p); - } - - public MetaPacket(Collection packets) - { - this.packets.addAll(packets); - } - - @Override - public void readPacketData(DataInput datain) - { - throw new IllegalStateException("Meta packets can't be read"); - } - - @Override - public void writePacketData(DataOutput dataout) { - try {//TODO: fix super IOException - //send a dummy 250 - super.writePacketData(dataout); - - for(Packet p : packets) - Packet.writePacket(p, dataout); - - //adjust sent size for Packet.writePacket - Packet.sentSize-=getPacketSize()-super.getPacketSize(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void processPacket(NetHandler nethandler) - { - for(Packet p : packets)//Memory connection - p.processPacket(nethandler); - } - - @Override - public int getPacketSize() - { - int size = 0; - for(Packet p : packets) - size+=p.getPacketSize()+1; - return size; - } -} diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index e21f5ac..5d4e531 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -1,741 +1,356 @@ package codechicken.lib.packet; -import java.io.*; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.zip.Deflater; -import java.util.zip.Inflater; import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.vec.BlockCoord; +import com.google.common.collect.Maps; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.network.*; +import cpw.mods.fml.common.network.handshake.NetworkDispatcher; +import cpw.mods.fml.common.network.internal.FMLProxyPacket; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cpw.mods.fml.common.network.FMLNetworkHandler; -import cpw.mods.fml.common.network.IConnectionHandler; -import cpw.mods.fml.common.network.IPacketHandler; -import cpw.mods.fml.common.network.ITinyPacketHandler; -import cpw.mods.fml.common.network.NetworkModHandler; -import cpw.mods.fml.common.network.NetworkRegistry; -import cpw.mods.fml.common.network.Player; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.compression.Snappy; +import io.netty.util.AttributeKey; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.NetClientHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.INetworkManager; -import net.minecraft.network.NetLoginHandler; -import net.minecraft.network.NetServerHandler; -import net.minecraft.network.packet.NetHandler; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.Packet131MapData; -import net.minecraft.network.packet.Packet1Login; -import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.network.INetHandler; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.Packet; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.network.play.INetHandlerPlayServer; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.management.PlayerInstance; +import net.minecraft.server.management.PlayerManager.PlayerInstance; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.fluids.FluidStack; +import java.util.EnumMap; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + public final class PacketCustom implements MCDataInput, MCDataOutput { - public static interface ICustomPacketHandler + public static interface ICustomPacketHandler { } - + public interface IClientPacketHandler extends ICustomPacketHandler { - public void handlePacket(PacketCustom packetCustom, NetClientHandler nethandler, Minecraft mc); + public void handlePacket(PacketCustom packetCustom, Minecraft mc, INetHandlerPlayClient handler); } - + public interface IServerPacketHandler extends ICustomPacketHandler { - public void handlePacket(PacketCustom packetCustom, NetServerHandler nethandler, EntityPlayerMP sender); + public void handlePacket(PacketCustom packetCustom, EntityPlayerMP sender, INetHandlerPlayServer handler); } - - public static class PacketAssembler + + public static AttributeKey cclHandler = new AttributeKey("ccl:handler"); + + @ChannelHandler.Sharable + public static class CustomInboundHandler extends SimpleChannelInboundHandler { - public class AssemblyEntry - { - public AssemblyEntry(Object channel, int type, int length) - { - this.channel = channel; - this.type = type; - data = new byte[length]; - } - - public void append(byte[] b, int off, int len) - { - System.arraycopy(b, off, data, pos, len); - pos+=len; - } - - public PacketCustom finished() - { - if(pos < data.length) - return null; - - return new PacketCustom(channel, type, data); - } - - Object channel; - int type; - int pos; - byte[] data; - } - - public HashMap assemblerMap = new HashMap(); - - public PacketCustom assemble(IPacketCarrier carrier, Packet packet) - { - int type = carrier.readType(packet); - if(type != 0x80) - return new PacketCustom(carrier.readChannel(packet), carrier.readType(packet), carrier.readData(packet)); - - byte[] data = carrier.readData(packet); - int asmID = readInt(data, 0); - AssemblyEntry e = assemblerMap.get(asmID); - if(e == null) - { - e = new AssemblyEntry(carrier.readChannel(packet), data[4]&0xFF, readInt(data, 5)); - assemblerMap.put(asmID, e); - return null; - } - - e.append(data, 4, data.length-4); - PacketCustom ret = e.finished(); - if(ret != null) - assemblerMap.remove(asmID); - return ret; - } - } - - private static abstract class CustomPacketHandler implements IPacketHandler - { - HashMap handlermap = new HashMap(); - - public CustomPacketHandler(String channel) - { - NetworkRegistry.instance().registerChannel(this, channel, getSide()); + public EnumMap handlers = Maps.newEnumMap(Side.class); + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + super.handlerAdded(ctx); + ctx.channel().attr(cclHandler).set(this); } @Override - public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) - { - PacketCustom packetCustom = assembler.assemble(carrier250, packet); - if(packetCustom == null) - return; - - ICustomPacketHandler handler = handlermap.get(packetCustom.getType()); - if(handler != null) - handle(handler, packetCustom, player); + protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception { + handlers.get(ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get()) + .handle(ctx.channel().attr(NetworkRegistry.NET_HANDLER).get(), + ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get(), + new PacketCustom(msg.payload())); } - - public void registerRange(int firstID, int lastID, ICustomPacketHandler handler) - { - for(int i = firstID; i <= lastID; i++) - handlermap.put(i, handler); - } - - public abstract Side getSide(); - public abstract void handle(ICustomPacketHandler handler, PacketCustom packet, Player player); } - - private static class ClientPacketHandler extends CustomPacketHandler + + private static interface CustomHandler { - public ClientPacketHandler(String channel) - { - super(channel); - NetClientHandlerHelper.register(); - } - - @Override - public Side getSide() - { - return Side.CLIENT; - } - - @Override - public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) - { - ((IClientPacketHandler)handler).handlePacket(packet, NetClientHandlerHelper.handler, Minecraft.getMinecraft()); - } + public void handle(INetHandler handler, String channel, PacketCustom packet) throws Exception; } - - private static class ServerPacketHandler extends CustomPacketHandler + + public static class ClientInboundHandler implements CustomHandler { - public ServerPacketHandler(String channel) - { - super(channel); + private IClientPacketHandler handler; + + public ClientInboundHandler(ICustomPacketHandler handler) { + this.handler = (IClientPacketHandler) handler; } @Override - public Side getSide() - { - return Side.SERVER; - } - - @Override - public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) - { - ((IServerPacketHandler)handler).handlePacket(packet, ((EntityPlayerMP)player).playerNetServerHandler, (EntityPlayerMP)player); - } - } - - private static class ServerTinyPacketHandler - { - IServerPacketHandler serverHandler; - - public ServerTinyPacketHandler(IServerPacketHandler handler) - { - serverHandler = handler; - } - - public void handle(PacketCustom packetCustom, NetHandler handler) - { - serverHandler.handlePacket(packetCustom, (NetServerHandler)handler, ((NetServerHandler)handler).playerEntity); - } - } - - private static class ClientTinyPacketHandler - { - IClientPacketHandler clientHandler; - - public ClientTinyPacketHandler(IClientPacketHandler handler) - { - clientHandler = handler; - } - - public void handle(PacketCustom packetCustom, NetHandler handler) - { - clientHandler.handlePacket(packetCustom, (NetClientHandler)handler, Minecraft.getMinecraft()); - } - } - - public static final class CustomTinyPacketHandler implements ITinyPacketHandler - { - private ClientTinyPacketHandler clientDelegate; - private ServerTinyPacketHandler serverDelegate; - - @Override - public void handle(NetHandler handler, Packet131MapData packet) - { - PacketCustom packetCustom = assembler.assemble(carrier131, packet); - if(packetCustom == null) - return; - - if(handler instanceof NetServerHandler) - serverDelegate.handle(packetCustom, handler); + public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { + if (netHandler instanceof INetHandlerPlayClient) + handler.handlePacket(packet, Minecraft.getMinecraft(), (INetHandlerPlayClient) netHandler); else - clientDelegate.handle(packetCustom, handler); + System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); + } + } + + public static class ServerInboundHandler implements CustomHandler + { + private IServerPacketHandler handler; + + public ServerInboundHandler(ICustomPacketHandler handler) { + this.handler = (IServerPacketHandler) handler; } - private void registerSidedHandler(ICustomPacketHandler handler) - { - if(handler instanceof IClientPacketHandler) - { - if(clientDelegate != null) - throw new IllegalStateException("Client handler already registered"); - - clientDelegate = new ClientTinyPacketHandler((IClientPacketHandler) handler); - } - else if(handler instanceof IServerPacketHandler) - { - if(serverDelegate != null) - throw new IllegalStateException("Server handler already registered"); - - serverDelegate = new ServerTinyPacketHandler((IServerPacketHandler) handler); - } + @Override + public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { + if (netHandler instanceof NetHandlerPlayServer) + handler.handlePacket(packet, ((NetHandlerPlayServer) netHandler).playerEntity, (INetHandlerPlayServer) netHandler); else - { - throw new IllegalStateException("Handler is not a client or server handler"); - } - } - } - - private static class NetClientHandlerHelper implements IConnectionHandler - { - private static boolean registered = false; - public static NetClientHandler handler; - - public static void register() - { - if(registered) - return; - - NetworkRegistry.instance().registerConnectionHandler(new NetClientHandlerHelper()); - registered = true; - } - - @Override - public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) - { - handler = (NetClientHandler) netClientHandler; - } - - @Override - public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) - { - handler = (NetClientHandler) netClientHandler; - } - - @Override - public void connectionClosed(INetworkManager manager) - { - } - - @Override - public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) - { - return null; - } - - @Override - public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) - { - } - - @Override - public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) - { - } - } - - public static interface IPacketCarrier - { - public int readType(Packet packet); - public byte[] readData(Packet packet); - public Object readChannel(Packet packet); - public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data); - public boolean shortCapped(); - } - - public static class Packet250Carrier implements IPacketCarrier - { - @Override - public int readType(Packet packet) - { - return ((Packet250CustomPayload)packet).data[0]&0xFF; - } - - @Override - public byte[] readData(Packet packet) - { - byte[] data = ((Packet250CustomPayload)packet).data; - return Arrays.copyOfRange(data, 1, data.length); - } - - public Object readChannel(Packet packet) - { - return ((Packet250CustomPayload)packet).channel; - } - - @Override - public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data) - { - byte[] pdata = new byte[data.length+1]; - pdata[0] = (byte) type; - System.arraycopy(data, 0, pdata, 1, data.length); - - Packet250CustomPayload payload = new Packet250CustomPayload(); - payload.channel = (String) channel; - payload.isChunkDataPacket = chunkDataPacket; - payload.data = pdata; - payload.length = payload.data.length; - return payload; - } - - public boolean shortCapped() - { - return true; - } - } - - public static class Packet131Carrier implements IPacketCarrier - { - @Override - public int readType(Packet packet) - { - return ((Packet131MapData)packet).uniqueID&0xFF; - } - - @Override - public byte[] readData(Packet packet) - { - return ((Packet131MapData)packet).itemData; - } - - public Object readChannel(Packet packet) - { - return ((Packet131MapData)packet).itemID; - } - - @Override - public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data) - { - NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(channel); - Packet131MapData payload = new Packet131MapData((short) nmh.getNetworkId(), (short) type, data); - payload.isChunkDataPacket = chunkDataPacket; - return payload; - } - - @Override - public boolean shortCapped() - { - return true; + System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); } } - public static PacketAssembler assembler = new PacketAssembler(); - public static IPacketCarrier carrier250 = new Packet250Carrier(); - public static IPacketCarrier carrier131 = new Packet131Carrier(); - - public static IPacketCarrier carrierForChannel(Object channel) + public static interface IHandshakeHandler { - if(channel instanceof String) - return carrier250; - if(FMLNetworkHandler.instance().findNetworkModHandler(channel) != null) - return carrier131; - - return null; + public void handshakeRecieved(NetHandlerPlayServer netHandler); } - - private static int assemblyID = 0; - - public static void writeInt(byte[] b, int pos, int i) + + public static class HandshakeInboundHandler extends ChannelInboundHandlerAdapter { - b[pos++] = (byte) (i>>>24); - b[pos++] = (byte) (i>>16); - b[pos++] = (byte) (i>>8); - b[pos++] = (byte) (i); + public IHandshakeHandler handler; + + public HandshakeInboundHandler(IHandshakeHandler handler) { + this.handler = handler; + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof NetworkHandshakeEstablished) { + INetHandler netHandler = ((NetworkDispatcher) ctx.channel().attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).get()).getNetHandler(); + if (netHandler instanceof NetHandlerPlayServer) + handler.handshakeRecieved((NetHandlerPlayServer) netHandler); + } else + ctx.fireUserEventTriggered(evt); + } } - - public static int readInt(byte[] b, int pos) - { - return (b[pos++]&0xFF)<<24| - (b[pos++]&0xFF)<<16| - (b[pos++]&0xFF)<<8| - b[pos++]&0xFF; + + public static String channelName(Object channelKey) { + if (channelKey instanceof String) + return (String) channelKey; + if (channelKey instanceof ModContainer) + return ((ModContainer) channelKey).getModId(); + + ModContainer mc = FMLCommonHandler.instance().findContainerFor(channelKey); + if (mc != null) + return mc.getModId(); + + throw new IllegalArgumentException("Invalid channel: " + channelKey); } - - private PacketCustom(Object channel, int type, byte[] data) - { - this.channel = channel; + + public static FMLEmbeddedChannel getOrCreateChannel(String channelName, Side side) { + if (!NetworkRegistry.INSTANCE.hasChannel(channelName, side)) + NetworkRegistry.INSTANCE.newChannel(channelName, new CustomInboundHandler()); + return NetworkRegistry.INSTANCE.getChannel(channelName, side); + } + + public static void assignHandler(Object channelKey, ICustomPacketHandler handler) { + String channelName = channelName(channelKey); + Side side = handler instanceof IServerPacketHandler ? Side.SERVER : Side.CLIENT; + FMLEmbeddedChannel channel = getOrCreateChannel(channelName, side); + channel.attr(cclHandler).get().handlers.put(side, side == Side.SERVER ? new ServerInboundHandler(handler) : new ClientInboundHandler(handler)); + } + + public static void assignHandshakeHandler(Object channelKey, IHandshakeHandler handler) { + FMLEmbeddedChannel channel = getOrCreateChannel(channelName(channelKey), Side.SERVER); + channel.pipeline().addLast(new HandshakeInboundHandler(handler)); + } + + private ByteBuf byteBuf; + private String channel; + private int type; + + public PacketCustom(ByteBuf payload) { + byteBuf = payload; + + type = byteBuf.readUnsignedByte(); + if (type > 0x80) + decompress(); + type &= 0x7F; + } + + public PacketCustom(Object channelKey, int type) { + if (type <= 0 || type >= 0x80) + throw new IllegalArgumentException("Packet type: " + type + " is not within required 0 < t < 0x80"); + + this.channel = channelName(channelKey); this.type = type; - if(type > 0x80) - data = decompress(data); - datain = new DataInputStream(new ByteArrayInputStream(data)); + byteBuf = Unpooled.buffer(); + byteBuf.writeByte(type); } - public PacketCustom(Object channel, int type) - { - if(type <= 0 || type >= 0x80) - throw new IllegalArgumentException("Packet type: "+type+" is not within required 0 < t < 0x80"); - - this.channel = channel; - this.type = type; - isChunkDataPacket = false; - - dataarrayout = new ByteArrayOutputStream(); - dataout = new DataOutputStream(dataarrayout); - } - - public boolean incoming() - { - return dataout == null; - } - - public int getType() - { - return type&0x7F; - } - - public PacketCustom setChunkDataPacket() - { - isChunkDataPacket = true; - return this; - } - - private byte[] decompress(byte[] cdata) - { - if((type&0x80) == 0) - return cdata; - + /** + * Decompresses the remaining ByteBuf (after type has been read) using Snappy + */ + private void decompress() { Inflater inflater = new Inflater(); - try - { - byte[] ddata = new byte[readInt(cdata, 0)]; - inflater.setInput(cdata, 4, cdata.length-4); - inflater.inflate(ddata); - return ddata; - } - catch(Exception e) - { + try { + int len = byteBuf.readInt(); + ByteBuf out = Unpooled.buffer(len); + inflater.setInput(byteBuf.array(), byteBuf.readerIndex(), byteBuf.readableBytes()); + inflater.inflate(out.array()); + out.writerIndex(len); + byteBuf = out; + } catch (Exception e) { throw new RuntimeException(e); - } - finally - { + } finally { inflater.end(); } } - - public PacketCustom compressed() - { - if(incoming()) - throw new IllegalStateException("Tried to compress an incoming packet"); - if((type&0x80) != 0) - throw new IllegalStateException("Packet already compressed"); - type|=0x80; - return this; - } - - private byte[] compress(byte[] data) - { + + /** + * Compresses the payload ByteBuf after the type byte + */ + private void do_compress() { Deflater deflater = new Deflater(); - try - { - deflater.setInput(data, 0, data.length); + try { + byteBuf.readerIndex(1); + int len = byteBuf.readableBytes(); + deflater.setInput(byteBuf.array(), byteBuf.readerIndex(), len); deflater.finish(); - byte[] cbuf = new byte[data.length]; - int clen = deflater.deflate(cbuf, 0, data.length); - if(clen == data.length || !deflater.finished())//not worth compressing, gets larger - { - type &= 0x7F; - return data; - } - - byte[] cdata = new byte[clen+4]; - writeInt(cdata, 0, data.length); - System.arraycopy(cbuf, 0, cdata, 4, clen); - type|=0x80; - return cdata; - } - catch(Exception e) - { + ByteBuf out = Unpooled.buffer(len + 5); + int clen = deflater.deflate(out.array(), 5, len); + if (clen >= len - 5 || !deflater.finished())//not worth compressing, gets larger + return; + + out.setByte(0, type | 0x80); + out.setInt(1, len); + out.writerIndex(clen + 5); + byteBuf = out; + } catch (Exception e) { throw new RuntimeException(e); - } - finally - { + } finally { deflater.end(); } } - - public Packet toPacket() - { - if(incoming()) - throw new IllegalStateException("Tried to write an incoming packet"); - - try - { - dataout.close(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - - byte[] data = dataarrayout.toByteArray(); - if(data.length > 32000 || (type&0x80) != 0) - data = compress(data); - IPacketCarrier carrier = carrierForChannel(channel); - if(data.length > 32000 && carrier.shortCapped()) - { - MetaPacket payload = new MetaPacket(); - int asmID = assemblyID++; - - byte[] hdata = new byte[9]; - writeInt(hdata, 0, asmID); - hdata[4] = (byte) type; - writeInt(hdata, 5, data.length); - payload.packets.add(carrier.write(channel, isChunkDataPacket, 0x80, hdata)); - - for(int i = 0; i < data.length; i+=32000) - { - int size = Math.min(data.length-i, 32000); - byte[] sdata = new byte[size+4]; - writeInt(sdata, 0, asmID); - System.arraycopy(data, i, sdata, 4, size); - payload.packets.add(carrier.write(channel, isChunkDataPacket, 0x80, sdata)); - } - - return payload; - } - - return carrier.write(channel, isChunkDataPacket, type, data); + public boolean incoming() { + return channel == null; } - - public PacketCustom writeBoolean(boolean b) - { - try - { - dataout.writeBoolean(b); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public int getType() { + return type & 0x7F; + } + + public ByteBuf getByteBuf() { + return byteBuf; + } + + public PacketCustom compress() { + if (incoming()) + throw new IllegalStateException("Tried to compress an incoming packet"); + if ((type & 0x80) != 0) + throw new IllegalStateException("Packet already compressed"); + type |= 0x80; return this; } - - public PacketCustom writeByte(int b) - { - try - { - dataout.writeByte(b); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeBoolean(boolean b) { + byteBuf.writeBoolean(b); return this; } - - public PacketCustom writeShort(int s) - { - try - { - dataout.writeShort(s); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeByte(int b) { + byteBuf.writeByte(b); return this; } - - public PacketCustom writeInt(int i) - { - try - { - dataout.writeInt(i); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeShort(int s) { + byteBuf.writeShort(s); return this; } - - public PacketCustom writeFloat(float f) - { - try - { - dataout.writeFloat(f); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeInt(int i) { + byteBuf.writeInt(i); return this; } - - public PacketCustom writeDouble(double d) - { - try - { - dataout.writeDouble(d); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeFloat(float f) { + byteBuf.writeFloat(f); return this; } - - public PacketCustom writeLong(long l) - { - try - { - dataout.writeLong(l); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeDouble(double d) { + byteBuf.writeDouble(d); return this; } - + + public PacketCustom writeLong(long l) { + byteBuf.writeLong(l); + return this; + } + @Override - public PacketCustom writeChar(char c) - { - try - { - dataout.writeChar(c); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + public PacketCustom writeChar(char c) { + byteBuf.writeChar(c); return this; } - - public PacketCustom writeByteArray(byte[] barray) - { - try - { - dataout.write(barray); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeVarInt(int i) { + ByteBufUtils.writeVarInt(byteBuf, i, 5); return this; } - - public PacketCustom writeCoord(int x, int y, int z) - { + + public PacketCustom writeVarShort(int s) { + ByteBufUtils.writeVarShort(byteBuf, s); + return this; + } + + public PacketCustom writeByteArray(byte[] barray) { + byteBuf.writeBytes(barray); + return this; + } + + public PacketCustom writeString(String s) { + ByteBufUtils.writeUTF8String(byteBuf, s); + return this; + } + + public PacketCustom writeCoord(int x, int y, int z) { writeInt(x); writeInt(y); writeInt(z); return this; } - - public PacketCustom writeCoord(BlockCoord coord) - { + + public PacketCustom writeCoord(BlockCoord coord) { writeInt(coord.x); writeInt(coord.y); writeInt(coord.z); return this; } - - public PacketCustom writeString(String s) - { - try - { - if(s.length() > 65535) - throw new IOException("String length: "+s.length()+"too long."); - dataout.writeShort(s.length()); - dataout.writeChars(s); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public PacketCustom writeItemStack(ItemStack stack) - { + + public PacketCustom writeItemStack(ItemStack stack) { writeItemStack(stack, false); return this; } - - public PacketCustom writeItemStack(ItemStack stack, boolean large) - { - if (stack == null) - { + + public PacketCustom writeItemStack(ItemStack stack, boolean large) { + if (stack == null) { writeShort(-1); - } - else - { - writeShort(stack.itemID); - if(large) + } else { + writeShort(Item.getIdFromItem(stack.getItem())); + if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); @@ -744,228 +359,110 @@ public final class PacketCustom implements MCDataInput, MCDataOutput } return this; } - - public PacketCustom writeNBTTagCompound(NBTTagCompound compound) - { - try - { - if (compound == null) - { - writeShort(-1); - } - else - { - byte[] bytes = CompressedStreamTools.compress(compound); - writeShort((short)bytes.length); - writeByteArray(bytes); - } - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeNBTTagCompound(NBTTagCompound compound) { + ByteBufUtils.writeTag(byteBuf, compound); return this; } - public PacketCustom writeFluidStack(FluidStack fluid) - { - if (fluid == null) - { + public PacketCustom writeFluidStack(FluidStack fluid) { + if (fluid == null) { writeShort(-1); - } - else - { + } else { writeShort(fluid.fluidID); - writeInt(fluid.amount); + writeVarInt(fluid.amount); writeNBTTagCompound(fluid.tag); } return this; } - public boolean readBoolean() - { - try - { - return datain.readBoolean(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public int readUByte() - { - return readByte() & 0xFF; - } - - public int readUShort() - { - return readShort() & 0xFFFF; - } - - public byte readByte() - { - try - { - return datain.readByte(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public short readShort() - { - try - { - return datain.readShort(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public int readInt() - { - try - { - return datain.readInt(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public float readFloat() - { - try - { - return datain.readFloat(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public double readDouble() - { - try - { - return datain.readDouble(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public long readLong() - { - try - { - return datain.readLong(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public char readChar() - { - try - { - return datain.readChar(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public BlockCoord readCoord() - { - return new BlockCoord(readInt(), readInt(), readInt()); - } - - public byte[] readByteArray(int length) - { - try - { - byte[] barray = new byte[length]; - datain.readFully(barray, 0, length); - return barray; - } - catch(IOException e) - { - throw new RuntimeException(e); - } - } - - public String readString() - { - try - { - int length = datain.readUnsignedShort(); - char[] chars = new char[length]; - for(int i = 0; i < length; i++) - chars[i] = readChar(); - - return new String(chars); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - + public boolean readBoolean() { + return byteBuf.readBoolean(); } - public ItemStack readItemStack() - { + public short readUByte() { + return byteBuf.readUnsignedByte(); + } + + public int readUShort() { + return byteBuf.readUnsignedShort(); + } + + public byte readByte() { + return byteBuf.readByte(); + } + + public short readShort() { + return byteBuf.readShort(); + } + + public int readInt() { + return byteBuf.readInt(); + } + + public float readFloat() { + return byteBuf.readFloat(); + } + + public double readDouble() { + return byteBuf.readDouble(); + } + + public long readLong() { + return byteBuf.readLong(); + } + + public char readChar() { + return byteBuf.readChar(); + } + + @Override + public int readVarShort() { + return ByteBufUtils.readVarShort(byteBuf); + } + + @Override + public int readVarInt() { + return ByteBufUtils.readVarInt(byteBuf, 5); + } + + public BlockCoord readCoord() { + return new BlockCoord(readInt(), readInt(), readInt()); + } + + public byte[] readByteArray(int length) { + byte[] barray = new byte[length]; + byteBuf.readBytes(barray, 0, length); + return barray; + } + + public String readString() { + return ByteBufUtils.readUTF8String(byteBuf); + } + + public ItemStack readItemStack() { return readItemStack(false); } - - public ItemStack readItemStack(boolean large) - { + + public ItemStack readItemStack(boolean large) { ItemStack item = null; short itemID = readShort(); - if (itemID >= 0) - { + if (itemID >= 0) { int stackSize = large ? readInt() : readByte(); short damage = readShort(); - item = new ItemStack(itemID, stackSize, damage); + item = new ItemStack(Item.getItemById(itemID), stackSize, damage); item.stackTagCompound = readNBTTagCompound(); } return item; } - - public NBTTagCompound readNBTTagCompound() - { - try - { - short len = readShort(); - - if (len < 0) - return null; - - byte[] bytes = readByteArray(len); - return CompressedStreamTools.decompress(bytes); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public NBTTagCompound readNBTTagCompound() { + return ByteBufUtils.readTag(byteBuf); } - - public FluidStack readFluidStack() - { + + public FluidStack readFluidStack() { FluidStack fluid = null; short fluidID = readShort(); @@ -975,121 +472,79 @@ public final class PacketCustom implements MCDataInput, MCDataOutput return fluid; } - private Object channel; - private int type; - private boolean isChunkDataPacket; - - private ByteArrayOutputStream dataarrayout; - private DataOutputStream dataout; - - private DataInputStream datain; - - private static HashMap clienthandlermap = new HashMap(); - private static HashMap serverhandlermap = new HashMap(); - - public static void assignHandler(String channel, int firstID, int lastID, ICustomPacketHandler IHandler) - { - Side side = IHandler instanceof IClientPacketHandler ? Side.CLIENT : Side.SERVER; - HashMap handlerMap = side.isClient() ? clienthandlermap : serverhandlermap; - CustomPacketHandler handler = handlerMap.get(channel); - - if(handler == null) - { - if(side.isClient()) - handler = new ClientPacketHandler(channel); - else - handler = new ServerPacketHandler(channel); - - handlerMap.put(channel, handler); - } - handler.registerRange(firstID, lastID, IHandler); + public FMLProxyPacket toPacket() { + if (incoming()) + throw new IllegalStateException("Tried to write an incoming packet"); + + if (byteBuf.readableBytes() > 32000 || (type & 0x80) != 0) + do_compress(); + + //FML packet impl returns the whole of the backing array, copy used portion of array to another ByteBuf + return new FMLProxyPacket(byteBuf.copy(), channel); } - public static void assignHandler(Object mod, ICustomPacketHandler handler) - { - NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mod); - if(nmh == null || nmh.getTinyPacketHandler() == null || !(nmh.getTinyPacketHandler() instanceof CustomTinyPacketHandler)) - throw new IllegalStateException("Invalid network tiny packet handler for mod: "+mod); - - ((CustomTinyPacketHandler)nmh.getTinyPacketHandler()).registerSidedHandler(handler); - } - - public void sendToPlayer(EntityPlayer player) - { + public void sendToPlayer(EntityPlayer player) { sendToPlayer(toPacket(), player); } - - public static void sendToPlayer(Packet packet, EntityPlayer player) - { - if(player == null) + + public static void sendToPlayer(Packet packet, EntityPlayer player) { + if (player == null) sendToClients(packet); else - ((EntityPlayerMP)player).playerNetServerHandler.sendPacketToPlayer(packet); + ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet); } - - public void sendToClients() - { + + public void sendToClients() { sendToClients(toPacket()); - } - - public static void sendToClients(Packet packet) - { + } + + public static void sendToClients(Packet packet) { MinecraftServer.getServer().getConfigurationManager().sendPacketToAllPlayers(packet); } - - public void sendPacketToAllAround(double x, double y, double z, double range, int dim) - { + + public void sendPacketToAllAround(double x, double y, double z, double range, int dim) { sendToAllAround(toPacket(), x, y, z, range, dim); } - - public static void sendToAllAround(Packet packet, double x, double y, double z, double range, int dim) - { + + public static void sendToAllAround(Packet packet, double x, double y, double z, double range, int dim) { MinecraftServer.getServer().getConfigurationManager().sendToAllNear(x, y, z, range, dim, packet); } - - public void sendToDimension(int dim) - { + + public void sendToDimension(int dim) { sendToDimension(toPacket(), dim); } - - public static void sendToDimension(Packet packet, int dim) - { + + public static void sendToDimension(Packet packet, int dim) { MinecraftServer.getServer().getConfigurationManager().sendPacketToAllPlayersInDimension(packet, dim); } - public void sendToChunk(World world, int chunkX, int chunkZ) - { + public void sendToChunk(World world, int chunkX, int chunkZ) { sendToChunk(toPacket(), world, chunkX, chunkZ); } - - public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) - { - PlayerInstance p = ((WorldServer)world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); - if(p != null) + + public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) { + PlayerInstance p = ((WorldServer) world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); + if (p != null) p.sendToAllPlayersWatchingChunk(packet); } - - public void sendToOps() - { + + public void sendToOps() { sendToOps(toPacket()); } - public static void sendToOps(Packet packet) - { - for(EntityPlayerMP player : (List)MinecraftServer.getServer().getConfigurationManager().playerEntityList) - if(MinecraftServer.getServer().getConfigurationManager().isPlayerOpped(player.username)) + public static void sendToOps(Packet packet) { + for (EntityPlayerMP player : (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) + if (MinecraftServer.getServer().getConfigurationManager().isPlayerOpped(player.getCommandSenderName())) sendToPlayer(packet, player); } - + @SideOnly(Side.CLIENT) - public void sendToServer() - { + public void sendToServer() { sendToServer(toPacket()); } @SideOnly(Side.CLIENT) - public static void sendToServer(Packet packet) - { + public static void sendToServer(Packet packet) { Minecraft.getMinecraft().getNetHandler().addToSendQueue(packet); } } diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 44bb183..3fdb45c 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -13,7 +13,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.util.EnumMovingObjectType; +import net.minecraft.util.MovingObjectPosition.MovingObjectType; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; @@ -112,7 +112,7 @@ public class RayTracer MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); if(mop != null) { - mop.typeOfHit = EnumMovingObjectType.TILE; + mop.typeOfHit = MovingObjectType.BLOCK; mop.blockX = pos.x; mop.blockY = pos.y; mop.blockZ = pos.z; @@ -125,7 +125,7 @@ public class RayTracer MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); if(mop != null) { - mop.typeOfHit = EnumMovingObjectType.ENTITY; + mop.typeOfHit = MovingObjectType.ENTITY; mop.entityHit = e; } return mop; @@ -156,7 +156,7 @@ public class RayTracer MovingObjectPosition mop = rayTraceCuboids(start, end, cuboids); if(mop != null) { - mop.typeOfHit = EnumMovingObjectType.TILE; + mop.typeOfHit = MovingObjectType.BLOCK; mop.blockX = pos.x; mop.blockY = pos.y; mop.blockZ = pos.z; @@ -174,7 +174,7 @@ public class RayTracer if(mop != null) { ExtendedMOP emop = new ExtendedMOP(mop, cuboid.data, s_dist); - emop.typeOfHit = EnumMovingObjectType.TILE; + emop.typeOfHit = MovingObjectType.BLOCK; emop.blockX = pos.x; emop.blockY = pos.y; emop.blockZ = pos.z; @@ -185,9 +185,7 @@ public class RayTracer public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) { - Block block = Block.blocksList[world.getBlockId(x, y, z)]; - if(block == null) - return null; + Block block = world.getBlock(x, y, z); Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1.0F); @@ -217,7 +215,7 @@ public class RayTracer Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1); Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); - return world.rayTraceBlocks_do_do(headVec, endVec, true, false); + return world.func_147447_a(headVec, endVec, true, false, true); } public static Vec3 getCorrectedHeadVec(EntityPlayer player) diff --git a/codechicken/lib/render/BlockRenderer.java b/codechicken/lib/render/BlockRenderer.java new file mode 100644 index 0000000..c222d2a --- /dev/null +++ b/codechicken/lib/render/BlockRenderer.java @@ -0,0 +1,126 @@ +package codechicken.lib.render; + +import codechicken.lib.lighting.LC; +import codechicken.lib.vec.Cuboid6; + +public class BlockRenderer +{ + public static class BlockFace implements CCRenderState.IVertexSource + { + public Vertex5[] verts = new Vertex5[]{new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; + public LC[] lightCoords = new LC[]{new LC(), new LC(), new LC(), new LC()}; + public boolean lcComputed = false; + public int side; + + @Override + public Vertex5[] getVertices() { + return verts; + } + + @Override + public T getAttributes(CCRenderState.VertexAttribute attr) { + return attr == CCRenderState.lightCoordAttrib && lcComputed ? (T)lightCoords : null; + } + + @Override + public boolean hasAttribute(CCRenderState.VertexAttribute attr) { + return attr == CCRenderState.sideAttrib || attr == CCRenderState.lightCoordAttrib && lcComputed; + } + + @Override + public void prepareVertex() { + CCRenderState.side = side; + } + + public BlockFace computeLightCoords() { + if(!lcComputed) { + for (int i = 0; i < 4; i++) + lightCoords[i].compute(verts[i].vec, side); + lcComputed = true; + } + return this; + } + + public BlockFace loadCuboidFace(Cuboid6 c, int side) { + double x1 = c.min.x; + double x2 = c.max.x; + double y1 = c.min.y; + double y2 = c.max.y; + double z1 = c.min.z; + double z2 = c.max.z; + double u1; double u2; double v1; double v2; + this.side = side; + lcComputed = false; + + switch(side) { + case 0: + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + verts[0].set(x1, y1, z2, u1, v2, 0); + verts[1].set(x1, y1, z1, u1, v1, 0); + verts[2].set(x2, y1, z1, u2, v1, 0); + verts[3].set(x2, y1, z2, u2, v2, 0); + break; + case 1: + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + verts[0].set(x2, y2, z2, u2, v2, 1); + verts[1].set(x2, y2, z1, u2, v1, 1); + verts[2].set(x1, y2, z1, u1, v1, 1); + verts[3].set(x1, y2, z2, u1, v2, 1); + break; + case 2: + u1 = 1-x1; v1 = 1-y2; + u2 = 1-x2; v2 = 1-y1; + verts[0].set(x1, y1, z1, u1, v2, 2); + verts[1].set(x1, y2, z1, u1, v1, 2); + verts[2].set(x2, y2, z1, u2, v1, 2); + verts[3].set(x2, y1, z1, u2, v2, 2); + break; + case 3: + u1 = x1; v1 = 1-y2; + u2 = x2; v2 = 1-y1; + verts[0].set(x2, y1, z2, u2, v2, 3); + verts[1].set(x2, y2, z2, u2, v1, 3); + verts[2].set(x1, y2, z2, u1, v1, 3); + verts[3].set(x1, y1, z2, u1, v2, 3); + break; + case 4: + u1 = z1; v1 = 1-y2; + u2 = z2; v2 = 1-y1; + verts[0].set(x1, y1, z2, u2, v2, 4); + verts[1].set(x1, y2, z2, u2, v1, 4); + verts[2].set(x1, y2, z1, u1, v1, 4); + verts[3].set(x1, y1, z1, u1, v2, 4); + break; + case 5: + u1 = 1-z1; v1 = 1-y2; + u2 = 1-z2; v2 = 1-y1; + verts[0].set(x2, y1, z1, u1, v2, 5); + verts[1].set(x2, y2, z1, u1, v1, 5); + verts[2].set(x2, y2, z2, u2, v1, 5); + verts[3].set(x2, y1, z2, u2, v2, 5); + } + return this; + } + } + + private static BlockFace face = new BlockFace(); + + /** + * 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(Cuboid6 bounds, int sideMask) { + if(sideMask == 0x3F) + return; + + CCRenderState.setModel(face); + for(int s = 0; s < 6; s++) + if((sideMask & 1< { private static class PositionNormalEntry - { + { public Vector3 pos; public LinkedList normals = new LinkedList(); - + public PositionNormalEntry(Vector3 position) { pos = position; } - + public boolean positionEqual(Vector3 v) { return pos.x == v.x && pos.y == v.y && pos.z == v.z; } - + public PositionNormalEntry addNormal(Vector3 normal) { normals.add(normal); return this; } } - + public final int vertexMode; public final int vp; public Vertex5[] verts; - public Vector3[] normals; - public int[] colours; - + public ArrayList attributes = new ArrayList(); + protected CCModel(int vertexMode) { if(vertexMode != 7 && vertexMode != 4) throw new IllegalArgumentException("Models must be GL_QUADS or GL_TRIANGLES"); - + this.vertexMode = vertexMode; vp = vertexMode == 7 ? 4 : 3; } - + + public Vector3[] normals() { + return getAttributes(CCRenderState.normalAttrib); + } + + @Override + public Vertex5[] getVertices() { + return verts; + } + + @Override + public T getAttributes(CCRenderState.VertexAttribute attr) { + if(attr.attributeIndex < attributes.size()) + return (T) attributes.get(attr.attributeIndex); + + return null; + } + + @Override + public boolean hasAttribute(CCRenderState.VertexAttribute attrib) { + return attrib.attributeIndex < attributes.size() && attributes.get(attrib.attributeIndex) != null; + } + + @Override + public void prepareVertex() { + } + + public T getOrAllocate(CCRenderState.VertexAttribute attrib) { + T array = getAttributes(attrib); + if(array == null) { + while(attributes.size() <= attrib.attributeIndex) + attributes.add(null); + attributes.set(attrib.attributeIndex, array = attrib.newArray(verts.length)); + } + return array; + } + /** * Each pixel corresponds to one unit of position when generating the model * @param i Vertex index to start generating at @@ -87,7 +124,7 @@ public class CCModel double y2 = y1+h; double z2 = z1+d; x1 /= f; x2 /= f; y1 /= f; y2 /= f; z1 /= f; z2 /= f; - + //bottom face u1 = (tx + d + w) / tw; v1 = (ty + d) / th; u2 = (tx + d*2 + w) / tw; v2 = ty / th; @@ -95,7 +132,7 @@ public class CCModel verts[i++] = new Vertex5(x1, y1, z1, u1, v1); verts[i++] = new Vertex5(x2, y1, z1, u2, v1); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); - + //top face u1 = (tx + d) / tw; v1 = (ty + d) / th; u2 = (tx + d + w) / tw; v2 = ty / th; @@ -103,7 +140,7 @@ public class CCModel verts[i++] = new Vertex5(x2, y2, z1, u2, v1); verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y2, z2, u1, v2); - + //front face u1 = (tx + d + w) / tw; v1 = (ty + d) / th; u2 = (tx + d) / tw; v2 = (ty + d + h) / th; @@ -111,7 +148,7 @@ public class CCModel verts[i++] = new Vertex5(x2, y2, z1, u1, v1); verts[i++] = new Vertex5(x2, y1, z1, u1, v2); verts[i++] = new Vertex5(x1, y1, z1, u2, v2); - + //back face u1 = (tx + d*2 + w*2) / tw; v1 = (ty + d) / th; u2 = (tx + d*2 + w) / tw; v2 = (ty + d + h) / th; @@ -119,7 +156,7 @@ public class CCModel verts[i++] = new Vertex5(x1, y1, z2, u1, v2); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); verts[i++] = new Vertex5(x2, y2, z2, u2, v1); - + //left face u1 = (tx + d) / tw; v1 = (ty + d) / th; u2 = (tx) / tw; v2 = (ty + d + h) / th; @@ -127,7 +164,7 @@ public class CCModel verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y1, z1, u1, v2); verts[i++] = new Vertex5(x1, y1, z2, u2, v2); - + //right face u1 = (tx + d*2 + w) / tw; v1 = (ty + d) / th; u2 = (tx + d + w) / tw; v2 = (ty + d + h) / th; @@ -135,7 +172,7 @@ public class CCModel verts[i++] = new Vertex5(x2, y1, z1, u2, v2); verts[i++] = new Vertex5(x2, y2, z1, u2, v1); verts[i++] = new Vertex5(x2, y2, z2, u1, v1); - + return this; } @@ -149,7 +186,7 @@ public class CCModel { return generateBlock(i, bounds, 0); } - + public CCModel generateBlock(int i, Cuboid6 bounds, int mask) { return generateBlock(i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z, mask); @@ -175,7 +212,7 @@ public class CCModel public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2, int mask) { double u1, v1, u2, v2; - + if((mask&1) == 0) {//bottom face u1 = x1; v1 = z1; u2 = x2; v2 = z2; @@ -184,7 +221,7 @@ public class CCModel verts[i++] = new Vertex5(x2, y1, z1, u2, v1); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); } - + if((mask&2) == 0) {//top face u1 = x1+2; v1 = z1; u2 = x2+2; v2 = z2; @@ -193,7 +230,7 @@ public class CCModel verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y2, z2, u1, v2); } - + if((mask&4) == 0) {//east face u1 = 1-x1+4; v1 = 1-y2; u2 = 1-x2+4; v2 = 1-y1; @@ -202,7 +239,7 @@ public class CCModel verts[i++] = new Vertex5(x2, y2, z1, u2, v1); verts[i++] = new Vertex5(x2, y1, z1, u2, v2); } - + if((mask&8) == 0) {//west face u1 = x1+6; v1 = 1-y2; u2 = x2+6; v2 = 1-y1; @@ -211,7 +248,7 @@ public class CCModel verts[i++] = new Vertex5(x1, y2, z2, u1, v1); verts[i++] = new Vertex5(x1, y1, z2, u1, v2); } - + if((mask&0x10) == 0) {//north face u1 = z1+8; v1 = 1-y2; u2 = z2+8; v2 = 1-y1; @@ -220,7 +257,7 @@ public class CCModel verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y1, z1, u1, v2); } - + if((mask&0x20) == 0) {//south face u1 = 1-z1+10; v1 = 1-y2; u2 = 1-z2+10; v2 = 1-y1; @@ -229,10 +266,10 @@ public class CCModel verts[i++] = new Vertex5(x2, y2, z2, u2, v1); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); } - + return this; } - + public CCModel computeNormals() { return computeNormals(0, verts.length); @@ -249,10 +286,8 @@ public class CCModel { if(length%vp != 0 || start%vp != 0) throw new IllegalArgumentException("Cannot generate normals across polygons"); - - if(normals == null) - normals = new Vector3[verts.length]; - + + Vector3[] normals = getOrAllocate(CCRenderState.normalAttrib); for(int k = 0; k < length; k+=vp) { int i = k + start; @@ -262,44 +297,47 @@ public class CCModel for(int d = 1; d < vp; d++) normals[i+d] = normals[i].copy(); } - - return this; - } - - /** - * Computes lighting using the normals and the colour 0xFFFFFF. - * Per vert colouring will be added when needed. - * Make sure you have generated your normals on the model first. - * If you rotate your model after this, the lighting will no longer be valid - * @param light The light model to calculate - * @return The model - */ - public CCModel computeLighting(LightModel light) - { - if(colours == null) - setColour(-1); - for(int k = 0; k < verts.length; k++) - colours[k] = light.apply(colours[k], normals[k]); - return this; - } - - public CCModel setColour(int c) - { - if(colours == null) - colours = new int[verts.length]; - for(int k = 0; k < verts.length; k++) - colours[k] = c; + return this; } /** - * Warning, only use this if you NEED to be identical to MC's light model, it's hideous. + * 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 CCRBModel withMCLighting() + public CCModel computeLighting(LightModel light) { - return new CCRBModel(this); + Vector3[] normals = normals(); + int[] colours = getAttributes(CCRenderState.colourAttrib); + if(colours == null) { + setColour(-1); + colours = getAttributes(CCRenderState.colourAttrib); + } + for(int k = 0; k < verts.length; k++) + colours[k] = light.apply(colours[k], normals[k]); + return this; } - + + public CCModel setColour(int c) + { + 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); + Vector3[] normals = normals(); + for(int i = 0; i < verts.length; i++) + lcs[i] = new LC().compute(verts[i].vec, normals[i]); + return this; + } + /** * Averages all normals at the same position to produce a smooth lighting effect. * @return The model @@ -307,6 +345,7 @@ public class CCModel public CCModel smoothNormals() { ArrayList map = new ArrayList(); + Vector3[] normals = normals(); nextvert: for(int k = 0; k < verts.length; k++) { Vector3 vec = verts[k].vec; @@ -316,24 +355,24 @@ public class CCModel e.addNormal(normals[k]); continue nextvert; } - + map.add(new PositionNormalEntry(vec).addNormal(normals[k])); } - + for(PositionNormalEntry e : map) { if(e.normals.size() <= 1) continue; - + Vector3 new_n = new Vector3(); for(Vector3 n : e.normals) new_n.add(n); - + new_n.normalize(); for(Vector3 n : e.normals) n.set(new_n); } - + return this; } @@ -341,134 +380,93 @@ public class CCModel { for(int k = 0; k < verts.length; k++) verts[k].apply(t); - + + Vector3[] normals = normals(); if(normals != null) for(int k = 0; k < normals.length; k++) t.applyN(normals[k]); - + return this; } - public CCModel apply(IUVTransformation uvt) + public CCModel apply(UVTransformation uvt) { for(int k = 0; k < verts.length; k++) verts[k].apply(uvt); - + return this; } - + public CCModel expand(int extraVerts) { int newLen = verts.length+extraVerts; verts = Arrays.copyOf(verts, newLen); - if(normals != null) - normals = Arrays.copyOf(normals, newLen); - if(colours != null) - colours = Arrays.copyOf(colours, newLen); + for(int i = 0; i < attributes.size(); i++) + if(attributes.get(i) != null) + attributes.set(i, CCRenderState.copyOf((CCRenderState.VertexAttribute)CCRenderState.getAttribute(i), attributes.get(i), newLen)); + return this; } - + public void render() { render(0, verts.length, null, null, null); } - + public void render(double x, double y, double z, double u, double v) { - render(new Translation(new Vector3(x, y, z)), new UVTranslation(u, v)); + render(new Vector3(x, y, z).translation(), new UVTranslation(u, v)); } - public void render(double x, double y, double z, IUVTransformation u) + public void render(double x, double y, double z, UVTransformation u) { - render(new Translation(new Vector3(x, y, z)), u); + render(new Vector3(x, y, z).translation(), u); } public void render(Transformation t, double u, double v) { render(t, new UVTranslation(u, v)); } - - public void render(Transformation t, IUVTransformation u) + + public void render(CCRenderState.IVertexOperation... ops) { - render(t, u, ColourModifier.instance); - } - - public void render(Transformation t, IUVTransformation u, IVertexModifier m) - { - render(0, verts.length, t, u, m); + render(0, verts.length, ops); } /** * Renders vertices start through start+length-1 of the model - * @param start The first vertex to render - * @param length The number of vertices to render - * @param t The transformation to apply to the mat - * @param u The u texture offset - * @param v The v texture offset + * @param start The first vertex index to render + * @param end The vertex index to render until + * @param ops Operations to apply */ - public void render(int start, int length, Transformation t, IUVTransformation u, IVertexModifier m) + public void render(int start, int end, CCRenderState.IVertexOperation... ops) { - boolean drawNormal = CCRenderState.useNormals() && normals != null; - boolean computeNormal = drawNormal || m != null && m.needsNormals(); - Vector3 normal = new Vector3(); - Vertex5 vert; - Vector3 vec = new Vector3(); - UV uv = new UV(); - Tessellator tess = Tessellator.instance; - for(int k = 0; k < length; k++) - { - int i = start+k; - if(computeNormal) - { - if(t != null) - t.applyN(normal.set(normals[i])); - else - normal = normals[i]; - - if(drawNormal) - tess.setNormal((float)normal.x, (float)normal.y, (float)normal.z); - } - - vert = verts[i]; - if(t != null) - t.apply(vec.set(vert.vec)); - else - vec = vert.vec; - - if(u != null) - u.transform(uv.set(vert.uv)); - else - uv = vert.uv; - - if(m != null) - m.applyModifiers(this, tess, vec, uv, normal, i); - - tess.addVertexWithUV(vec.x, vec.y, vec.z, uv.u, uv.v); - } + CCRenderState.setPipeline(this, start, end, ops); + CCRenderState.render(); } - + public static CCModel quadModel(int numVerts) { return newModel(7, numVerts); } - + public static CCModel triModel(int numVerts) { return newModel(4, numVerts); } - + public static CCModel newModel(int vertexMode, int numVerts) { CCModel model = newModel(vertexMode); model.verts = new Vertex5[numVerts]; return model; } - + public static CCModel newModel(int vertexMode) { return new CCModel(vertexMode); } - + public static double[] parseDoubles(String s, String token) { String[] as = s.split(token); @@ -482,7 +480,7 @@ public class CCModel { if(!b) throw new IllegalArgumentException(err); } - + public static void assertMatch(Matcher m, String s) { m.reset(s); @@ -497,7 +495,7 @@ public class CCModel public static final Matcher uvwMatcher = uvwPattern.matcher(""); public static final Matcher normalMatcher = normalPattern.matcher(""); public static final Matcher polyMatcher = polyPattern.matcher(""); - + /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file * @param input An input stream to a obj file @@ -511,14 +509,14 @@ public class CCModel if(coordSystem == null) coordSystem = new RedundantTransformation(); int vp = vertexMode == 7 ? 4 : 3; - + HashMap modelMap = new HashMap(); ArrayList verts = new ArrayList(); ArrayList uvs = new ArrayList(); ArrayList normals = new ArrayList(); ArrayList polys = new ArrayList(); String modelName = "unnamed"; - + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String line; @@ -527,7 +525,7 @@ public class CCModel line = line.replaceAll("\\s+", " ").trim(); if(line.startsWith("#") || line.length() == 0) continue; - + if(line.startsWith("v ")) { assertMatch(vertMatcher, line); @@ -584,13 +582,13 @@ public class CCModel modelName = line.substring(2); } } - + if(!polys.isEmpty()) modelMap.put(modelName, createModel(verts, uvs, normals, vertexMode, polys)); - + return modelMap; } - + public static void triangulate(List polys, int[][] polyVerts) { for(int i = 2; i < polyVerts.length; i++) @@ -600,7 +598,7 @@ public class CCModel polys.add(polyVerts[i-1]); } } - + public static void quadulate(List polys, int[][] polyVerts) { if(polyVerts.length == 4) @@ -624,7 +622,7 @@ public class CCModel /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * @param s The name of the obj resource + * @param res The resource for the obj file * @return A map of group names to models */ public static Map parseObjModels(ResourceLocation res) @@ -642,7 +640,7 @@ public class CCModel try { return parseObjModels( - Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), 4, coordSystem); } catch(IOException e) @@ -650,10 +648,10 @@ public class CCModel throw new RuntimeException("failed to load model: "+res, e); } } - + /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * @param s The name of the obj resource + * @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 * @return A map of group names to models @@ -663,7 +661,7 @@ public class CCModel try { return parseObjModels( - Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), vertexMode, coordSystem); } catch(Exception e) @@ -677,12 +675,12 @@ public class CCModel int vp = vertexMode == 7 ? 4 : 3; if(polys.size() < vp || polys.size()%vp != 0) throw new IllegalArgumentException("Invalid number of vertices for model: "+polys.size()); - + boolean hasNormals = polys.get(0)[2] > 0; CCModel model = CCModel.newModel(vertexMode, polys.size()); if(hasNormals) - model.normals = new Vector3[polys.size()]; - + model.getOrAllocate(CCRenderState.normalAttrib); + for(int i = 0; i < polys.size(); i++) { int[] ai = polys.get(i); @@ -690,12 +688,12 @@ public class CCModel Vector3 uv = ai[1] <= 0 ? new Vector3() : uvs.get(ai[1]-1).copy(); if(ai[2] > 0 != hasNormals) throw new IllegalArgumentException("Normals are an all or nothing deal here."); - + model.verts[i] = new Vertex5(vert, uv.x, uv.y); if(hasNormals) - model.normals[i] = normals.get(ai[2]-1).copy(); + model.normals()[i] = normals.get(ai[2]-1).copy(); } - + return model; } @@ -726,7 +724,7 @@ public class CCModel int vStart = verts.size(); int uStart = uvs.size(); int nStart = normals.size(); - boolean hasNormals = m.normals != null; + boolean hasNormals = m.normals() != null; polys.clear(); for(int i = 0; i < m.verts.length; i++) { @@ -734,7 +732,7 @@ public class CCModel ia[0] = addIndex(verts, m.verts[i].vec); ia[1] = addIndex(uvs, m.verts[i].uv); if(hasNormals) - ia[2] = addIndex(normals, m.normals[i]); + ia[2] = addIndex(normals, m.normals()[i]); polys.add(ia); } @@ -788,7 +786,7 @@ public class CCModel { uv.add(verts[k+i].uv); } - uv.mul(1D/vp); + uv.multiply(1D/vp); for(int i = 0; i < vp; i++) { Vertex5 vert = verts[k+i]; @@ -798,7 +796,7 @@ public class CCModel } return this; } - + /** * @param side1 The side of this model * @param side2 The side of the new model @@ -811,30 +809,18 @@ public class CCModel copy(this, 0, model, 0, model.verts.length); return model.apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point)); } - + /** * Copies length vertices and normals */ - public static void copy(CCModel src, int srcpos, CCModel dest, int destpos, int length) + public static void copy(CCModel src, int srcpos, CCModel dst, int destpos, int length) { for(int k = 0; k < length; k++) - dest.verts[destpos+k] = src.verts[srcpos+k].copy(); - - if(src.normals != null) - { - if(dest.normals == null) - dest.normals = new Vector3[dest.verts.length]; + dst.verts[destpos+k] = src.verts[srcpos+k].copy(); - for(int k = 0; k < length; k++) - dest.normals[destpos+k] = src.normals[srcpos+k].copy(); - } - - if(src.colours != null) - { - if(dest.colours == null) - dest.colours = new int[dest.verts.length]; - System.arraycopy(src.colours, srcpos, dest.colours, destpos, length); - } + for(int i = 0; i < src.attributes.size(); i++) + if(src.attributes.get(i) != null) + CCRenderState.arrayCopy(src.attributes.get(i), srcpos, dst.getOrAllocate(CCRenderState.getAttribute(i)), destpos, length); } /** @@ -849,11 +835,11 @@ public class CCModel { if(s == side) continue; - + models[s] = models[side].sidedCopy(side, s, point); } } - + /** * Generate models rotated to the other 3 horizontal of the block * @param models An array of 4 models @@ -870,12 +856,12 @@ public class CCModel models[s] = models[side].sidedCopy(side, s, point); } } - + public CCModel backfacedCopy() { return generateBackface(this, 0, copy(), 0, verts.length); } - + /** * Generates copies of faces with clockwise vertices * @return The model @@ -885,7 +871,7 @@ public class CCModel int vp = src.vp; if(srcpos%vp != 0 || destpos%vp != 0 || length%vp != 0) throw new IllegalArgumentException("Vertices do not align with polygons"); - + int[][] o = new int[][]{{0, 0}, {1, vp-1}, {2, vp-2}, {3, vp-3}}; for(int i = 0; i < length; i++) { @@ -894,10 +880,12 @@ public class CCModel int di = destpos+b+o[d][1]; int si = srcpos+b+o[d][0]; dst.verts[di] = src.verts[si].copy(); - if(src.normals != null && src.normals[si] != null) - dst.normals[di] = src.normals[si].copy().negate(); - if(src.colours != null) - dst.colours[di] = src.colours[si]; + for(int a = 0; a < src.attributes.size(); a++) + if(src.attributes.get(a) != null) + CCRenderState.arrayCopy(src.attributes.get(a), si, dst.getOrAllocate(CCRenderState.getAttribute(a)), di, 1); + + if(dst.normals() != null && dst.normals()[di] != null) + dst.normals()[di].negate(); } return dst; } @@ -911,15 +899,15 @@ public class CCModel if(verts.length%(6*vp) != 0) throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); int length = verts.length/6; - + for(int s = 0; s < 6; s++) { if(s == side) continue; - + generateSidedPart(side, s, point, length*side, length*s, length); } - + return this; } @@ -932,7 +920,7 @@ public class CCModel if(verts.length%(4*vp) != 0) throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); int length = verts.length/4; - + for(int s = 2; s < 6; s++) { if(s == side) @@ -940,7 +928,7 @@ public class CCModel generateSidedPart(side, s, point, length*(side-2), length*(s-2), length); } - + return this; } @@ -962,13 +950,14 @@ public class CCModel verts[destpos+k] = verts[srcpos+k].copy(); verts[destpos+k].vec.apply(t); } - + + Vector3[] normals = normals(); if(normals != null) for(int k = 0; k < length; k++) { normals[destpos+k] = normals[srcpos+k].copy(); t.applyN(normals[destpos+k]); } - + return this; } @@ -976,7 +965,7 @@ public class CCModel { if(models.isEmpty()) return null; - + int numVerts = 0; int vertexMode = -1; for(CCModel model : models) @@ -985,10 +974,10 @@ public class CCModel vertexMode = model.vertexMode; if(vertexMode != model.vertexMode) throw new IllegalArgumentException("Cannot combine models with different vertex modes"); - + numVerts+=model.verts.length; } - + CCModel c_model = newModel(vertexMode, numVerts); int i = 0; for(CCModel model : models) @@ -996,7 +985,7 @@ public class CCModel copy(model, 0, c_model, i, model.verts.length); i+=model.verts.length; } - + return c_model; } @@ -1013,7 +1002,7 @@ public class CCModel copy(this, 0, model, 0, verts.length); return model; } - + /** * @return The average of all vertices, for bones. */ @@ -1025,13 +1014,13 @@ public class CCModel v.multiply(1/(double)verts.length); return v; } - + public CCModel zOffset(Cuboid6 offsets) { for(int k = 0; k < verts.length; k++) { Vertex5 vert = verts[k]; - Vector3 normal = normals[k]; + Vector3 normal = normals()[k]; switch(findSide(normal)) { case 0: @@ -1056,7 +1045,7 @@ public class CCModel } return this; } - + public static int findSide(Vector3 normal) { if(normal.y <=-0.99) return 0; diff --git a/codechicken/lib/render/CCRenderPipeline.java b/codechicken/lib/render/CCRenderPipeline.java new file mode 100644 index 0000000..d2dcaff --- /dev/null +++ b/codechicken/lib/render/CCRenderPipeline.java @@ -0,0 +1,135 @@ +package codechicken.lib.render; + +import java.util.ArrayList; + +import codechicken.lib.render.CCRenderState.IVertexOperation; +import codechicken.lib.render.CCRenderState.VertexAttribute; + +public class CCRenderPipeline +{ + public class PipelineBuilder + { + public PipelineBuilder add(IVertexOperation op) { + ops.add(op); + return this; + } + + public PipelineBuilder add(IVertexOperation... ops) { + for(int i = 0; i < ops.length; i++) + CCRenderPipeline.this.ops.add(ops[i]); + return this; + } + + public void build() { + rebuild(); + } + + public void render() { + rebuild(); + CCRenderState.render(); + } + } + + private class PipelineNode + { + public ArrayList deps = new ArrayList(); + public IVertexOperation op; + + public void add() { + if(op == null) + return; + + for(int i = 0; i < deps.size(); i++) + deps.get(i).add(); + deps.clear(); + sorted.add(op); + op = null; + } + } + + private ArrayList attribs = new ArrayList(); + private ArrayList ops = new ArrayList(); + private ArrayList nodes = new ArrayList(); + private ArrayList sorted = new ArrayList(); + private PipelineNode loading; + private PipelineBuilder builder = new PipelineBuilder(); + + public void setPipeline(IVertexOperation... ops) { + this.ops.clear(); + for(int i = 0; i < ops.length; i++) + this.ops.add(ops[i]); + rebuild(); + } + + public void reset() { + ops.clear(); + unbuild(); + } + + private void unbuild() { + for(int i = 0; i < attribs.size(); i++) + attribs.get(i).active = false; + attribs.clear(); + sorted.clear(); + } + + public void rebuild() { + if(ops.isEmpty() || CCRenderState.model == null) + return; + + //ensure enough nodes for all ops + while(nodes.size() < CCRenderState.operationCount()) + nodes.add(new PipelineNode()); + unbuild(); + + if(CCRenderState.useNormals) + addAttribute(CCRenderState.normalAttrib); + if(CCRenderState.baseColour != -1 || CCRenderState.alphaOverride >= 0) + addAttribute(CCRenderState.colourAttrib); + else if(CCRenderState.hasColour) + CCRenderState.setColour(-1); + + for(int i = 0; i < ops.size(); i++) { + IVertexOperation op = ops.get(i); + loading = nodes.get(op.operationID()); + boolean loaded = op.load(); + if(loaded) + loading.op = op; + + if(op instanceof VertexAttribute) + if(loaded) + attribs.add((VertexAttribute)op); + else + ((VertexAttribute)op).active = false; + } + + for(int i = 0; i < nodes.size(); i++) + nodes.get(i).add(); + } + + public void addRequirement(int opRef) { + loading.deps.add(nodes.get(opRef)); + } + + public void addDependency(VertexAttribute attrib) { + loading.deps.add(nodes.get(attrib.operationID())); + addAttribute(attrib); + } + + public void addAttribute(VertexAttribute attrib) { + if(!attrib.active) { + ops.add(attrib); + attrib.active = true; + } + } + + public void operate() { + for(int i = 0; i < sorted.size(); i++) + sorted.get(i).operate(); + } + + public PipelineBuilder builder() { + ops.clear(); + return builder; + } +} diff --git a/codechicken/lib/render/CCRenderState.java b/codechicken/lib/render/CCRenderState.java index 3ef7262..835cbb7 100644 --- a/codechicken/lib/render/CCRenderState.java +++ b/codechicken/lib/render/CCRenderState.java @@ -1,147 +1,383 @@ package codechicken.lib.render; import codechicken.lib.colour.ColourRGBA; -import net.minecraft.block.Block; +import codechicken.lib.lighting.LC; +import codechicken.lib.lighting.LightMatrix; +import codechicken.lib.util.Copyable; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Transformation; +import codechicken.lib.vec.Vector3; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.util.ResourceLocation; import net.minecraft.world.IBlockAccess; +import java.util.ArrayList; + +/** + * The core of the CodeChickenLib render system. + * Rendering operations are written to avoid object allocations by reusing static variables. + */ public class CCRenderState -{ - private static boolean useNormals; - private static boolean hasBrightness; - private static int brightness; - private static boolean useModelColours; - private static int colour; - private static boolean hasColour; - private static int alpha; - private static boolean alphaOverride; - - public static void useNormals(boolean b) - { - useNormals = b; - } - - public static boolean useNormals() - { - return useNormals; - } - - public static void useModelColours(boolean b) - { - useModelColours = b; +{ + private static int nextOperationIndex; + + public static int registerOperation() { + return nextOperationIndex++; } - public static boolean useModelColours() - { - return useModelColours; - } - - public static void setAlpha(int a) - { - alpha = a; - alphaOverride = true; - } - - public static void clearAlphaOverride() - { - alphaOverride = false; - } - - public static void vertexColour(int c) - { - if(alphaOverride) - setColour(c&0xFFFFFF00|alpha); - else - setColour(c); + public static int operationCount() { + return nextOperationIndex; } - public static void vertexColour(int r, int g, int b, int a) + /** + * Represents an operation to be run for each vertex that operates on and modifies the current state + */ + public static interface IVertexOperation { - if(alphaOverride) - Tessellator.instance.setColorRGBA(r, g, b, alpha); - else - Tessellator.instance.setColorRGBA(r, g, b, a); - } - - public static void setBrightness(IBlockAccess world, int x, int y, int z) - { - Block block = Block.blocksList[world.getBlockId(x, y, z)]; - setBrightness(block == null ? world.getLightBrightnessForSkyBlocks(x, y, z, 0) : block.getMixedBrightnessForBlock(world, x, y, z)); - setColour(0xFFFFFFFF); + /** + * Load any required references and add dependencies to the pipeline based on the current model (may be null) + * Return false if this operation is redundant in the pipeline with the given model + */ + public boolean load(); + + /** + * Perform the operation on the current render state + */ + public void operate(); + + /** + * Get the unique id representing this type of operation. Duplicate operation IDs within the pipeline may have unexpected results. + * ID shoulld be obtained from CCRenderState.registerOperation() and stored in a static variable + */ + public int operationID(); } - public static void setBrightness(int b) - { - hasBrightness = true; - Tessellator.instance.setBrightness(brightness = b); - } - - public static void setColourOpaque(int c) - { - setColour(c << 8 | 0xFF); - } - - //RGBA - public static void setColour(int c) - { - hasColour = true; - colour = c; - Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF); - } - - public static void changeTexture(String texture) - { - changeTexture(new ResourceLocation(texture)); - } - - public static void changeTexture(ResourceLocation texture) - { - Minecraft.getMinecraft().renderEngine.bindTexture(texture); + private static ArrayList> vertexAttributes = new ArrayList>(); + private static int registerVertexAttribute(VertexAttribute attr) { + vertexAttributes.add(attr); + return vertexAttributes.size()-1; } - public static void apply() + public static VertexAttribute getAttribute(int index) { + return vertexAttributes.get(index); + } + + /** + * 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 The array type for this attrute eg. int[], Vector3[] + */ + public static abstract class VertexAttribute implements IVertexOperation { + public final int attributeIndex = registerVertexAttribute(this); + private final int operationIndex = registerOperation(); + /** + * Set to true when the attrute is part of the pipeline. Should only be managed by CCRenderState when constructing the pipeline + */ + public boolean active = false; + + /** + * Construct a new array for storage of vertex attrutes in a model + */ + public abstract T newArray(int length); + + @Override + public int operationID() { + return operationIndex; + } + } + + public static void arrayCopy(Object src, int srcPos, Object dst, int destPos, int length) { + System.arraycopy(src, srcPos, dst, destPos, length); + if(dst instanceof Copyable[]) { + Object[] oa = (Object[])dst; + Copyable[] c = (Copyable[])dst; + for(int i = destPos; i < destPos+length; i++) + if(c[i] != null) + oa[i] = c[i].copy(); + } + } + + public static T copyOf(VertexAttribute attr, T src, int length) { + T dst = attr.newArray(length); + arrayCopy(src, 0, dst, 0, length); + return dst; + } + + public static interface IVertexSource + { + public Vertex5[] getVertices(); + + /** + * Gets an array of vertex attrutes + * @param attr The vertex attrute to get + * @param The attrute array type + * @return An array, or null if not computed + */ + public T getAttributes(VertexAttribute attr); + + /** + * @return True if the specified attrute is provided by this model, either by returning an array from getAttributes or by setting the state in prepareVertex + */ + public boolean hasAttribute(VertexAttribute attr); + + /** + * Callback to set CCRenderState for a vertex before the pipeline runs + */ + public void prepareVertex(); + } + + public static VertexAttribute normalAttrib = new VertexAttribute() { + private Vector3[] normalRef; + + @Override + public Vector3[] newArray(int length) { + return new Vector3[length]; + } + + @Override + public boolean load() { + normalRef = model.getAttributes(this); + if(model.hasAttribute(this)) + return normalRef != null; + + if(model.hasAttribute(sideAttrib)) { + pipeline.addDependency(sideAttrib); + return true; + } + throw new IllegalStateException("Normals requested but neither normal or side attrutes are provided by the model"); + } + + @Override + public void operate() { + if(normalRef != null) + setNormal(normalRef[vertexIndex]); + else + setNormal(Rotation.axes[side]); + } + }; + public static VertexAttribute colourAttrib = new VertexAttribute() { + private int[] colourRef; + + @Override + public int[] newArray(int length) { + return new int[length]; + } + + @Override + public boolean load() { + colourRef = model.getAttributes(this); + return colourRef != null || !model.hasAttribute(this); + } + + @Override + public void operate() { + if(colourRef != null) + setColour(ColourRGBA.multiply(baseColour, colourRef[vertexIndex])); + else + setColour(baseColour); + } + }; + public static VertexAttribute sideAttrib = new VertexAttribute() { + private int[] sideRef; + + @Override + public int[] newArray(int length) { + return new int[length]; + } + + @Override + public boolean load() { + sideRef = model.getAttributes(this); + if(model.hasAttribute(this)) + return sideRef != null; + + pipeline.addDependency(normalAttrib); + return true; + } + + @Override + public void operate() { + if(sideRef != null) + side = sideRef[vertexIndex]; + else + side = CCModel.findSide(normal); + } + }; + /** + * Uses the position of the lightmatrix to compute LC if not provided + */ + public static VertexAttribute lightCoordAttrib = new VertexAttribute() { + private LC[] lcRef; + private Vector3 vec = new Vector3();//for computation + private Vector3 pos = new Vector3(); + + @Override + public LC[] newArray(int length) { + return new LC[length]; + } + + @Override + public boolean load() { + lcRef = model.getAttributes(this); + if(model.hasAttribute(this)) + return lcRef != null; + + pos.set(lightMatrix.pos.x, lightMatrix.pos.y, lightMatrix.pos.z); + pipeline.addDependency(sideAttrib); + pipeline.addRequirement(Transformation.operationIndex); + return true; + } + + @Override + public void operate() { + if(lcRef != null) + lc.set(lcRef[vertexIndex]); + else + lc.compute(vec.set(vert.vec).sub(pos), side); + } + }; + + //pipeline state + public static IVertexSource model; + public static int firstVertexIndex; + public static int lastVertexIndex; + public static int vertexIndex; + public static CCRenderPipeline pipeline = new CCRenderPipeline(); + + //context + public static int baseColour; + public static int alphaOverride; + public static boolean useNormals; + public static LightMatrix lightMatrix = new LightMatrix(); + + //vertex outputs + public static Vertex5 vert = new Vertex5(); + public static boolean hasNormal; + public static Vector3 normal = new Vector3(); + public static boolean hasColour; + public static int colour; + public static boolean hasBrightness; + public static int brightness; + + //attrute storage + public static int side; + public static LC lc = new LC(); + + public static void reset() { + model = null; + pipeline.reset(); + hasNormal = hasColour = hasBrightness = false; + baseColour = alphaOverride = -1; + } + + public static void setPipeline(IVertexOperation... ops) { + pipeline.setPipeline(ops); + } + + public static void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) { + pipeline.reset(); + setModel(model, start, end); + pipeline.setPipeline(ops); + } + + public static void bindModel(IVertexSource model) { + if(CCRenderState.model != model) { + CCRenderState.model = model; + pipeline.rebuild(); + } + } + + public static void setModel(IVertexSource source) { + setModel(source, 0, source.getVertices().length); + } + + public static void setModel(IVertexSource source, int start, int end) { + bindModel(source); + firstVertexIndex = start; + lastVertexIndex = end; + } + + public static void render(IVertexOperation... ops) { + setPipeline(ops); + render(); + } + + public static void render() { + Vertex5[] verts = model.getVertices(); + for(vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) { + model.prepareVertex(); + vert.set(verts[vertexIndex]); + runPipeline(); + writeVert(); + } + } + + public static void runPipeline() { + pipeline.operate(); + } + + public static void writeVert() { + if(hasNormal) + Tessellator.instance.setNormal((float)normal.x, (float)normal.y, (float)normal.z); + if(hasColour) + Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF); if(hasBrightness) Tessellator.instance.setBrightness(brightness); - if(hasColour) - Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF); + Tessellator.instance.addVertexWithUV(vert.vec.x, vert.vec.y, vert.vec.z, vert.uv.u, vert.uv.v); } - public static void reset() - { - hasBrightness = false; - useModelColours = false; - hasColour = false; - alphaOverride = false; - useNormals = false; + public static void setNormal(double x, double y, double z) { + hasNormal = true; + normal.set(x, y, z); } - public static void startDrawing(int i) - { - Tessellator.instance.startDrawing(i); - apply(); + public static void setNormal(Vector3 n) { + hasNormal = true; + normal.set(n); } - public static void draw() - { - Tessellator.instance.draw(); + public static void setColour(int c) { + hasColour = true; + colour = c; } - public static void pullLightmap() - { + public static void setBrightness(int b) { + hasBrightness = true; + brightness = b; + } + + public static void setBrightness(IBlockAccess world, int x, int y, int z) { + setBrightness(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z)); + } + + public static void pullLightmap() { setBrightness((int)OpenGlHelper.lastBrightnessY << 16 | (int)OpenGlHelper.lastBrightnessX); } - public static void applyBrightnessTexCoords() - { - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness&0xFFFF, brightness>>>16); + public static void changeTexture(String texture) { + changeTexture(new ResourceLocation(texture)); } - public static void glColour() - { - new ColourRGBA(colour).glColour(); + public static void changeTexture(ResourceLocation texture) { + Minecraft.getMinecraft().renderEngine.bindTexture(texture); + } + + public static void startDrawing() { + startDrawing(7); + } + + private static void startDrawing(int mode) { + Tessellator.instance.startDrawing(mode); + if(hasColour) + Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF); + if(hasBrightness) + Tessellator.instance.setBrightness(brightness); + } + + public static void draw() { + Tessellator.instance.draw(); } } diff --git a/codechicken/lib/render/ColourModifier.java b/codechicken/lib/render/ColourModifier.java deleted file mode 100644 index b1808b6..0000000 --- a/codechicken/lib/render/ColourModifier.java +++ /dev/null @@ -1,22 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.vec.Vector3; - -public class ColourModifier implements IVertexModifier -{ - public static final ColourModifier instance = new ColourModifier(); - - @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - if(CCRenderState.useModelColours() && m != null && m.colours != null) - CCRenderState.vertexColour(m.colours[i]); - } - - @Override - public boolean needsNormals() - { - return false; - } -} diff --git a/codechicken/lib/render/ColourMultiplier.java b/codechicken/lib/render/ColourMultiplier.java index d672ff3..8e30758 100644 --- a/codechicken/lib/render/ColourMultiplier.java +++ b/codechicken/lib/render/ColourMultiplier.java @@ -1,34 +1,39 @@ package codechicken.lib.render; -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.colour.Colour; import codechicken.lib.colour.ColourRGBA; -import codechicken.lib.vec.Vector3; -public class ColourMultiplier implements IVertexModifier +public class ColourMultiplier implements CCRenderState.IVertexOperation { - public Colour colour; - - public ColourMultiplier(Colour colour) - { + private static ColourMultiplier instance = new ColourMultiplier(-1); + + public static ColourMultiplier instance(int colour) { + instance.colour = colour; + return instance; + } + + public static final int operationIndex = CCRenderState.registerOperation(); + public int colour; + + public ColourMultiplier(int colour) { this.colour = colour; } - - public ColourMultiplier(int colour) - { - this(new ColourRGBA(colour)); - } - + @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - if(CCRenderState.useModelColours() && m != null && m.colours != null) - CCRenderState.vertexColour(new ColourRGBA(m.colours[i]).multiply(colour).rgba()); + public boolean load() { + if(colour == -1) + return false; + + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + return true; } @Override - public boolean needsNormals() - { - return false; + public void operate() { + CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colour)); + } + + @Override + public int operationID() { + return operationIndex; } } diff --git a/codechicken/lib/render/EntityDigIconFX.java b/codechicken/lib/render/EntityDigIconFX.java index 5a8c064..e0e7571 100644 --- a/codechicken/lib/render/EntityDigIconFX.java +++ b/codechicken/lib/render/EntityDigIconFX.java @@ -5,12 +5,12 @@ import codechicken.lib.vec.Vector3; import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.world.World; public class EntityDigIconFX extends EntityFX { - public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, Icon icon) + public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) { super(world, x, y, z, dx, dy, dz); particleIcon = icon; @@ -72,7 +72,7 @@ public class EntityDigIconFX extends EntityFX par1Tessellator.addVertexWithUV(f11 + par3 * f10 - par6 * f10, f12 - par4 * f10, f13 + par5 * f10 - par7 * f10, f7, f9); } - public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, Icon icon, EffectRenderer effectRenderer) + public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon, EffectRenderer effectRenderer) { float border = 0.1F; Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2*border); @@ -99,7 +99,7 @@ public class EntityDigIconFX extends EntityFX .multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F)); } - public static void addBlockDestroyEffects(World world, Cuboid6 bounds, Icon[] icons, EffectRenderer effectRenderer) + public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons, EffectRenderer effectRenderer) { Vector3 diff = bounds.max.copy().subtract(bounds.min); Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5); diff --git a/codechicken/lib/render/IUVTransformation.java b/codechicken/lib/render/IUVTransformation.java deleted file mode 100644 index 386d583..0000000 --- a/codechicken/lib/render/IUVTransformation.java +++ /dev/null @@ -1,6 +0,0 @@ -package codechicken.lib.render; - -public interface IUVTransformation -{ - public void transform(UV texcoord); -} diff --git a/codechicken/lib/render/IVertexModifier.java b/codechicken/lib/render/IVertexModifier.java deleted file mode 100644 index 34cc286..0000000 --- a/codechicken/lib/render/IVertexModifier.java +++ /dev/null @@ -1,11 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.vec.Vector3; - -public interface IVertexModifier -{ - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i); - - public boolean needsNormals(); -} diff --git a/codechicken/lib/render/IconTransformation.java b/codechicken/lib/render/IconTransformation.java deleted file mode 100644 index 3a189c5..0000000 --- a/codechicken/lib/render/IconTransformation.java +++ /dev/null @@ -1,20 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.util.Icon; - -public class IconTransformation implements IUVTransformation -{ - public Icon icon; - - public IconTransformation(Icon icon) - { - this.icon = icon; - } - - @Override - public void transform(UV texcoord) - { - texcoord.u = icon.getInterpolatedU(texcoord.u%2*16); - texcoord.v = icon.getInterpolatedV(texcoord.v%2*16); - } -} diff --git a/codechicken/lib/render/MultiIconTransformation.java b/codechicken/lib/render/MultiIconTransformation.java deleted file mode 100644 index ea6e4e3..0000000 --- a/codechicken/lib/render/MultiIconTransformation.java +++ /dev/null @@ -1,41 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.util.Icon; - -/** - * Icon index is specified as (int)u>>1 - */ -public class MultiIconTransformation implements IUVTransformation -{ - public Icon[] icons; - - public MultiIconTransformation(Icon... icons) - { - this.icons = icons; - } - - @Override - public void transform(UV texcoord) - { - int i = (int)texcoord.u>>1; - Icon icon = icons[i%icons.length]; - texcoord.u = icon.getInterpolatedU(texcoord.u%2*16); - texcoord.v = icon.getInterpolatedV(texcoord.v%2*16); - } - - public static CCModel setIconIndex(CCModel m, int index) - { - return setIconIndex(m, 0, m.verts.length, index); - } - - public static CCModel setIconIndex(CCModel m, int start, int end, int index) - { - for(int k = start; k < end; k++) - { - UV uv = m.verts[k].uv; - uv.u = uv.u%2+index*2; - uv.v %= 2; - } - return m; - } -} diff --git a/codechicken/lib/render/PlaceholderTexture.java b/codechicken/lib/render/PlaceholderTexture.java index 34538a6..8ef54ee 100644 --- a/codechicken/lib/render/PlaceholderTexture.java +++ b/codechicken/lib/render/PlaceholderTexture.java @@ -1,7 +1,7 @@ package codechicken.lib.render; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.ResourceManager; +import net.minecraft.client.resources.IResourceManager; import net.minecraft.util.ResourceLocation; public class PlaceholderTexture extends TextureAtlasSprite @@ -12,7 +12,7 @@ public class PlaceholderTexture extends TextureAtlasSprite } @Override - public boolean load(ResourceManager manager, ResourceLocation location) + public boolean load(IResourceManager manager, ResourceLocation location) { return false; } diff --git a/codechicken/lib/render/QBImporter.java b/codechicken/lib/render/QBImporter.java index f53184c..712036b 100644 --- a/codechicken/lib/render/QBImporter.java +++ b/codechicken/lib/render/QBImporter.java @@ -1,11 +1,13 @@ package codechicken.lib.render; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVScale; import codechicken.lib.vec.*; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.texture.IconRegister; -import net.minecraft.util.Icon; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import javax.imageio.ImageIO; @@ -638,7 +640,7 @@ public class QBImporter return map.get(key).m; } - public Icon getIcon(String key, IconRegister r, String iconName) { + public IIcon getIcon(String key, IIconRegister r, String iconName) { int img = map.get(key).img; if(icons[img] != null && !iconName.equals(icons[img])) throw new IllegalArgumentException("Attempted to get a previously registered icon by a different name: "+icons[img]+", "+iconName); diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 9f0d3ad..2ee90dd 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -3,6 +3,8 @@ package codechicken.lib.render; import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVTransformation; import org.lwjgl.opengl.GL11; import codechicken.lib.vec.Cuboid6; @@ -10,7 +12,7 @@ import codechicken.lib.vec.Rectangle4i; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; @@ -48,7 +50,7 @@ public class RenderUtils entityItem.hoverStart = 0; } - public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) + public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon, double res) { renderFluidQuad(point2, vectors[0].set(point4).subtract(point1), vectors[1].set(point1).subtract(point2), icon, res); } @@ -60,7 +62,7 @@ public class RenderUtils * @param high The left side of the quad * @param res Units per icon */ - public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, Icon icon, double res) + public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) { Tessellator t = Tessellator.instance; @@ -141,7 +143,7 @@ public class RenderUtils var2.draw(); } - public static void renderFluidCuboid(Cuboid6 bound, Icon tex, double res) + public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { renderFluidQuad(//bottom new Vector3(bound.min.x, bound.min.y, bound.min.z), @@ -236,7 +238,7 @@ public class RenderUtils * @param stack The fluid stack to render * @return The icon of the fluid */ - public static Icon prepareFluidRender(FluidStack stack, int alpha) + public static IIcon prepareFluidRender(FluidStack stack, int alpha) { GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_BLEND); @@ -283,8 +285,8 @@ public class RenderUtils else bound.max.y = bound.min.y+(bound.max.y-bound.min.y)*density; - Icon tex = prepareFluidRender(stack, alpha); - CCRenderState.startDrawing(7); + IIcon tex = prepareFluidRender(stack, alpha); + CCRenderState.startDrawing(); renderFluidCuboid(bound, tex, res); CCRenderState.draw(); postFluidRender(); @@ -305,8 +307,8 @@ public class RenderUtils rect.h = height; } - Icon tex = prepareFluidRender(stack, alpha); - CCRenderState.startDrawing(7); + IIcon tex = prepareFluidRender(stack, alpha); + CCRenderState.startDrawing(); renderFluidQuad( new Vector3(rect.x, rect.y+rect.h, 0), new Vector3(rect.w,0, 0), @@ -333,9 +335,9 @@ public class RenderUtils boolean is3D = customRenderer != null && customRenderer.shouldUseRenderHelper(ENTITY, item, BLOCK_3D); boolean larger = false; - if (item.getItem() instanceof ItemBlock && RenderBlocks.renderItemIn3d(Block.blocksList[item.itemID].getRenderType())) + if (item.getItem() instanceof ItemBlock && RenderBlocks.renderItemIn3d(Block.getBlockFromItem(item.getItem()).getRenderType())) { - int renderType = Block.blocksList[item.itemID].getRenderType(); + int renderType = Block.getBlockFromItem(item.getItem()).getRenderType(); larger = !(renderType == 1 || renderType == 19 || renderType == 12 || renderType == 2); } else if(is3D) @@ -351,137 +353,9 @@ public class RenderUtils GL11.glColor4f(1, 1, 1, 1); entityItem.setEntityItemStack(item); - uniformRenderItem.doRenderItem(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, (float)(spin*9/Math.PI)); + uniformRenderItem.doRender(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, (float)(spin*9/Math.PI)); if(larger) GL11.glScaled(d1, d1, d1); } - - private static Vertex5[] face = new Vertex5[]{new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; - public static void renderBlock(Cuboid6 c, int sideMask, IFaceRenderer r) - { - double x1 = c.min.x; - double x2 = c.max.x; - double y1 = c.min.y; - double y2 = c.max.y; - double z1 = c.min.z; - double z2 = c.max.z; - double u1 = 0; - double u2 = 0; - double v1 = 0; - double v2 = 0; - - if((sideMask&1) == 0) - { - u1 = x1; v1 = z1; - u2 = x2; v2 = z2; - face[0].set(x1, y1, z2, u1, v2); - face[1].set(x1, y1, z1, u1, v1); - face[2].set(x2, y1, z1, u2, v1); - face[3].set(x2, y1, z2, u2, v2); - r.renderFace(face, c.min.y > 0 ? 6 : 0); - } - - if((sideMask&2) == 0) - { - u1 = x1+2; v1 = z1; - u2 = x2+2; v2 = z2; - face[0].set(x2, y2, z2, u2, v2); - face[1].set(x2, y2, z1, u2, v1); - face[2].set(x1, y2, z1, u1, v1); - face[3].set(x1, y2, z2, u1, v2); - r.renderFace(face, c.max.y < 1 ? 7 : 1); - } - - if((sideMask&4) == 0) - { - u1 = 1-x1+4; v1 = 1-y2; - u2 = 1-x2+4; v2 = 1-y1; - face[0].set(x1, y1, z1, u1, v2); - face[1].set(x1, y2, z1, u1, v1); - face[2].set(x2, y2, z1, u2, v1); - face[3].set(x2, y1, z1, u2, v2); - r.renderFace(face, c.min.z > 0 ? 8 : 2); - } - - if((sideMask&8) == 0) - { - u1 = x1+6; v1 = 1-y2; - u2 = x2+6; v2 = 1-y1; - face[0].set(x2, y1, z2, u2, v2); - face[1].set(x2, y2, z2, u2, v1); - face[2].set(x1, y2, z2, u1, v1); - face[3].set(x1, y1, z2, u1, v2); - r.renderFace(face, c.max.z < 1 ? 9 : 3); - } - - if((sideMask&0x10) == 0) - { - u1 = z1+8; v1 = 1-y2; - u2 = z2+8; v2 = 1-y1; - face[0].set(x1, y1, z2, u2, v2); - face[1].set(x1, y2, z2, u2, v1); - face[2].set(x1, y2, z1, u1, v1); - face[3].set(x1, y1, z1, u1, v2); - r.renderFace(face, c.min.x > 0 ? 10 : 4); - } - - if((sideMask&0x20) == 0) - { - u1 = 1-z1+10; v1 = 1-y2; - u2 = 1-z2+10; v2 = 1-y1; - face[0].set(x2, y1, z1, u1, v2); - face[1].set(x2, y2, z1, u1, v1); - face[2].set(x2, y2, z2, u2, v1); - face[3].set(x2, y1, z2, u2, v2); - r.renderFace(face, c.max.x < 1 ? 11 : 5); - } - } - - public static void renderBlock(Cuboid6 bounds, int sideMask, final Transformation t, final IUVTransformation u, final IVertexModifier m) - { - renderBlock(bounds, sideMask, new IFaceRenderer(){ - boolean drawNormal = CCRenderState.useNormals(); - boolean computeNormal = drawNormal || m != null && m.needsNormals(); - Vector3 normal = new Vector3(); - Vertex5 vert; - Vector3 vec = new Vector3(); - UV uv = new UV(); - - @Override - public void renderFace(Vertex5[] face, int side) - { - Tessellator tess = Tessellator.instance; - for(int i = 0; i < face.length; i++) - { - if(computeNormal) - { - if(t != null) - t.applyN(normal.set(Rotation.axes[side%6])); - else - normal = Rotation.axes[side%6]; - - if(drawNormal) - tess.setNormal((float)normal.x, (float)normal.y, (float)normal.z); - } - - vert = face[i]; - if(t != null) - t.apply(vec.set(vert.vec)); - else - vec = vert.vec; - - if(u != null) - u.transform(uv.set(vert.uv)); - else - uv = vert.uv; - - if(m != null) - m.applyModifiers(null, tess, vec, uv, normal, i); - - tess.addVertexWithUV(vec.x, vec.y, vec.z, uv.u, uv.v); - } - } - }); - } } diff --git a/codechicken/lib/render/SpriteSheetManager.java b/codechicken/lib/render/SpriteSheetManager.java index 0d8c28f..f8a1157 100644 --- a/codechicken/lib/render/SpriteSheetManager.java +++ b/codechicken/lib/render/SpriteSheetManager.java @@ -3,19 +3,19 @@ package codechicken.lib.render; import java.util.ArrayList; import java.util.HashMap; -import codechicken.lib.render.TextureUtils.IIconRegister; +import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; public class SpriteSheetManager { @SideOnly(Side.CLIENT) - public static class SpriteSheet implements IIconRegister + public static class SpriteSheet implements IIconSelfRegister { private int tilesX; private int tilesY; @@ -42,7 +42,7 @@ public class SpriteSheetManager setupSprite(i); } - public void registerIcons(IconRegister register) + public void registerIcons(IIconRegister register) { TextureMap textureMap = (TextureMap)register; @@ -79,9 +79,9 @@ public class SpriteSheetManager spriteHeight = texture.height/tilesY; } - public Icon getSprite(int index) + public IIcon getSprite(int index) { - Icon i = sprites[index]; + IIcon i = sprites[index]; if(i == null) throw new IllegalArgumentException("Sprite at index: "+index+" from texture file "+resource+" was not preloaded."); return i; diff --git a/codechicken/lib/render/TextureFX.java b/codechicken/lib/render/TextureFX.java index 3685226..c46ebeb 100644 --- a/codechicken/lib/render/TextureFX.java +++ b/codechicken/lib/render/TextureFX.java @@ -13,55 +13,47 @@ public class TextureFX public int tileSizeSquare = 256; public int tileSizeMask = 15; public int tileSizeSquareMask = 255; - + public boolean anaglyphEnabled; public TextureSpecial texture; - public TextureFX(int spriteIndex, SpriteSheet sheet) - { + public TextureFX(int spriteIndex, SpriteSheet sheet) { texture = sheet.bindTextureFX(spriteIndex, this); } - - public TextureFX(int size, String name) - { + + public TextureFX(int size, String name) { texture = new TextureSpecial(name).blank(size).selfRegister().addTextureFX(this); } - - public TextureFX setAtlas(int index) - { + + public TextureFX setAtlas(int index) { texture.atlasIndex = index; return this; } - public void setup() - { + public void setup() { imageData = new int[tileSizeSquare]; } - - public void onTextureDimensionsUpdate(int width, int height) - { - if(width != height) - throw new IllegalArgumentException("Non-Square textureFX not supported ("+width+":"+height+")"); - + + public void onTextureDimensionsUpdate(int width, int height) { + if (width != height) + throw new IllegalArgumentException("Non-Square textureFX not supported (" + width + ":" + height + ")"); + tileSizeBase = width; tileSizeSquare = tileSizeBase * tileSizeBase; tileSizeMask = tileSizeBase - 1; tileSizeSquareMask = tileSizeSquare - 1; setup(); } - - public void update() - { + + public void update() { anaglyphEnabled = Minecraft.getMinecraft().gameSettings.anaglyph; onTick(); } - public void onTick() - { + public void onTick() { } - - public boolean changed() - { + + public boolean changed() { return true; } } diff --git a/codechicken/lib/render/TextureSpecial.java b/codechicken/lib/render/TextureSpecial.java index d5adcdb..3fe2beb 100644 --- a/codechicken/lib/render/TextureSpecial.java +++ b/codechicken/lib/render/TextureSpecial.java @@ -1,150 +1,148 @@ package codechicken.lib.render; +import java.awt.image.BufferedImage; import java.util.ArrayList; + import codechicken.lib.render.SpriteSheetManager.SpriteSheet; -import codechicken.lib.render.TextureUtils.IIconRegister; +import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureUtil; -import net.minecraft.client.resources.ResourceManager; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; @SideOnly(Side.CLIENT) -public class TextureSpecial extends TextureAtlasSprite implements IIconRegister -{ +public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegister { //sprite sheet fields private int spriteIndex; private SpriteSheet spriteSheet; - + //textureFX fields private TextureFX textureFX; - - private int blankSize = -1; + private int blankSize = -1; private ArrayList baseTextures; - + private boolean selfRegister; public int atlasIndex; - - protected TextureSpecial(String par1) - { + + protected TextureSpecial(String par1) { super(par1); } - - public TextureSpecial addTexture(TextureDataHolder t) - { - if(baseTextures == null) + + public TextureSpecial addTexture(TextureDataHolder t) { + if (baseTextures == null) baseTextures = new ArrayList(); baseTextures.add(t); return this; } - - public TextureSpecial baseFromSheet(SpriteSheet spriteSheet, int spriteIndex) - { + + public TextureSpecial baseFromSheet(SpriteSheet spriteSheet, int spriteIndex) { this.spriteSheet = spriteSheet; this.spriteIndex = spriteIndex; return this; } - - public TextureSpecial addTextureFX(TextureFX fx) - { + + public TextureSpecial addTextureFX(TextureFX fx) { textureFX = fx; return this; } - + @Override - public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) - { + public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) { super.initSprite(sheetWidth, sheetHeight, originX, originY, rotated); - if(textureFX != null) + if (textureFX != null) textureFX.onTextureDimensionsUpdate(width, height); } - + @Override - public void updateAnimation() - { - if(textureFX != null) - { + public void updateAnimation() { + if (textureFX != null) { textureFX.update(); - if(textureFX.changed()) - TextureUtil.uploadTextureSub(textureFX.imageData, width, height, originX, originY, false, false); + if (textureFX.changed()) + TextureUtil.uploadTextureSub(0, textureFX.imageData, width, height, originX, originY, false, false, false); } } - + @Override - public boolean load(ResourceManager manager, ResourceLocation location) - { - if(baseTextures != null) - { - for(TextureDataHolder tex : baseTextures) - { - framesTextureData.add(tex.data); + public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) { + return true; + } + + public void addFrame(int[] data) { + GameSettings settings = Minecraft.getMinecraft().gameSettings; + BufferedImage[] images = new BufferedImage[settings.mipmapLevels+1]; + images[0] = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + images[0].setRGB(0, 0, width, height, data, 0, width); + + super.loadSprite(images, null, settings.anisotropicFiltering > 1); + } + + @Override + public boolean load(IResourceManager manager, ResourceLocation location) { + if (baseTextures != null) { + for (TextureDataHolder tex : baseTextures) { width = tex.width; height = tex.height; + addFrame(tex.data); } } - - if(spriteSheet != null) - { + + if (spriteSheet != null) { TextureDataHolder tex = spriteSheet.createSprite(spriteIndex); width = tex.width; height = tex.height; - framesTextureData.add(tex.data); + addFrame(tex.data); } - - if(blankSize > 0) - { + + if (blankSize > 0) { width = height = blankSize; - framesTextureData.add(new int[blankSize*blankSize]); + addFrame(new int[blankSize * blankSize]); } - - if(framesTextureData.isEmpty()) - throw new RuntimeException("No base frame for texture: "+getIconName()); - - return true; + + if (framesTextureData.isEmpty()) + throw new RuntimeException("No base frame for texture: " + getIconName()); + + return false; } - + @Override - public boolean hasAnimationMetadata() - { + public boolean hasAnimationMetadata() { return textureFX != null || super.hasAnimationMetadata(); } - + @Override - public int getFrameCount() - { - if(textureFX != null) + public int getFrameCount() { + if (textureFX != null) return 1; - + return super.getFrameCount(); } - public TextureSpecial blank(int size) - { + public TextureSpecial blank(int size) { blankSize = size; return this; } - - public TextureSpecial selfRegister() - { + + public TextureSpecial selfRegister() { selfRegister = true; TextureUtils.addIconRegistrar(this); return this; } - + @Override - public void registerIcons(IconRegister register) - { - if(selfRegister) - ((TextureMap)register).setTextureEntry(getIconName(), this); + public void registerIcons(IIconRegister register) { + if (selfRegister) + ((TextureMap) register).setTextureEntry(getIconName(), this); } - + @Override - public int atlasIndex() - { + public int atlasIndex() { return atlasIndex; } } diff --git a/codechicken/lib/render/TextureUtils.java b/codechicken/lib/render/TextureUtils.java index ce52719..8556332 100644 --- a/codechicken/lib/render/TextureUtils.java +++ b/codechicken/lib/render/TextureUtils.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import javax.imageio.ImageIO; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; @@ -15,138 +16,118 @@ import codechicken.lib.colour.ColourARGB; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.ForgeSubscribe; public class TextureUtils -{ - public static interface IIconRegister +{ + public static interface IIconSelfRegister { - public void registerIcons(IconRegister register); + public void registerIcons(IIconRegister register); + public int atlasIndex(); } - - static - { + + static { MinecraftForge.EVENT_BUS.register(new TextureUtils()); } - - private static ArrayList iconRegistrars = new ArrayList(); - - public static void addIconRegistrar(IIconRegister registrar) - { + + private static ArrayList iconRegistrars = new ArrayList(); + + public static void addIconRegistrar(IIconSelfRegister registrar) { iconRegistrars.add(registrar); } - - @ForgeSubscribe - public void textureLoad(TextureStitchEvent.Pre event) - { - for(IIconRegister reg : iconRegistrars) - if(reg.atlasIndex() == event.map.textureType) + + @SubscribeEvent + public void textureLoad(TextureStitchEvent.Pre event) { + for (IIconSelfRegister reg : iconRegistrars) + if (reg.atlasIndex() == event.map.getTextureType()) reg.registerIcons(event.map); } - + /** * @return an array of ARGB pixel data */ - public static int[] loadTextureData(ResourceLocation resource) - { + public static int[] loadTextureData(ResourceLocation resource) { return loadTexture(resource).data; } - public static Colour[] loadTextureColours(ResourceLocation resource) - { + public static Colour[] loadTextureColours(ResourceLocation resource) { int[] idata = loadTextureData(resource); Colour[] data = new Colour[idata.length]; - for(int i = 0; i < data.length; i++) + for (int i = 0; i < data.length; i++) data[i] = new ColourARGB(idata[i]); return data; } - - public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException - { + + public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException { return Minecraft.getMinecraft().getResourceManager().getResource(textureFile).getInputStream(); } - - public static BufferedImage loadBufferedImage(ResourceLocation textureFile) - { - try - { + + public static BufferedImage loadBufferedImage(ResourceLocation textureFile) { + try { return loadBufferedImage(getTextureResource(textureFile)); - } - catch(Exception e) - { - System.err.println("Failed to load texture file: "+textureFile); + } catch (Exception e) { + System.err.println("Failed to load texture file: " + textureFile); e.printStackTrace(); } return null; } - public static BufferedImage loadBufferedImage(InputStream in) throws IOException - { + public static BufferedImage loadBufferedImage(InputStream in) throws IOException { BufferedImage img = ImageIO.read(in); in.close(); return img; } - public static TextureManager engine() - { + public static TextureManager engine() { return Minecraft.getMinecraft().renderEngine; } - public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, int[] toTex, int toWidth, int toX, int toY) - { - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - { - int fp = (y+fromY)*fromWidth+x+fromX; - int tp = (y+toX)*toWidth+x+toX; + public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, int[] toTex, int toWidth, int toX, int toY) { + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { + int fp = (y + fromY) * fromWidth + x + fromX; + int tp = (y + toX) * toWidth + x + toX; toTex[tp] = fromTex[fp]; } } - public static void bindAtlas(int atlasIndex) - { + public static void bindAtlas(int atlasIndex) { engine().bindTexture(atlasIndex == 0 ? TextureMap.locationBlocksTexture : TextureMap.locationItemsTexture); } - - public static Icon getBlankIcon(int size, IconRegister iconRegister) - { - TextureMap textureMap = (TextureMap)iconRegister; - String s = "blank_"+size; - if(textureMap.getTextureExtry(s) == null) - { + + public static IIcon getBlankIcon(int size, IIconRegister iconRegister) { + TextureMap textureMap = (TextureMap) iconRegister; + String s = "blank_" + size; + if (textureMap.getTextureExtry(s) == null) { TextureSpecial icon = new TextureSpecial(s).blank(size); textureMap.setTextureEntry(s, icon); } return iconRegister.registerIcon(s); } - - public static TextureSpecial getTextureSpecial(IconRegister iconRegister, String name) - { + + public static TextureSpecial getTextureSpecial(IIconRegister iconRegister, String name) { TextureMap textureMap = (TextureMap) iconRegister; - Icon entry = textureMap.getTextureExtry(name); - if(entry != null) - throw new IllegalStateException("Texture: "+name+" is already registered"); - + IIcon entry = textureMap.getTextureExtry(name); + if (entry != null) + throw new IllegalStateException("Texture: " + name + " is already registered"); + TextureSpecial icon = new TextureSpecial(name); textureMap.setTextureEntry(name, icon); return icon; } - public static void prepareTexture(int target, int texture, int min_mag_filter, int wrap) - { + public static void prepareTexture(int target, int texture, int min_mag_filter, int wrap) { GL11.glBindTexture(target, texture); GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, min_mag_filter); GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, min_mag_filter); - switch(target) - { + switch (target) { case GL12.GL_TEXTURE_3D: GL11.glTexParameteri(target, GL12.GL_TEXTURE_WRAP_R, wrap); case GL11.GL_TEXTURE_2D: @@ -156,32 +137,28 @@ public class TextureUtils } } - public static TextureDataHolder loadTexture(ResourceLocation resource) - { + public static TextureDataHolder loadTexture(ResourceLocation resource) { BufferedImage img = loadBufferedImage(resource); - if(img == null) - throw new RuntimeException("Texture not found: "+resource); + if (img == null) + throw new RuntimeException("Texture not found: " + resource); return new TextureDataHolder(img); } /** * Uses an empty placeholder texture to tell if the map has been reloaded since the last call to refresh texture and the texture with name needs to be reacquired to be valid */ - public static boolean refreshTexture(TextureMap map, String name) - { - if(map.getTextureExtry(name) == null) - { + public static boolean refreshTexture(TextureMap map, String name) { + if (map.getTextureExtry(name) == null) { map.setTextureEntry(name, new PlaceholderTexture(name)); return true; } return false; } - public static Icon safeIcon(Icon icon) - { - if(icon == null) - icon = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); - + public static IIcon safeIcon(IIcon icon) { + if (icon == null) + icon = ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); + return icon; } } diff --git a/codechicken/lib/render/UV.java b/codechicken/lib/render/UV.java deleted file mode 100644 index 9181e5a..0000000 --- a/codechicken/lib/render/UV.java +++ /dev/null @@ -1,79 +0,0 @@ -package codechicken.lib.render; - -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - -public class UV -{ - public double u; - public double v; - - public UV() - { - } - - public UV(double u, double v) - { - this.u = u; - this.v = v; - } - - public UV(UV uv) - { - this(uv.u, uv.v); - } - - public UV set(double u, double v) - { - this.u = u; - this.v = v; - return this; - } - - public UV set(UV uv) - { - u = uv.u; - v = uv.v; - return this; - } - - public UV copy() - { - return new UV(this); - } - - public UV add(UV uv) - { - u+=uv.u; - v+=uv.v; - return this; - } - - public UV mul(double d) - { - u*=d; - v*=d; - return this; - } - - public String toString() - { - MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "UV("+new BigDecimal(u, cont)+", "+new BigDecimal(v, cont)+")"; - } - - public UV apply(IUVTransformation transform) - { - transform.transform(this); - return this; - } - - @Override - public boolean equals(Object o) { - if(!(o instanceof UV)) - return false; - UV uv = (UV)o; - return u == uv.u && v == uv.v; - } -} \ No newline at end of file diff --git a/codechicken/lib/render/UVScale.java b/codechicken/lib/render/UVScale.java deleted file mode 100644 index 3abdce0..0000000 --- a/codechicken/lib/render/UVScale.java +++ /dev/null @@ -1,25 +0,0 @@ -package codechicken.lib.render; - -public class UVScale implements IUVTransformation -{ - double su; - double sv; - - public UVScale(double scaleu, double scalev) - { - su = scaleu; - sv = scalev; - } - - public UVScale(double d) - { - this(d, d); - } - - @Override - public void transform(UV uv) - { - uv.u*=su; - uv.v*=sv; - } -} diff --git a/codechicken/lib/render/UVTranslation.java b/codechicken/lib/render/UVTranslation.java deleted file mode 100644 index ffd2565..0000000 --- a/codechicken/lib/render/UVTranslation.java +++ /dev/null @@ -1,20 +0,0 @@ -package codechicken.lib.render; - -public class UVTranslation implements IUVTransformation -{ - public double du; - public double dv; - - public UVTranslation(double u, double v) - { - du = u; - dv = v; - } - - @Override - public void transform(UV texcoord) - { - texcoord.u+=du; - texcoord.v+=dv; - } -} diff --git a/codechicken/lib/render/Vertex5.java b/codechicken/lib/render/Vertex5.java index 4c6780b..41683af 100644 --- a/codechicken/lib/render/Vertex5.java +++ b/codechicken/lib/render/Vertex5.java @@ -4,10 +4,13 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVTransformation; +import codechicken.lib.util.Copyable; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; -public class Vertex5 +public class Vertex5 implements Copyable { public Vector3 vec; public UV uv; @@ -32,7 +35,7 @@ public class Vertex5 { this(new Vector3(x, y, z), new UV(u, v)); } - + public Vertex5 set(double x, double y, double z, double u, double v) { vec.set(x, y, z); @@ -40,6 +43,19 @@ public class Vertex5 return this; } + public Vertex5 set(double x, double y, double z, double u, double v, int tex) + { + vec.set(x, y, z); + uv.set(u, v, tex); + return this; + } + + public Vertex5 set(Vertex5 vert) { + vec.set(vert.vec); + uv.set(vert.uv); + return this; + } + public Vertex5(Vertex5 vertex5) { this(vertex5.vec.copy(), vertex5.uv.copy()); @@ -62,7 +78,7 @@ public class Vertex5 return this; } - public Vertex5 apply(IUVTransformation t) + public Vertex5 apply(UVTransformation t) { uv.apply(t); return this; diff --git a/codechicken/lib/render/uv/IconTransformation.java b/codechicken/lib/render/uv/IconTransformation.java new file mode 100644 index 0000000..ff7b975 --- /dev/null +++ b/codechicken/lib/render/uv/IconTransformation.java @@ -0,0 +1,23 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.vec.IrreversibleTransformationException; +import net.minecraft.util.IIcon; + +public class IconTransformation extends UVTransformation { + public IIcon icon; + + public IconTransformation(IIcon icon) { + this.icon = icon; + } + + @Override + public void apply(UV uv) { + uv.u = icon.getInterpolatedU(uv.u * 16); + uv.v = icon.getInterpolatedV(uv.v * 16); + } + + @Override + public UVTransformation inverse() { + throw new IrreversibleTransformationException(this); + } +} diff --git a/codechicken/lib/render/uv/MultiIconTransformation.java b/codechicken/lib/render/uv/MultiIconTransformation.java new file mode 100644 index 0000000..7080f43 --- /dev/null +++ b/codechicken/lib/render/uv/MultiIconTransformation.java @@ -0,0 +1,24 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.vec.IrreversibleTransformationException; +import net.minecraft.util.IIcon; + +public class MultiIconTransformation extends UVTransformation { + public IIcon[] icons; + + public MultiIconTransformation(IIcon... icons) { + this.icons = icons; + } + + @Override + public void apply(UV uv) { + IIcon icon = icons[uv.tex % icons.length]; + uv.u = icon.getInterpolatedU(uv.u * 16); + uv.v = icon.getInterpolatedV(uv.v * 16); + } + + @Override + public UVTransformation inverse() { + throw new IrreversibleTransformationException(this); + } +} diff --git a/codechicken/lib/render/uv/UV.java b/codechicken/lib/render/uv/UV.java new file mode 100644 index 0000000..708b243 --- /dev/null +++ b/codechicken/lib/render/uv/UV.java @@ -0,0 +1,79 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.util.Copyable; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UV implements Copyable { + public double u; + public double v; + public int tex; + + public UV() { + } + + public UV(double u, double v) { + this(u, v, 0); + } + + public UV(double u, double v, int tex) { + this.u = u; + this.v = v; + this.tex = tex; + } + + public UV(UV uv) { + this(uv.u, uv.v, uv.tex); + } + + public UV set(double u, double v, int tex) { + this.u = u; + this.v = v; + this.tex = tex; + return this; + } + + public UV set(double u, double v) { + return set(u, v, tex); + } + + public UV set(UV uv) { + return set(uv.u, uv.v, uv.tex); + } + + public UV copy() { + return new UV(this); + } + + public UV add(UV uv) { + u += uv.u; + v += uv.v; + return this; + } + + public UV multiply(double d) { + u *= d; + v *= d; + return this; + } + + public String toString() { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UV(" + new BigDecimal(u, cont) + ", " + new BigDecimal(v, cont) + ")"; + } + + public UV apply(UVTransformation t) { + t.apply(this); + return this; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof UV)) + return false; + UV uv = (UV) o; + return u == uv.u && v == uv.v; + } +} \ No newline at end of file diff --git a/codechicken/lib/render/uv/UVRotation.java b/codechicken/lib/render/uv/UVRotation.java new file mode 100644 index 0000000..e57ee3f --- /dev/null +++ b/codechicken/lib/render/uv/UVRotation.java @@ -0,0 +1,53 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.math.MathHelper; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UVRotation extends UVTransformation +{ + public double angle; + + /** + * @param angle The angle to rotate counterclockwise in radians + */ + public UVRotation(double angle) { + this.angle = angle; + } + + @Override + public void apply(UV uv) { + double c = MathHelper.cos(angle); + double s = MathHelper.sin(angle); + double u2 = c*uv.u + s*uv.v; + uv.v = - s*uv.u + c*uv.v; + uv.u = u2; + } + + @Override + public UVTransformation inverse() { + return new UVRotation(-angle); + } + + @Override + public UVTransformation merge(UVTransformation next) { + if(next instanceof UVRotation) + return new UVRotation(angle+((UVRotation)next).angle); + + return null; + } + + @Override + public boolean isRedundant() { + return MathHelper.between(-1E-5, angle, 1E-5); + } + + @Override + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UVRotation(" + new BigDecimal(angle, cont) + ")"; + } +} diff --git a/codechicken/lib/render/uv/UVScale.java b/codechicken/lib/render/uv/UVScale.java new file mode 100644 index 0000000..db229ec --- /dev/null +++ b/codechicken/lib/render/uv/UVScale.java @@ -0,0 +1,36 @@ +package codechicken.lib.render.uv; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UVScale extends UVTransformation { + double su; + double sv; + + public UVScale(double scaleu, double scalev) { + su = scaleu; + sv = scalev; + } + + public UVScale(double d) { + this(d, d); + } + + @Override + public void apply(UV uv) { + uv.u *= su; + uv.v *= sv; + } + + @Override + public UVTransformation inverse() { + return new UVScale(1 / su, 1 / sv); + } + + @Override + public String toString() { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UVScale(" + new BigDecimal(su, cont) + ", " + new BigDecimal(sv, cont) + ")"; + } +} diff --git a/codechicken/lib/render/uv/UVTransformation.java b/codechicken/lib/render/uv/UVTransformation.java new file mode 100644 index 0000000..0d9afd2 --- /dev/null +++ b/codechicken/lib/render/uv/UVTransformation.java @@ -0,0 +1,37 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.ITransformation; + +/** + * Abstract supertype for any UV transformation + */ +public abstract class UVTransformation extends ITransformation implements CCRenderState.IVertexOperation +{ + public static final int operationIndex = CCRenderState.registerOperation(); + + public UVTransformation at(UV point) { + return new UVTransformationList(new UVTranslation(-point.u, -point.v), this, new UVTranslation(point.u, point.v)); + } + + public UVTransformationList with(UVTransformation t) { + return new UVTransformationList(this, t); + } + + @Override + public boolean load() { + return !isRedundant(); + } + + @Override + public void operate() { + apply(CCRenderState.vert.uv); + } + + @Override + public int operationID() { + return operationIndex; + } +} + + diff --git a/codechicken/lib/render/uv/UVTransformationList.java b/codechicken/lib/render/uv/UVTransformationList.java new file mode 100644 index 0000000..ec69ae9 --- /dev/null +++ b/codechicken/lib/render/uv/UVTransformationList.java @@ -0,0 +1,106 @@ +package codechicken.lib.render.uv; + +import java.util.ArrayList; +import java.util.Iterator; + +public class UVTransformationList extends UVTransformation +{ + private ArrayList transformations = new ArrayList(); + + public UVTransformationList(UVTransformation... transforms) + { + for(UVTransformation t : transforms) + if(t instanceof UVTransformationList) + transformations.addAll(((UVTransformationList)t).transformations); + else + transformations.add(t); + + compact(); + } + + @Override + public void apply(UV uv) + { + for(int i = 0; i < transformations.size(); i++) + transformations.get(i).apply(uv); + } + + @Override + public UVTransformationList with(UVTransformation t) + { + if(t.isRedundant()) + return this; + + if(t instanceof UVTransformationList) + transformations.addAll(((UVTransformationList)t).transformations); + else + transformations.add(t); + + compact(); + return this; + } + + public UVTransformationList prepend(UVTransformation t) + { + if(t.isRedundant()) + return this; + + if(t instanceof UVTransformationList) + transformations.addAll(0, ((UVTransformationList)t).transformations); + else + transformations.add(0, t); + + compact(); + return this; + } + + private void compact() { + ArrayList newList = new ArrayList(transformations.size()); + Iterator iterator = transformations.iterator(); + UVTransformation prev = null; + while(iterator.hasNext()) { + UVTransformation t = iterator.next(); + if(t.isRedundant()) + continue; + + if(prev != null) { + UVTransformation m = prev.merge(t); + if(m == null) + newList.add(prev); + else if(m.isRedundant()) + t = null; + else + t = m; + } + prev = t; + } + if(prev != null) + newList.add(prev); + + if(newList.size() < transformations.size()) + transformations = newList; + } + + @Override + public boolean isRedundant() { + return transformations.size() == 0; + } + + @Override + public UVTransformation inverse() + { + UVTransformationList rev = new UVTransformationList(); + for(int i = transformations.size()-1; i >= 0; i--) + rev.with(transformations.get(i).inverse()); + return rev; + } + + @Override + public String toString() + { + String s = ""; + for(UVTransformation t : transformations) + s+="\n"+t.toString(); + return s.trim(); + } +} diff --git a/codechicken/lib/render/uv/UVTranslation.java b/codechicken/lib/render/uv/UVTranslation.java new file mode 100644 index 0000000..cd87544 --- /dev/null +++ b/codechicken/lib/render/uv/UVTranslation.java @@ -0,0 +1,54 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.math.MathHelper; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UVTranslation extends UVTransformation { + public double du; + public double dv; + + public UVTranslation(double u, double v) { + du = u; + dv = v; + } + + @Override + public void apply(UV uv) { + uv.u += du; + uv.v += dv; + } + + @Override + public UVTransformation at(UV point) { + return this; + } + + @Override + public UVTransformation inverse() { + return new UVTranslation(-du, -dv); + } + + @Override + public UVTransformation merge(UVTransformation next) { + if (next instanceof UVTranslation) { + UVTranslation t = (UVTranslation)next; + return new UVTranslation(du+t.du, dv+t.dv); + } + + return null; + } + + @Override + public boolean isRedundant() { + return MathHelper.between(-1E-5, du, 1E-5) && MathHelper.between(-1E-5, dv, 1E-5); + } + + @Override + public String toString() { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UVTranslation(" + new BigDecimal(du, cont) + ", " + new BigDecimal(dv, cont) + ")"; + } +} diff --git a/codechicken/lib/util/Copyable.java b/codechicken/lib/util/Copyable.java new file mode 100644 index 0000000..2f78c39 --- /dev/null +++ b/codechicken/lib/util/Copyable.java @@ -0,0 +1,5 @@ +package codechicken.lib.util; + +public interface Copyable { + public T copy(); +} diff --git a/codechicken/lib/vec/BlockCoord.java b/codechicken/lib/vec/BlockCoord.java index 547b830..061a4cd 100644 --- a/codechicken/lib/vec/BlockCoord.java +++ b/codechicken/lib/vec/BlockCoord.java @@ -1,9 +1,10 @@ package codechicken.lib.vec; +import codechicken.lib.util.Copyable; import net.minecraft.tileentity.TileEntity; import codechicken.lib.math.MathHelper; -public class BlockCoord implements Comparable +public class BlockCoord implements Comparable, Copyable { public int x; public int y; diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java index d44d331..8101cf1 100644 --- a/codechicken/lib/vec/Cuboid6.java +++ b/codechicken/lib/vec/Cuboid6.java @@ -4,10 +4,11 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.util.Copyable; import net.minecraft.block.Block; import net.minecraft.util.AxisAlignedBB; -public class Cuboid6 +public class Cuboid6 implements Copyable { public static Cuboid6 full = new Cuboid6(0, 0, 0, 1, 1, 1); @@ -47,7 +48,23 @@ public class Cuboid6 { return new Cuboid6(this); } - + + public Cuboid6 set(Cuboid6 c) { + return set(c.min, c.max); + } + + public Cuboid6 set(Vector3 min, Vector3 max) { + this.min.set(min); + this.max.set(max); + return this; + } + + public Cuboid6 set(double minx, double miny, double minz, double maxx, double maxy, double maxz) { + min.set(minx, miny, minz); + max.set(maxx, maxy, maxz); + return this; + } + public Cuboid6 add(Vector3 vec) { min.add(vec); diff --git a/codechicken/lib/vec/CuboidCoord.java b/codechicken/lib/vec/CuboidCoord.java index 3d34116..a3c598a 100644 --- a/codechicken/lib/vec/CuboidCoord.java +++ b/codechicken/lib/vec/CuboidCoord.java @@ -1,10 +1,11 @@ package codechicken.lib.vec; +import codechicken.lib.util.Copyable; import net.minecraft.util.AxisAlignedBB; import java.util.Iterator; -public class CuboidCoord implements Iterable +public class CuboidCoord implements Iterable, Copyable { public BlockCoord min; public BlockCoord max; diff --git a/codechicken/lib/vec/ITransformation.java b/codechicken/lib/vec/ITransformation.java new file mode 100644 index 0000000..ab823f0 --- /dev/null +++ b/codechicken/lib/vec/ITransformation.java @@ -0,0 +1,49 @@ +package codechicken.lib.vec; + +/** + * Abstract supertype for any VectorN transformation + * @param The vector type + * @param The transformation type + */ +public abstract class ITransformation +{ + /** + * Applies this transformation to vec + */ + public abstract void apply(Vector vec); + + /** + * @param point The point to apply this transformation around + * @return Wraps this transformation in a translation to point and then back from point + */ + public abstract Transformation at(Vector point); + + /** + * Creates a TransformationList composed of this transformation followed by t + * If this is a TransformationList, the transformation will be appended and this returned + */ + public abstract Transformation with(Transformation t); + + /** + * Returns a simplified transformation that performs this, followed by next. If such a transformation does not exist, returns null + */ + public Transformation merge(Transformation next) { + return null; + } + + /** + * Returns true if this transformation is redundant, eg. Scale(1, 1, 1), Translation(0, 0, 0) or Rotation(0, a, b, c) + */ + public boolean isRedundant() { + return false; + } + + public abstract Transformation inverse(); + + /** + * Scala ++ operator + */ + public Transformation $plus$plus(Transformation t) { + return with(t); + } +} diff --git a/codechicken/lib/vec/IrreversibleTransformationException.java b/codechicken/lib/vec/IrreversibleTransformationException.java index c7d5c4d..015add0 100644 --- a/codechicken/lib/vec/IrreversibleTransformationException.java +++ b/codechicken/lib/vec/IrreversibleTransformationException.java @@ -3,9 +3,9 @@ package codechicken.lib.vec; @SuppressWarnings("serial") public class IrreversibleTransformationException extends RuntimeException { - public Transformation t; + public ITransformation t; - public IrreversibleTransformationException(Transformation t) + public IrreversibleTransformationException(ITransformation t) { this.t = t; } diff --git a/codechicken/lib/vec/Matrix4.java b/codechicken/lib/vec/Matrix4.java index 10afb16..1ac8a13 100644 --- a/codechicken/lib/vec/Matrix4.java +++ b/codechicken/lib/vec/Matrix4.java @@ -7,12 +7,13 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.DoubleBuffer; +import codechicken.lib.util.Copyable; import org.lwjgl.opengl.GL11; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class Matrix4 extends Transformation +public class Matrix4 extends Transformation implements Copyable { private static DoubleBuffer glBuf = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer(); diff --git a/codechicken/lib/vec/Quat.java b/codechicken/lib/vec/Quat.java index e639552..404daa6 100644 --- a/codechicken/lib/vec/Quat.java +++ b/codechicken/lib/vec/Quat.java @@ -4,14 +4,14 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import codechicken.lib.math.MathHelper; +import codechicken.lib.util.Copyable; -public class Quat +public class Quat implements Copyable { public double x; public double y; public double z; public double s; - public static final double SQRT2 = Math.sqrt(2D); public Quat() { diff --git a/codechicken/lib/vec/Rotation.java b/codechicken/lib/vec/Rotation.java index e3ee9d5..af253f2 100644 --- a/codechicken/lib/vec/Rotation.java +++ b/codechicken/lib/vec/Rotation.java @@ -139,7 +139,7 @@ public class Rotation extends Transformation { Vector3 axis = Rotation.axes[rotateSide(side^1, r)]; double d = look.scalarProject(axis); - if(max > d)//TODO wrong way round + if(d > max) { max = d; maxr = r; diff --git a/codechicken/lib/vec/Scale.java b/codechicken/lib/vec/Scale.java index ca36bf5..a6e38b1 100644 --- a/codechicken/lib/vec/Scale.java +++ b/codechicken/lib/vec/Scale.java @@ -9,72 +9,62 @@ import org.lwjgl.opengl.GL11; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class Scale extends Transformation -{ - private Vector3 factor; - - public Scale(Vector3 factor) - { +public class Scale extends Transformation { + public Vector3 factor; + + public Scale(Vector3 factor) { this.factor = factor; } - public Scale(double factor) - { + public Scale(double factor) { this(new Vector3(factor, factor, factor)); } - - public Scale(double x, double y, double z) - { + + public Scale(double x, double y, double z) { this(new Vector3(x, y, z)); } @Override - public void apply(Vector3 vec) - { + public void apply(Vector3 vec) { vec.multiply(factor); } - + @Override - public void applyN(Vector3 normal) - { + public void applyN(Vector3 normal) { } - + @Override - public void apply(Matrix4 mat) - { + public void apply(Matrix4 mat) { mat.scale(factor); } - + @Override @SideOnly(Side.CLIENT) - public void glApply() - { + public void glApply() { GL11.glScaled(factor.x, factor.y, factor.z); } - + @Override - public Transformation inverse() - { - return new Scale(1/factor.x, 1/factor.y, 1/factor.z); + public Transformation inverse() { + return new Scale(1 / factor.x, 1 / factor.y, 1 / factor.z); } - + @Override public Transformation merge(Transformation next) { - if(next instanceof Scale) + if (next instanceof Scale) return new Scale(factor.copy().multiply(((Scale) next).factor)); - + return null; } - + @Override public boolean isRedundant() { return factor.equalsT(Vector3.one); } - + @Override - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Scale("+new BigDecimal(factor.x, cont)+", "+new BigDecimal(factor.y, cont)+", "+new BigDecimal(factor.z, cont)+")"; + return "Scale(" + new BigDecimal(factor.x, cont) + ", " + new BigDecimal(factor.y, cont) + ", " + new BigDecimal(factor.z, cont) + ")"; } } diff --git a/codechicken/lib/vec/Transformation.java b/codechicken/lib/vec/Transformation.java index 5e0e12d..8b323df 100644 --- a/codechicken/lib/vec/Transformation.java +++ b/codechicken/lib/vec/Transformation.java @@ -1,72 +1,54 @@ package codechicken.lib.vec; +import codechicken.lib.render.CCRenderState; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; /** - * Interface for any 3D vector transformation + * Abstract supertype for any 3D vector transformation */ -public abstract class Transformation -{ - /** - * Applies this transformation to a position vector - * @param vec The vector to transform - */ - public abstract void apply(Vector3 vec); - +public abstract class Transformation extends ITransformation implements CCRenderState.IVertexOperation +{ + public static final int operationIndex = CCRenderState.registerOperation(); + /** * 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); - - /** - * @param point The point in OBJECT space to apply this transformation around - * @return Wraps this transformation in a translation to point and then back from point - */ - public Transformation at(Vector3 point) - { + + public Transformation at(Vector3 point) { return new TransformationList(new Translation(-point.x, -point.y, -point.z), this, point.translation()); } - - /** - * Creates a transformation list composed of this transformation followed by t - * If this is a TransformationList, the transformation will be appended and this returned - */ - public TransformationList with(Transformation t) - { + + public TransformationList with(Transformation t) { return new TransformationList(this, t); } - - /** - * Returns a simplified transformation that performs this, followed by next. If such a transformation does not exist, returns null - */ - public Transformation merge(Transformation next) - { - return null; - } - - /** - * Returns true if this transformation is redundant, eg. Scale(1, 1, 1), Translation(0, 0, 0) or Rotation(0, a, b, c) - */ - public boolean isRedundant() - { - return false; - } - + @SideOnly(Side.CLIENT) public abstract void glApply(); - public abstract Transformation inverse(); - - public TransformationList $plus$plus(Transformation t) - { - return with(t); + @Override + public boolean load() { + CCRenderState.pipeline.addRequirement(CCRenderState.normalAttrib.operationID()); + return !isRedundant(); + } + + @Override + public void operate() { + apply(CCRenderState.vert.vec); + if(CCRenderState.normalAttrib.active) + applyN(CCRenderState.normal); + } + + @Override + public int operationID() { + return operationIndex; } } diff --git a/codechicken/lib/vec/Translation.java b/codechicken/lib/vec/Translation.java index ad2776e..63c18e5 100644 --- a/codechicken/lib/vec/Translation.java +++ b/codechicken/lib/vec/Translation.java @@ -9,73 +9,63 @@ import org.lwjgl.opengl.GL11; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class Translation extends Transformation -{ - private Vector3 vec; - - public Translation(Vector3 vec) - { +public class Translation extends Transformation { + public Vector3 vec; + + public Translation(Vector3 vec) { this.vec = vec; } - public Translation(double x, double y, double z) - { + public Translation(double x, double y, double z) { this(new Vector3(x, y, z)); } @Override - public void apply(Vector3 vec) - { + public void apply(Vector3 vec) { vec.add(this.vec); } - - @Override - public void applyN(Vector3 normal) - { - } @Override - public void apply(Matrix4 mat) - { + public void applyN(Vector3 normal) { + } + + @Override + public void apply(Matrix4 mat) { mat.translate(vec); } - + @Override - public Transformation at(Vector3 point) - { + public Transformation at(Vector3 point) { return this; } - + @Override @SideOnly(Side.CLIENT) - public void glApply() - { + public void glApply() { GL11.glTranslated(vec.x, vec.y, vec.z); } - + @Override - public Transformation inverse() - { + public Transformation inverse() { return new Translation(-vec.x, -vec.y, -vec.z); } - + @Override public Transformation merge(Transformation next) { - if(next instanceof Translation) + if (next instanceof Translation) return new Translation(vec.copy().add(((Translation) next).vec)); - + return null; } - + @Override public boolean isRedundant() { return vec.equalsT(Vector3.zero); } - + @Override - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Translation("+new BigDecimal(vec.x, cont)+", "+new BigDecimal(vec.y, cont)+", "+new BigDecimal(vec.z, cont)+")"; + return "Translation(" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + new BigDecimal(vec.z, cont) + ")"; } } diff --git a/codechicken/lib/vec/Vector3.java b/codechicken/lib/vec/Vector3.java index 09d0a7f..944029b 100644 --- a/codechicken/lib/vec/Vector3.java +++ b/codechicken/lib/vec/Vector3.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.util.Copyable; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector3f; import org.lwjgl.util.vector.Vector4f; @@ -17,7 +18,7 @@ import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Vec3; -public class Vector3 +public class Vector3 implements Copyable { public static Vector3 zero = new Vector3(); public static Vector3 one = new Vector3(1, 1, 1); diff --git a/codechicken/lib/world/ChunkExtension.java b/codechicken/lib/world/ChunkExtension.java index 1315e3a..0dc3c90 100644 --- a/codechicken/lib/world/ChunkExtension.java +++ b/codechicken/lib/world/ChunkExtension.java @@ -2,11 +2,11 @@ package codechicken.lib.world; import java.util.HashSet; +import net.minecraft.network.Packet; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.packet.Packet; public abstract class ChunkExtension { @@ -42,7 +42,7 @@ public abstract class ChunkExtension public final void sendPacketToPlayers(Packet packet) { for(EntityPlayerMP player : watchedPlayers) - player.playerNetServerHandler.sendPacketToPlayer(packet); + player.playerNetServerHandler.sendPacket(packet); } public final void watchPlayer(EntityPlayerMP player) diff --git a/codechicken/lib/world/WorldExtensionManager.java b/codechicken/lib/world/WorldExtensionManager.java index 536a190..97c3d02 100644 --- a/codechicken/lib/world/WorldExtensionManager.java +++ b/codechicken/lib/world/WorldExtensionManager.java @@ -5,17 +5,16 @@ import java.util.EnumSet; import java.util.HashMap; import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.ITickHandler; -import cpw.mods.fml.common.TickType; -import cpw.mods.fml.common.registry.TickRegistry; +import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.EmptyChunk; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.ForgeSubscribe; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; @@ -26,7 +25,7 @@ public class WorldExtensionManager { public static class WorldExtensionEventHandler { - @ForgeSubscribe + @SubscribeEvent public void onChunkDataLoad(ChunkDataEvent.Load event) { if(!worldMap.containsKey(event.world)) @@ -38,7 +37,7 @@ public class WorldExtensionManager extension.loadChunkData(event.getChunk(), event.getData()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkDataSave(ChunkDataEvent.Save event) { for(WorldExtension extension : worldMap.get(event.world)) @@ -48,7 +47,7 @@ public class WorldExtensionManager removeChunk(event.world, event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { if(!worldMap.containsKey(event.world)) @@ -60,7 +59,7 @@ public class WorldExtensionManager extension.loadChunk(event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkUnLoad(ChunkEvent.Unload event) { if(event.getChunk() instanceof EmptyChunk) @@ -73,7 +72,7 @@ public class WorldExtensionManager removeChunk(event.world, event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onWorldSave(WorldEvent.Save event) { if(worldMap.containsKey(event.world)) @@ -81,14 +80,14 @@ public class WorldExtensionManager extension.save(); } - @ForgeSubscribe + @SubscribeEvent public void onWorldLoad(WorldEvent.Load event) { if(!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); } - @ForgeSubscribe + @SubscribeEvent public void onWorldUnLoad(WorldEvent.Unload event) { if(worldMap.containsKey(event.world))//because force closing unloads a world twice @@ -96,7 +95,7 @@ public class WorldExtensionManager extension.unload(); } - @ForgeSubscribe + @SubscribeEvent public void onChunkWatch(Watch event) { Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); @@ -104,82 +103,34 @@ public class WorldExtensionManager extension.watchChunk(chunk, event.player); } - @ForgeSubscribe + @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); } - } - - public static class WorldExtensionClientTickHandler implements ITickHandler - { - @Override - public void tickStart(EnumSet type, Object... tickData) + + @SubscribeEvent + @SideOnly(Side.CLIENT) + public void clientTick(TickEvent.ClientTickEvent event) { - if(type.contains(TickType.CLIENT)) - { - World world = Minecraft.getMinecraft().theWorld; - if(worldMap.containsKey(world)) + World world = Minecraft.getMinecraft().theWorld; + if (worldMap.containsKey(world)) + if (event.phase == TickEvent.Phase.START) preTick(world); - } - } - - @Override - public void tickEnd(EnumSet type, Object... tickData) - { - if(type.contains(TickType.CLIENT)) - { - World world = Minecraft.getMinecraft().theWorld; - if(worldMap.containsKey(world)) + else postTick(world); - } } - @Override - public EnumSet ticks() + @SubscribeEvent + public void clientTick(TickEvent.WorldTickEvent event) { - return EnumSet.of(TickType.CLIENT); - } - - @Override - public String getLabel() - { - return "WorldExtenstions"; - } - } - - public static class WorldExtensionServerTickHandler implements ITickHandler - { - @Override - public void tickStart(EnumSet type, Object... tickData) - { - if(type.contains(TickType.WORLD)) - { - preTick((World)tickData[0]); - } - } - - @Override - public void tickEnd(EnumSet type, Object... tickData) - { - if(type.contains(TickType.WORLD)) - { - postTick((World)tickData[0]); - } - } - - @Override - public EnumSet ticks() - { - return EnumSet.of(TickType.WORLD, TickType.CLIENT); - } - - @Override - public String getLabel() - { - return "WorldExtenstions"; + if(event.phase == TickEvent.Phase.START) + preTick(event.world); + else + postTick(event.world); } } @@ -199,11 +150,7 @@ public class WorldExtensionManager { initialised = true; MinecraftForge.EVENT_BUS.register(new WorldExtensionEventHandler()); - TickRegistry.registerTickHandler(new WorldExtensionServerTickHandler(), Side.SERVER); - if(FMLCommonHandler.instance().getSide().isClient()) - { - TickRegistry.registerTickHandler(new WorldExtensionClientTickHandler(), Side.CLIENT); - } + FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler()); } private static HashMap worldMap = new HashMap();