Initial 1.7 commit

This commit is contained in:
Chicken-Bomes committed 2014-04-07 14:02:47 +10:00
1 parent 34154fc011
commit ca675b5f31
72 files changed
+2967 -3335

No files matched your search

+104 -142
View File
@@ -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<String, MethodWriter> writers)
{
if(writers.containsKey(name))
{
public static byte[] writeMethods(String name, byte[] bytes, Multimap<String, MethodWriter> 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<String, MethodInjector> injectors)
{
if(injectors.containsKey(name))
{
public static byte[] injectMethods(String name, byte[] bytes, Multimap<String, MethodInjector> 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<AbstractInsnNode> 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<LabelNode, LabelNode> cloneLabels(InsnList insns)
{
public static Map<LabelNode, LabelNode> cloneLabels(InsnList insns) {
HashMap<LabelNode, LabelNode> labelMap = new HashMap<LabelNode, LabelNode>();
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<LabelNode, LabelNode> labelMap, InsnList insns)
{
public static InsnList cloneInsnList(Map<LabelNode, LabelNode> 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<TryCatchBlockNode> cloneTryCatchBlocks(Map<LabelNode, LabelNode> labelMap, List<TryCatchBlockNode> tcblocks)
{
public static List<TryCatchBlockNode> cloneTryCatchBlocks(Map<LabelNode, LabelNode> labelMap, List<TryCatchBlockNode> tcblocks) {
ArrayList<TryCatchBlockNode> clone = new ArrayList<TryCatchBlockNode>();
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<LocalVariableNode> cloneLocals(Map<LabelNode, LabelNode> labelMap, List<LocalVariableNode> locals)
{
public static List<LocalVariableNode> cloneLocals(Map<LabelNode, LabelNode> labelMap, List<LocalVariableNode> locals) {
ArrayList<LocalVariableNode> clone = new ArrayList<LocalVariableNode>();
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<LabelNode, LabelNode> 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<String, MethodAltercator> altercators)
{
if(altercators.containsKey(name))
{
public static byte[] alterMethods(String name, byte[] bytes, HashMultimap<String, MethodAltercator> 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<LocalVariableNode> list, String name)
{
public static int getLocal(List<LocalVariableNode> 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;
}
+2 -2
View File
@@ -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");
+143 -123
View File
@@ -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<String, String> fields = new HashMap<String, String>();
private HashMap<String, String> funcs = new HashMap<String, String>();
public ObfRemapper() {
try {
Field rawFieldMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawFieldMaps");
Field rawMethodMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawMethodMaps");
rawFieldMapsField.setAccessible(true);
rawMethodMapsField.setAccessible(true);
Map<String, Map<String, String>> rawFieldMaps = (Map<String, Map<String, String>>) rawFieldMapsField.get(FMLDeobfuscatingRemapper.INSTANCE);
Map<String, Map<String, String>> rawMethodMaps = (Map<String, Map<String, String>>) 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<String, String> map : rawFieldMaps.values())
for(Entry<String, String> entry : map.entrySet())
if(entry.getValue().startsWith("field"))
fields.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf(':')));
for(Map<String, String> map : rawMethodMaps.values())
for(Entry<String, String> 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);
}
}
+2 -1
View File
@@ -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<Colour>
{
public byte r;
public byte g;
+26 -17
View File
@@ -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;
}
}
+50 -78
View File
@@ -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};
}
+3 -1
View File
@@ -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();
+2
View File
@@ -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);
+31 -10
View File
@@ -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);
-246
View File
@@ -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++);
}
}
+1 -1
View File
@@ -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};
+223
View File
@@ -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<ITooltipLineHandler> tipLineHandlers = new ArrayList<ITooltipLineHandler>();
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<String> 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);
}
}
+7 -7
View File
@@ -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;
}
+7 -7
View File
@@ -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;
}
@@ -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()
{
}
}
+126 -147
View File
@@ -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;
}
}
+34 -34
View File
@@ -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<ItemKey>
{
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;
}
}
-110
View File
@@ -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<Language>)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;
}
}
-31
View File
@@ -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]);
}
}
+65 -35
View File
@@ -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<LC>
{
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);
}
}
@@ -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);
}
}
+63 -111
View File
@@ -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<<side) == 0)
{
public void sideSample(int side) {
if ((computed & 1 << side) == 0) {
int[] ssample = ssamplem[side];
for(int q = 0; q < 4; q++)
{
for (int q = 0; q < 4; q++) {
int[] qsample = qsamplem[q];
if(Minecraft.isAmbientOcclusionEnabled())
if (Minecraft.isAmbientOcclusionEnabled())
interp(side, q, ssample[qsample[0]], ssample[qsample[1]], ssample[qsample[2]], ssample[qsample[3]]);
else
interp(side, q, ssample[4], ssample[4], ssample[4], ssample[4]);
}
computed|=1<<side;
computed |= 1 << side;
}
}
private void sample(int i, float[] aSamples, int[] bSamples, IBlockAccess a, int x, int y, int z)
{
int bid = a.getBlockId(x, y, z);
Block b = Block.blocksList[bid];
if(b == null)
{
bSamples[i] = a.getLightBrightnessForSkyBlocks(x, y, z, 0);
aSamples[i] = 1;
}
else
{
bSamples[i] = a.getLightBrightnessForSkyBlocks(x, y, z, b.getLightValue(a, x, y, z));
aSamples[i] = b.getAmbientOcclusionLightValue(a, x, y, z);
}
}
private void interp(int s, int q, int a, int b, int c, int d)
{
private void interp(int s, int q, int a, int b, int c, int d) {
sample(a); sample(b); sample(c); sample(d);
ao[s][q] = interpAO(aSamples[a], aSamples[b], aSamples[c], aSamples[d])*sideao[s];
brightness[s][q] = interpBrightness(bSamples[a], bSamples[b], bSamples[c], bSamples[d]);
}
public static float interpAO(float a, float b, float c, float d)
{
return (a+b+c+d)/4F;
public static float interpAO(float a, float b, float c, float d) {
return (a + b + c + d) / 4F;
}
public static int interpBrightness(int a, int b, int c, int d)
{
if(a == 0)
public static int interpBrightness(int a, int b, int c, int d) {
if (a == 0)
a = d;
if(b == 0)
if (b == 0)
b = d;
if(c == 0)
if (c == 0)
c = d;
return (a+b+c+d)>>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;
}
}
+45 -48
View File
@@ -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);
}
+19 -26
View File
@@ -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;
}
}
-91
View File
@@ -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<Class<? extends Packet>, Integer> packetClassToIdMap = (Map<Class<? extends Packet>, Integer>) field.get(null);
packetClassToIdMap.put(MetaPacket.class, 250);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
public ArrayList<Packet> packets = new ArrayList<Packet>();
public MetaPacket(Packet... packets)
{
super("", null);
for(Packet p : packets)
this.packets.add(p);
}
public MetaPacket(Collection<? extends Packet> 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;
}
}
File diff suppressed because it is too large. Load diff
+7 -9
View File
@@ -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)
+126
View File
@@ -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> T getAttributes(CCRenderState.VertexAttribute<T> 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<<s) == 0) {
face.loadCuboidFace(bounds, s);
CCRenderState.render();
}
}
}
+195 -206
View File
@@ -11,59 +11,96 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import codechicken.lib.lighting.LC;
import codechicken.lib.render.uv.UV;
import codechicken.lib.render.uv.UVTransformation;
import codechicken.lib.render.uv.UVTranslation;
import codechicken.lib.util.Copyable;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.ResourceLocation;
import codechicken.lib.lighting.CCRBModel;
import codechicken.lib.lighting.LightModel;
import codechicken.lib.vec.Cuboid6;
import codechicken.lib.vec.RedundantTransformation;
import codechicken.lib.vec.Transformation;
import codechicken.lib.vec.TransformationList;
import codechicken.lib.vec.Translation;
import codechicken.lib.vec.Vector3;
import static codechicken.lib.vec.Rotation.*;
public class CCModel
public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel>
{
private static class PositionNormalEntry
{
{
public Vector3 pos;
public LinkedList<Vector3> normals = new LinkedList<Vector3>();
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<Object> attributes = new ArrayList<Object>();
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> T getAttributes(CCRenderState.VertexAttribute<T> 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> T getOrAllocate(CCRenderState.VertexAttribute<T> 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<PositionNormalEntry> map = new ArrayList<PositionNormalEntry>();
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<String, CCModel> modelMap = new HashMap<String, CCModel>();
ArrayList<Vector3> verts = new ArrayList<Vector3>();
ArrayList<Vector3> uvs = new ArrayList<Vector3>();
ArrayList<Vector3> normals = new ArrayList<Vector3>();
ArrayList<int[]> polys = new ArrayList<int[]>();
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<int[]> 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<int[]> 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<String, CCModel> 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;
@@ -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<PipelineNode> deps = new ArrayList<PipelineNode>();
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<VertexAttribute> attribs = new ArrayList<VertexAttribute>();
private ArrayList<IVertexOperation> ops = new ArrayList<IVertexOperation>();
private ArrayList<PipelineNode> nodes = new ArrayList<PipelineNode>();
private ArrayList<IVertexOperation> sorted = new ArrayList<IVertexOperation>();
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;
}
}
+346 -110
View File
@@ -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<VertexAttribute<?>> vertexAttributes = new ArrayList<VertexAttribute<?>>();
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 <T> The array type for this attrute eg. int[], Vector3[]
*/
public static abstract class VertexAttribute<T> 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<Object>[] c = (Copyable[])dst;
for(int i = destPos; i < destPos+length; i++)
if(c[i] != null)
oa[i] = c[i].copy();
}
}
public static <T> T copyOf(VertexAttribute<T> 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 <T> The attrute array type
* @return An array, or null if not computed
*/
public <T> T getAttributes(VertexAttribute<T> 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<Vector3[]> normalAttrib = new VertexAttribute<Vector3[]>() {
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<int[]> colourAttrib = new VertexAttribute<int[]>() {
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<int[]> sideAttrib = new VertexAttribute<int[]>() {
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<LC[]> lightCoordAttrib = new VertexAttribute<LC[]>() {
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();
}
}
@@ -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;
}
}
+26 -21
View File
@@ -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;
}
}
+4 -4
View File
@@ -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);
@@ -1,6 +0,0 @@
package codechicken.lib.render;
public interface IUVTransformation
{
public void transform(UV texcoord);
}
@@ -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();
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
+5 -3
View File
@@ -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);
+14 -140
View File
@@ -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);
}
}
});
}
}
@@ -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;
+17 -25
View File
@@ -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;
}
}
+73 -75
View File
@@ -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<TextureDataHolder> 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<TextureDataHolder>();
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;
}
}
+59 -82
View File
@@ -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<IIconRegister> iconRegistrars = new ArrayList<TextureUtils.IIconRegister>();
public static void addIconRegistrar(IIconRegister registrar)
{
private static ArrayList<IIconSelfRegister> iconRegistrars = new ArrayList<TextureUtils.IIconSelfRegister>();
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;
}
}
-79
View File
@@ -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;
}
}
-25
View File
@@ -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;
}
}
-20
View File
@@ -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;
}
}
+19 -3
View File
@@ -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<Vertex5>
{
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;
@@ -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);
}
}
@@ -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);
}
}
+79
View File
@@ -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<UV> {
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;
}
}
+53
View File
@@ -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) + ")";
}
}
+36
View File
@@ -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) + ")";
}
}
@@ -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<UV, UVTransformation> 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;
}
}
@@ -0,0 +1,106 @@
package codechicken.lib.render.uv;
import java.util.ArrayList;
import java.util.Iterator;
public class UVTransformationList extends UVTransformation
{
private ArrayList<UVTransformation> transformations = new ArrayList<UVTransformation>();
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<UVTransformation> newList = new ArrayList<UVTransformation>(transformations.size());
Iterator<UVTransformation> 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();
}
}
@@ -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) + ")";
}
}
+5
View File
@@ -0,0 +1,5 @@
package codechicken.lib.util;
public interface Copyable<T> {
public T copy();
}
+2 -1
View File
@@ -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<BlockCoord>
public class BlockCoord implements Comparable<BlockCoord>, Copyable<BlockCoord>
{
public int x;
public int y;
+19 -2
View File
@@ -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<Cuboid6>
{
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);
+2 -1
View File
@@ -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<BlockCoord>
public class CuboidCoord implements Iterable<BlockCoord>, Copyable<CuboidCoord>
{
public BlockCoord min;
public BlockCoord max;
+49
View File
@@ -0,0 +1,49 @@
package codechicken.lib.vec;
/**
* Abstract supertype for any VectorN transformation
* @param <Vector> The vector type
* @param <Transformation> The transformation type
*/
public abstract class ITransformation<Vector, Transformation extends 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);
}
}
@@ -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;
}
+2 -1
View File
@@ -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<Matrix4>
{
private static DoubleBuffer glBuf = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer();
+2 -2
View File
@@ -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<Quat>
{
public double x;
public double y;
public double z;
public double s;
public static final double SQRT2 = Math.sqrt(2D);
public Quat()
{
+1 -1
View File
@@ -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;
+24 -34
View File
@@ -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) + ")";
}
}
+28 -46
View File
@@ -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<Vector3, Transformation> 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;
}
}
+24 -34
View File
@@ -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) + ")";
}
}
+2 -1
View File
@@ -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<Vector3>
{
public static Vector3 zero = new Vector3();
public static Vector3 one = new Vector3(1, 1, 1);
+2 -2
View File
@@ -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)
@@ -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<TickType> 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<TickType> type, Object... tickData)
{
if(type.contains(TickType.CLIENT))
{
World world = Minecraft.getMinecraft().theWorld;
if(worldMap.containsKey(world))
else
postTick(world);
}
}
@Override
public EnumSet<TickType> 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<TickType> type, Object... tickData)
{
if(type.contains(TickType.WORLD))
{
preTick((World)tickData[0]);
}
}
@Override
public void tickEnd(EnumSet<TickType> type, Object... tickData)
{
if(type.contains(TickType.WORLD))
{
postTick((World)tickData[0]);
}
}
@Override
public EnumSet<TickType> 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<World, WorldExtension[]> worldMap = new HashMap<World, WorldExtension[]>();