mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
transition seal (well most of it)
This commit is contained in:
parent
2538a071ce
commit
f222672523
153
src/main/java/com/hbm/animloader/AnimatedModel.java
Normal file
153
src/main/java/com/hbm/animloader/AnimatedModel.java
Normal file
@ -0,0 +1,153 @@
|
||||
package com.hbm.animloader;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.hbm.util.BobMathUtil;
|
||||
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.util.MathHelper;
|
||||
|
||||
public class AnimatedModel {
|
||||
|
||||
public static FloatBuffer auxGLMatrix = GLAllocation.createDirectFloatBuffer(16);
|
||||
|
||||
//Pointless...
|
||||
public AnimationController controller;
|
||||
|
||||
public String name = "";
|
||||
|
||||
public float[] transform;
|
||||
|
||||
boolean hasGeometry = true;
|
||||
boolean hasTransform = false;
|
||||
|
||||
public String geo_name = "";
|
||||
public AnimatedModel parent;
|
||||
public List<AnimatedModel> children = new ArrayList<AnimatedModel>();
|
||||
int callList;
|
||||
|
||||
public AnimatedModel() {
|
||||
}
|
||||
|
||||
public void renderAnimated(long sysTime) {
|
||||
renderAnimated(sysTime, null);
|
||||
}
|
||||
|
||||
public void renderAnimated(long sysTime, IAnimatedModelCallback c) {
|
||||
if(controller.activeAnim == AnimationWrapper.EMPTY) {
|
||||
render(c);
|
||||
return;
|
||||
}
|
||||
|
||||
AnimationWrapper activeAnim = controller.activeAnim;
|
||||
int numKeyFrames = activeAnim.anim.numKeyFrames;
|
||||
int diff = (int) (sysTime - activeAnim.startTime);
|
||||
diff *= activeAnim.speedScale;
|
||||
if(diff > activeAnim.anim.length) {
|
||||
int diff2 = diff % activeAnim.anim.length;
|
||||
switch(activeAnim.endResult.type) {
|
||||
case END:
|
||||
controller.activeAnim = AnimationWrapper.EMPTY;
|
||||
render(c);
|
||||
return;
|
||||
case REPEAT:
|
||||
activeAnim.startTime = sysTime - diff2;
|
||||
break;
|
||||
case REPEAT_REVERSE:
|
||||
activeAnim.startTime = sysTime - diff2;
|
||||
activeAnim.reverse = !activeAnim.reverse;
|
||||
break;
|
||||
case START_NEW:
|
||||
activeAnim.cloneStats(activeAnim.endResult.next);
|
||||
activeAnim.startTime = sysTime - diff2;
|
||||
break;
|
||||
case STAY:
|
||||
activeAnim.startTime = sysTime - activeAnim.anim.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
diff = (int) (sysTime - activeAnim.startTime);
|
||||
if(activeAnim.reverse)
|
||||
diff = activeAnim.anim.length - diff;
|
||||
diff *= activeAnim.speedScale;
|
||||
float remappedTime = MathHelper.clamp_float(BobMathUtil.remap(diff, 0, activeAnim.anim.length, 0, numKeyFrames - 1), 0, numKeyFrames - 1);
|
||||
float diffN = BobMathUtil.remap01_clamp(diff, 0, activeAnim.anim.length);
|
||||
int index = (int) remappedTime;
|
||||
int first = index;
|
||||
int next;
|
||||
if(index < numKeyFrames - 1) {
|
||||
next = index + 1;
|
||||
} else {
|
||||
next = first;
|
||||
}
|
||||
|
||||
renderWithIndex((float) fract(remappedTime), first, next, diffN, c);
|
||||
controller.activeAnim.prevFrame = first;
|
||||
}
|
||||
|
||||
protected void renderWithIndex(float inter, int firstIndex, int nextIndex, float diffN, IAnimatedModelCallback c) {
|
||||
GL11.glPushMatrix();
|
||||
boolean hidden = false;
|
||||
if(hasTransform) {
|
||||
Transform[] transforms = controller.activeAnim.anim.objectTransforms.get(name);
|
||||
if(transforms != null) {
|
||||
hidden = transforms[firstIndex].hidden;
|
||||
transforms[firstIndex].interpolateAndApply(transforms[nextIndex], inter);
|
||||
} else {
|
||||
auxGLMatrix.put(transform);
|
||||
auxGLMatrix.rewind();
|
||||
GL11.glMultMatrix(auxGLMatrix);
|
||||
}
|
||||
}
|
||||
if(c != null)
|
||||
hidden |= c.onRender(controller.activeAnim.prevFrame, firstIndex, callList, diffN, name);
|
||||
if(hasGeometry && !hidden) {
|
||||
GL11.glCallList(callList);
|
||||
}
|
||||
if(c != null)
|
||||
c.postRender(controller.activeAnim.prevFrame, firstIndex, callList, diffN, name);
|
||||
for(AnimatedModel m : children) {
|
||||
m.renderWithIndex(inter, firstIndex, nextIndex, diffN, c);
|
||||
}
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
public void render() {
|
||||
render(null);
|
||||
}
|
||||
|
||||
public void render(IAnimatedModelCallback c) {
|
||||
GL11.glPushMatrix();
|
||||
if(hasTransform) {
|
||||
auxGLMatrix.put(transform);
|
||||
auxGLMatrix.rewind();
|
||||
GL11.glMultMatrix(auxGLMatrix);
|
||||
}
|
||||
boolean hidden = false;
|
||||
if(c != null)
|
||||
hidden = c.onRender(-1, -1, callList, -1, name);
|
||||
if(hasGeometry && !hidden) {
|
||||
GL11.glCallList(callList);
|
||||
}
|
||||
if(c != null)
|
||||
c.postRender(-1, -1, callList, -1, name);
|
||||
for(AnimatedModel m : children) {
|
||||
m.render(c);
|
||||
}
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
private static float fract(float number) {
|
||||
return (float) (number - Math.floor(number));
|
||||
}
|
||||
|
||||
public static interface IAnimatedModelCallback {
|
||||
//(prevFrame, currentFrame, model, diffN, modelName)
|
||||
public boolean onRender(int prevFrame, int currentFrame, int model, float diffN, String modelName);
|
||||
public default void postRender(int prevFrame, int currentFrame, int model, float diffN, String modelName){};
|
||||
}
|
||||
}
|
||||
22
src/main/java/com/hbm/animloader/Animation.java
Normal file
22
src/main/java/com/hbm/animloader/Animation.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.hbm.animloader;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Animation {
|
||||
|
||||
public static final Animation EMPTY = createBlankAnimation();
|
||||
|
||||
public int length;
|
||||
public int numKeyFrames;
|
||||
public Map<String, Transform[]> objectTransforms = new HashMap<String, Transform[]>();
|
||||
|
||||
private static Animation createBlankAnimation(){
|
||||
Animation anim = new Animation();
|
||||
anim.numKeyFrames = 0;
|
||||
anim.length = 0;
|
||||
anim.objectTransforms = new HashMap<String, Transform[]>();
|
||||
return anim;
|
||||
}
|
||||
|
||||
}
|
||||
22
src/main/java/com/hbm/animloader/AnimationController.java
Normal file
22
src/main/java/com/hbm/animloader/AnimationController.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.hbm.animloader;
|
||||
|
||||
public class AnimationController {
|
||||
|
||||
//Drillgon200: You know what? I'm pretty sure this class is entirely pointless and just acts as a stupid getter/setter for the wrapper.
|
||||
//TODO delete
|
||||
|
||||
protected AnimationWrapper activeAnim = AnimationWrapper.EMPTY;
|
||||
|
||||
public void setAnim(AnimationWrapper w) {
|
||||
activeAnim = w;
|
||||
}
|
||||
|
||||
public void stopAnim() {
|
||||
activeAnim = AnimationWrapper.EMPTY;
|
||||
}
|
||||
|
||||
public AnimationWrapper getAnim() {
|
||||
return activeAnim;
|
||||
}
|
||||
|
||||
}
|
||||
87
src/main/java/com/hbm/animloader/AnimationWrapper.java
Normal file
87
src/main/java/com/hbm/animloader/AnimationWrapper.java
Normal file
@ -0,0 +1,87 @@
|
||||
package com.hbm.animloader;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class AnimationWrapper {
|
||||
|
||||
public static final AnimationWrapper EMPTY = new AnimationWrapper(Animation.EMPTY){
|
||||
public AnimationWrapper onEnd(EndResult res) {
|
||||
return this;
|
||||
};
|
||||
};
|
||||
|
||||
public Animation anim;
|
||||
|
||||
public long startTime;
|
||||
public float speedScale = 1;
|
||||
public boolean reverse;
|
||||
public EndResult endResult = EndResult.END;
|
||||
public int prevFrame = 0;
|
||||
|
||||
public AnimationWrapper(Animation a){
|
||||
this.anim = a;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public AnimationWrapper(long startTime, Animation a){
|
||||
this.anim = a;
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public AnimationWrapper(long startTime, float scale, Animation a){
|
||||
this.anim = a;
|
||||
this.speedScale = scale;
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public AnimationWrapper onEnd(EndResult res){
|
||||
this.endResult = res;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationWrapper reverse(){
|
||||
this.reverse = !reverse;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationWrapper cloneStats(AnimationWrapper other){
|
||||
this.anim = other.anim;
|
||||
this.startTime = other.startTime;
|
||||
this.reverse = other.reverse;
|
||||
this.endResult = other.endResult;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationWrapper cloneStatsWithoutTime(AnimationWrapper other){
|
||||
this.anim = other.anim;
|
||||
this.reverse = other.reverse;
|
||||
this.endResult = other.endResult;
|
||||
return this;
|
||||
}
|
||||
|
||||
public enum EndType {
|
||||
END,
|
||||
REPEAT,
|
||||
REPEAT_REVERSE,
|
||||
START_NEW,
|
||||
STAY;
|
||||
}
|
||||
|
||||
public static class EndResult {
|
||||
|
||||
public static final EndResult END = new EndResult(EndType.END, null);
|
||||
|
||||
EndType type;
|
||||
AnimationWrapper next;
|
||||
|
||||
public EndResult(EndType type) {
|
||||
this(type, null);
|
||||
}
|
||||
|
||||
public EndResult(EndType type, @Nullable AnimationWrapper next) {
|
||||
this.type = type;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
445
src/main/java/com/hbm/animloader/ColladaLoader.java
Normal file
445
src/main/java/com/hbm/animloader/ColladaLoader.java
Normal file
@ -0,0 +1,445 @@
|
||||
package com.hbm.animloader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.hbm.main.MainRegistry;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.resources.IResource;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class ColladaLoader {
|
||||
//Drillgon200: This code is only slightly less terrible than the first time. I hate XML.
|
||||
|
||||
/*
|
||||
* My attempt at making a collada loader.
|
||||
* Some things to note: You can't use child of constraints with it with complete accuracy,
|
||||
* as this will break the linear interpolation and I don't know how to fix it
|
||||
* To get around this, you can put multiple objects with different parents or origins and toggle their visibility.
|
||||
* It's hacky, but it works, at least if you don't need an object affected by multiple bones at the same time.
|
||||
*/
|
||||
|
||||
//Bob:
|
||||
|
||||
/*
|
||||
* I walk to Burger King, then I walk back home from Burger King
|
||||
* walk to Burger King, then I walk back home I walk back
|
||||
* I walk, then I walk back home from Burger King
|
||||
* I walk, then I walk back home from Burger King
|
||||
* then I walk back home from Burger King
|
||||
* I walk, I walk
|
||||
* walk walk, walk walk
|
||||
* I walk, I walk
|
||||
* Burger King
|
||||
*/
|
||||
|
||||
public static AnimatedModel load(ResourceLocation file) {
|
||||
return load(file, false);
|
||||
}
|
||||
|
||||
public static AnimatedModel load(ResourceLocation file, boolean flipV) {
|
||||
IResource res;
|
||||
try {
|
||||
res = Minecraft.getMinecraft().getResourceManager().getResource(file);
|
||||
Document doc;
|
||||
try {
|
||||
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(res.getInputStream());
|
||||
return parse(doc.getDocumentElement(), flipV);
|
||||
} catch(SAXException e) {
|
||||
e.printStackTrace();
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch(ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
MainRegistry.logger.log(Level.ERROR, "FAILED TO LOAD MODEL: " + file);
|
||||
return null;
|
||||
}
|
||||
|
||||
//Model loading section
|
||||
|
||||
private static AnimatedModel parse(Element root, boolean flipV){
|
||||
//Should get the first bone
|
||||
Element scene = getFirstElement((Element)root.getElementsByTagName("library_visual_scenes").item(0));
|
||||
AnimatedModel structure = new AnimatedModel(){
|
||||
@Override
|
||||
protected void renderWithIndex(float inter, int firstIndex, int nextIndex, float diffN, IAnimatedModelCallback c) {
|
||||
for(AnimatedModel m : children){
|
||||
m.renderWithIndex(inter, firstIndex, nextIndex, diffN, c);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void render() {
|
||||
for(AnimatedModel m : children){
|
||||
m.render();
|
||||
}
|
||||
}
|
||||
};
|
||||
for(Element node : getChildElements(scene)){
|
||||
if(node.getElementsByTagName("instance_geometry").getLength() > 0){
|
||||
structure.children.add(parseStructure(node));
|
||||
}
|
||||
}
|
||||
Map<String, Integer> geometry = parseGeometry((Element)root.getElementsByTagName("library_geometries").item(0), flipV);
|
||||
addGeometry(structure, geometry);
|
||||
setAnimationController(structure, new AnimationController());
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
private static void setAnimationController(AnimatedModel model, AnimationController control){
|
||||
model.controller = control;
|
||||
for(AnimatedModel m : model.children)
|
||||
setAnimationController(m, control);
|
||||
}
|
||||
|
||||
private static Element getFirstElement(Node root){
|
||||
NodeList nodes = root.getChildNodes();
|
||||
for(int i = 0; i < nodes.getLength(); i ++){
|
||||
Node node = nodes.item(i);
|
||||
if(node.getNodeType() == Node.ELEMENT_NODE){
|
||||
return (Element)node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<Element> getElementsByName(Element e, String name){
|
||||
List<Element> elements = new ArrayList<Element>();
|
||||
NodeList n = e.getChildNodes();
|
||||
for(int i = 0; i < n.getLength(); i ++){
|
||||
Node node = n.item(i);
|
||||
if(node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals(name)){
|
||||
elements.add((Element) node);
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
private static List<Element> getChildElements(Element e){
|
||||
List<Element> elements = new ArrayList<Element>();
|
||||
if(e == null)
|
||||
return elements;
|
||||
NodeList n = e.getChildNodes();
|
||||
for(int i = 0; i < n.getLength(); i ++){
|
||||
Node node = n.item(i);
|
||||
if(node.getNodeType() == Node.ELEMENT_NODE){
|
||||
elements.add((Element) node);
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
private static AnimatedModel parseStructure(Element root){
|
||||
AnimatedModel model = new AnimatedModel();
|
||||
model.name = root.getAttribute("name");
|
||||
|
||||
NodeList children = root.getChildNodes();
|
||||
for(int i = 0; i < children.getLength(); i ++){
|
||||
Node node = children.item(i);
|
||||
if(node.getNodeType() != Node.ELEMENT_NODE)
|
||||
continue;
|
||||
Element ele = (Element) node;
|
||||
if("transform".equals(ele.getAttribute("sid"))){
|
||||
//Do I even need to flip the matrix here? No idea!
|
||||
model.transform = flipMatrix(parseFloatArray(ele.getTextContent()));
|
||||
model.hasTransform = true;
|
||||
} else if("instance_geometry".equals(ele.getTagName())){
|
||||
model.geo_name = ele.getAttribute("url").substring(1);
|
||||
} else if(ele.getElementsByTagName("instance_geometry").getLength() > 0){
|
||||
AnimatedModel childModel = parseStructure(ele);
|
||||
childModel.parent = model;
|
||||
model.children.add(childModel);
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
/*private static void addStructureChildren(Element root, AnimatedModel model){
|
||||
NodeList children = root.getChildNodes();
|
||||
for(int i = 0; i < children.getLength(); i ++){
|
||||
Node node = children.item(i);
|
||||
if(node.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element element = (Element) node;if(getElementsByName(element, "instance_geometry").size() > 0){
|
||||
addGeoNamesToModel(element, model);
|
||||
} else if(getElementsByName(element, "node").size() > 0 && "JOINT".equals(((Element)getElementsByName(element, "node").get(0)).getAttribute("type"))){
|
||||
AnimatedModel m = parseStructure(element);
|
||||
model.children.add(m);
|
||||
m.parent = model;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addGeoNamesToModel(Element root, AnimatedModel model){
|
||||
List<Element> geo_names = getElementsByName(root, "instance_geometry");
|
||||
for(Element e : geo_names){
|
||||
String name = e.getAttribute("url").substring(1);
|
||||
model.geo_names.add(name);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
//Geometry loading section
|
||||
|
||||
//Map of geometry name to display list id
|
||||
private static Map<String, Integer> parseGeometry(Element root, boolean flipV){
|
||||
Map<String, Integer> allGeometry = new HashMap<String, Integer>();
|
||||
for(Element e : getElementsByName(root, "geometry")){
|
||||
String name = e.getAttribute("id");
|
||||
Element mesh = getElementsByName(e, "mesh").get(0);
|
||||
|
||||
float[] positions = new float[0];
|
||||
float[] normals = new float[0];
|
||||
float[] texCoords = new float[0];
|
||||
int[] indices = new int[0];
|
||||
|
||||
for(Element section : getChildElements(mesh)){
|
||||
String id = section.getAttribute("id");
|
||||
if(id.endsWith("mesh-positions")){
|
||||
positions = parsePositions(section);
|
||||
} else if(id.endsWith("mesh-normals")){
|
||||
normals = parseNormals(section);
|
||||
} else if(id.endsWith("mesh-map-0")){
|
||||
texCoords = parseTexCoords(section);
|
||||
} else if(section.getNodeName().equals("triangles")){
|
||||
indices = ArrayUtils.addAll(indices, parseIndices(section));
|
||||
}
|
||||
}
|
||||
if(positions.length == 0)
|
||||
continue;
|
||||
|
||||
int displayList = GL11.glGenLists(1);
|
||||
GL11.glNewList(displayList, GL11.GL_COMPILE);
|
||||
|
||||
Tessellator tess = Tessellator.instance;
|
||||
|
||||
tess.startDrawing(GL11.GL_TRIANGLES);
|
||||
|
||||
if(indices.length > 0){
|
||||
for(int i = 0; i < indices.length; i += 3){
|
||||
|
||||
float v = texCoords[indices[i + 2] * 2 + 1];
|
||||
if(flipV){
|
||||
v = 1 - v;
|
||||
}
|
||||
|
||||
tess.setNormal(normals[indices[i + 1] * 3], normals[indices[i + 1] * 3 + 1], normals[indices[i + 1] * 3 + 2]);
|
||||
tess.setTextureUV(texCoords[indices[i + 2] * 2], v);
|
||||
tess.addVertex(positions[indices[i] * 3], positions[indices[i] * 3 + 1], positions[indices[i] * 3 + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
//ORIGINAL:
|
||||
/*BufferBuilder buf = Tessellator.getInstance().getBuffer();
|
||||
buf.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX_NORMAL);
|
||||
if(indices.length > 0){
|
||||
for(int i = 0; i < indices.length; i += 3){
|
||||
float v = texCoords[indices[i+2]*2+1];
|
||||
if(flipV){
|
||||
v = 1-v;
|
||||
}
|
||||
buf.pos(positions[indices[i]*3], positions[indices[i]*3+1], positions[indices[i]*3+2])
|
||||
.tex(texCoords[indices[i+2]*2], v)
|
||||
.normal(normals[indices[i+1]*3], normals[indices[i+1]*3+1], normals[indices[i+1]*3+2])
|
||||
.endVertex();
|
||||
}
|
||||
} else {
|
||||
|
||||
}*/
|
||||
|
||||
tess.draw();
|
||||
GL11.glEndList();
|
||||
|
||||
allGeometry.put(name, displayList);
|
||||
}
|
||||
return allGeometry;
|
||||
}
|
||||
|
||||
private static float[] parsePositions(Element root){
|
||||
String content = root.getElementsByTagName("float_array").item(0).getTextContent();
|
||||
return parseFloatArray(content);
|
||||
}
|
||||
|
||||
private static float[] parseNormals(Element root){
|
||||
String content = root.getElementsByTagName("float_array").item(0).getTextContent();
|
||||
return parseFloatArray(content);
|
||||
}
|
||||
|
||||
private static float[] parseTexCoords(Element root){
|
||||
String content = root.getElementsByTagName("float_array").item(0).getTextContent();
|
||||
return parseFloatArray(content);
|
||||
}
|
||||
|
||||
private static int[] parseIndices(Element root){
|
||||
String content = root.getElementsByTagName("p").item(0).getTextContent();
|
||||
return parseIntegerArray(content);
|
||||
}
|
||||
|
||||
private static float[] parseFloatArray(String s){
|
||||
if(s.isEmpty()){
|
||||
return new float[0];
|
||||
}
|
||||
String[] numbers = s.split(" ");
|
||||
float[] arr = new float[numbers.length];
|
||||
for(int i = 0; i < numbers.length; i ++){
|
||||
arr[i] = Float.parseFloat(numbers[i]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
private static int[] parseIntegerArray(String s){
|
||||
String[] numbers = s.split(" ");
|
||||
int[] arr = new int[numbers.length];
|
||||
for(int i = 0; i < numbers.length; i ++){
|
||||
arr[i] = Integer.parseInt(numbers[i]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
private static void addGeometry(AnimatedModel m, Map<String, Integer> geometry){
|
||||
if(!"".equals(m.geo_name) && geometry.containsKey(m.geo_name))
|
||||
m.callList = geometry.get(m.geo_name);
|
||||
else {
|
||||
m.hasGeometry = false;
|
||||
m.callList = -1;
|
||||
}
|
||||
for(AnimatedModel child : m.children){
|
||||
addGeometry(child, geometry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Animation loading section
|
||||
public static Animation loadAnim(int length, ResourceLocation file){
|
||||
IResource res;
|
||||
try {
|
||||
res = Minecraft.getMinecraft().getResourceManager().getResource(file);
|
||||
Document doc;
|
||||
try {
|
||||
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(res.getInputStream());
|
||||
return parseAnim(doc.getDocumentElement(), length);
|
||||
} catch(SAXException e) {
|
||||
e.printStackTrace();
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch(ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
MainRegistry.logger.log(Level.ERROR, "FAILED TO LOAD MODEL: " + file);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Animation parseAnim(Element root, int length){
|
||||
Element anim_section = (Element)root.getElementsByTagName("library_animations").item(0);
|
||||
Animation anim = new Animation();
|
||||
anim.length = length;
|
||||
for(Element e : getChildElements(anim_section)){
|
||||
if("animation".equals(e.getNodeName())){
|
||||
String name = e.getAttribute("name");
|
||||
Transform[] t = null;
|
||||
List<Element> elements2 = getChildElements(e);
|
||||
if(elements2.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
for(Element e2 : elements2){
|
||||
if(e2.getAttribute("id").endsWith("transform")){
|
||||
t = parseTransforms(e2);
|
||||
} else if(e2.getAttribute("id").endsWith("hide_viewport")){
|
||||
setViewportHiddenKeyframes(t, e2);
|
||||
}
|
||||
}
|
||||
anim.objectTransforms.put(name, t);
|
||||
anim.numKeyFrames = t.length;
|
||||
}
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
|
||||
private static Transform[] parseTransforms(Element root){
|
||||
String output = getOutputLocation(root);
|
||||
for(Element e : getChildElements(root)){
|
||||
if(e.getAttribute("id").equals(output)){
|
||||
return parseTransformsFromText(e.getElementsByTagName("float_array").item(0).getTextContent());
|
||||
}
|
||||
}
|
||||
System.out.println("Failed to parse transforms! This will not work!");
|
||||
System.out.println("Node name: " + root.getTagName());
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void setViewportHiddenKeyframes(Transform[] t, Element root){
|
||||
String output = getOutputLocation(root);
|
||||
for(Element e : getChildElements(root)){
|
||||
if(e.getAttribute("id").equals(output)){
|
||||
int[] hiddenFrames = parseIntegerArray(e.getElementsByTagName("float_array").item(0).getTextContent());
|
||||
for(int i = 0; i < hiddenFrames.length; i ++){
|
||||
t[i].hidden = hiddenFrames[i] > 0 ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getOutputLocation(Element root){
|
||||
Element sampler = (Element) root.getElementsByTagName("sampler").item(0);
|
||||
for(Element e : getChildElements(sampler)){
|
||||
if("OUTPUT".equals(e.getAttribute("semantic"))){
|
||||
return e.getAttribute("source").substring(1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Transform[] parseTransformsFromText(String data){
|
||||
float[] floats = parseFloatArray(data);
|
||||
Transform[] transforms = new Transform[floats.length/16];
|
||||
for(int i = 0; i < floats.length/16; i++){
|
||||
float[] rawTransform = new float[16];
|
||||
for(int j = 0; j < 16; j ++)
|
||||
rawTransform[j] = floats[i*16 + j];
|
||||
transforms[i] = new Transform(rawTransform);
|
||||
}
|
||||
return transforms;
|
||||
}
|
||||
|
||||
private static float[] flipMatrix(float[] f){
|
||||
if(f.length != 16){
|
||||
System.out.println("Error flipping matrix: array length not 16. This will not work!");
|
||||
System.out.println("Matrix: " + f);
|
||||
}
|
||||
return new float[]{
|
||||
f[0], f[4], f[8], f[12],
|
||||
f[1], f[5], f[9], f[13],
|
||||
f[2], f[6], f[10], f[14],
|
||||
f[3], f[7], f[11], f[15]
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
133
src/main/java/com/hbm/animloader/Transform.java
Normal file
133
src/main/java/com/hbm/animloader/Transform.java
Normal file
@ -0,0 +1,133 @@
|
||||
package com.hbm.animloader;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import org.lwjgl.util.vector.Matrix4f;
|
||||
import org.lwjgl.util.vector.Quaternion;
|
||||
|
||||
import com.hbm.util.BobMathUtil;
|
||||
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.util.Vec3;
|
||||
|
||||
public class Transform {
|
||||
|
||||
protected static FloatBuffer auxGLMatrix = GLAllocation.createDirectFloatBuffer(16);
|
||||
|
||||
Vec3 scale;
|
||||
Vec3 translation;
|
||||
Quaternion rotation;
|
||||
|
||||
boolean hidden = false;
|
||||
|
||||
public Transform(float[] matrix){
|
||||
scale = getScaleFromMatrix(matrix);
|
||||
auxGLMatrix.put(matrix);
|
||||
auxGLMatrix.rewind();
|
||||
rotation = new Quaternion().setFromMatrix((Matrix4f) new Matrix4f().load(auxGLMatrix));
|
||||
translation = Vec3.createVectorHelper(matrix[0*4+3], matrix[1*4+3], matrix[2*4+3]);
|
||||
auxGLMatrix.rewind();
|
||||
}
|
||||
|
||||
private Vec3 getScaleFromMatrix(float[] matrix){
|
||||
float scaleX = (float) Vec3.createVectorHelper(matrix[0], matrix[1], matrix[2]).lengthVector();
|
||||
float scaleY = (float) Vec3.createVectorHelper(matrix[4], matrix[5], matrix[6]).lengthVector();
|
||||
float scaleZ = (float) Vec3.createVectorHelper(matrix[8], matrix[9], matrix[10]).lengthVector();
|
||||
|
||||
matrix[0] = matrix[0]/scaleX;
|
||||
matrix[1] = matrix[1]/scaleX;
|
||||
matrix[2] = matrix[2]/scaleX;
|
||||
|
||||
matrix[4] = matrix[4]/scaleY;
|
||||
matrix[5] = matrix[5]/scaleY;
|
||||
matrix[6] = matrix[6]/scaleY;
|
||||
|
||||
matrix[8] = matrix[8]/scaleZ;
|
||||
matrix[9] = matrix[9]/scaleZ;
|
||||
matrix[10] = matrix[10]/scaleZ;
|
||||
return Vec3.createVectorHelper(scaleX, scaleY, scaleZ);
|
||||
}
|
||||
|
||||
public void interpolateAndApply(Transform other, float inter){
|
||||
Vec3 trans = BobMathUtil.interpVec(this.translation, other.translation, inter); //ORIGINAL: translation.interpolate(other.translation, inter);
|
||||
Vec3 scale = BobMathUtil.interpVec(this.scale, other.scale, inter); //ORIGINAL: this.scale.interpolate(other.scale, inter);
|
||||
Quaternion rot = slerp(rotation, other.rotation, inter);
|
||||
//GlStateManager.quatToGlMatrix(auxGLMatrix, rot); TODO: find implementation
|
||||
scale(auxGLMatrix, scale);
|
||||
auxGLMatrix.put(12, (float) trans.xCoord);
|
||||
auxGLMatrix.put(13, (float) trans.yCoord);
|
||||
auxGLMatrix.put(14, (float) trans.zCoord);
|
||||
|
||||
//for(int i = 0; i < 16; i ++){
|
||||
//System.out.print(auxGLMatrix.get(i) + " ");
|
||||
//}
|
||||
//System.out.println();
|
||||
//GlStateManager.multMatrix(auxGLMatrix); TODO: find implementation
|
||||
}
|
||||
|
||||
private void scale(FloatBuffer matrix, Vec3 scale){
|
||||
matrix.put(0, (float) (matrix.get(0)*scale.xCoord));
|
||||
matrix.put(4, (float) (matrix.get(4)*scale.xCoord));
|
||||
matrix.put(8, (float) (matrix.get(8)*scale.xCoord));
|
||||
matrix.put(12, (float) (matrix.get(12)*scale.xCoord));
|
||||
|
||||
matrix.put(1, (float) (matrix.get(1)*scale.yCoord));
|
||||
matrix.put(5, (float) (matrix.get(5)*scale.yCoord));
|
||||
matrix.put(9, (float) (matrix.get(9)*scale.yCoord));
|
||||
matrix.put(13, (float) (matrix.get(13)*scale.yCoord));
|
||||
|
||||
matrix.put(2, (float) (matrix.get(2)*scale.zCoord));
|
||||
matrix.put(6, (float) (matrix.get(6)*scale.zCoord));
|
||||
matrix.put(10, (float) (matrix.get(10)*scale.zCoord));
|
||||
matrix.put(14, (float) (matrix.get(14)*scale.zCoord));
|
||||
}
|
||||
|
||||
//Thanks, wikipedia
|
||||
//God, I wish java had operator overloads. Those are one of my favorite things about c and glsl.
|
||||
protected Quaternion slerp(Quaternion v0, Quaternion v1, float t) {
|
||||
// Only unit quaternions are valid rotations.
|
||||
// Normalize to avoid undefined behavior.
|
||||
//Drillgon200: Any quaternions loaded from blender should be normalized already
|
||||
//v0.normalise();
|
||||
//v1.normalise();
|
||||
|
||||
// Compute the cosine of the angle between the two vectors.
|
||||
double dot = Quaternion.dot(v0, v1);
|
||||
|
||||
// If the dot product is negative, slerp won't take
|
||||
// the shorter path. Note that v1 and -v1 are equivalent when
|
||||
// the negation is applied to all four components. Fix by
|
||||
// reversing one quaternion.
|
||||
if (dot < 0.0f) {
|
||||
v1 = new Quaternion(-v1.x, -v1.y, -v1.z, -v1.w);
|
||||
dot = -dot;
|
||||
}
|
||||
|
||||
final double DOT_THRESHOLD = 0.9999999;
|
||||
if (dot > DOT_THRESHOLD) {
|
||||
// If the inputs are too close for comfort, linearly interpolate
|
||||
// and normalize the result.
|
||||
Quaternion result = new Quaternion(v0.x + t*v1.x,
|
||||
v0.y + t*v1.y,
|
||||
v0.z + t*v1.z,
|
||||
v0.w + t*v1.w);
|
||||
result.normalise();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Since dot is in range [0, DOT_THRESHOLD], acos is safe
|
||||
double theta_0 = Math.acos(dot); // theta_0 = angle between input vectors
|
||||
double theta = theta_0*t; // theta = angle between v0 and result
|
||||
double sin_theta = Math.sin(theta); // compute this value only once
|
||||
double sin_theta_0 = Math.sin(theta_0); // compute this value only once
|
||||
|
||||
float s0 = (float) (Math.cos(theta) - dot * sin_theta / sin_theta_0); // == sin(theta_0 - theta) / sin(theta_0)
|
||||
float s1 = (float) (sin_theta / sin_theta_0);
|
||||
|
||||
return new Quaternion(s0*v0.x + s1*v1.x,
|
||||
s0*v0.y + s1*v1.y,
|
||||
s0*v0.z + s1*v1.z,
|
||||
s0*v0.w + s1*v1.w);
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,6 +18,7 @@ import com.hbm.items.special.ItemOreBlock;
|
||||
import com.hbm.lib.ModDamageSource;
|
||||
import com.hbm.lib.RefStrings;
|
||||
import com.hbm.main.MainRegistry;
|
||||
import com.hbm.tileentity.DoorDecl;
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import net.minecraft.block.Block;
|
||||
@ -512,6 +513,7 @@ public class ModBlocks {
|
||||
|
||||
public static Block vault_door;
|
||||
public static Block blast_door;
|
||||
public static Block transision_seal;
|
||||
|
||||
public static Block door_metal;
|
||||
public static Block door_office;
|
||||
@ -1918,6 +1920,7 @@ public class ModBlocks {
|
||||
|
||||
vault_door = new VaultDoor(Material.iron).setBlockName("vault_door").setHardness(10.0F).setResistance(10000.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":vault_door");
|
||||
blast_door = new BlastDoor(Material.iron).setBlockName("blast_door").setHardness(10.0F).setResistance(10000.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":blast_door");
|
||||
transision_seal = new BlockDoorGeneric(Material.iron, DoorDecl.TRANSITION_SEAL).setBlockName("transission_seal").setHardness(10.0F).setResistance(10000.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":transission_seal");
|
||||
|
||||
door_metal = new BlockModDoor(Material.iron).setBlockName("door_metal").setHardness(5.0F).setResistance(5.0F).setBlockTextureName(RefStrings.MODID + ":door_metal");
|
||||
door_office = new BlockModDoor(Material.iron).setBlockName("door_office").setHardness(10.0F).setResistance(10.0F).setBlockTextureName(RefStrings.MODID + ":door_office");
|
||||
@ -2756,6 +2759,7 @@ public class ModBlocks {
|
||||
//Vault Door
|
||||
GameRegistry.registerBlock(vault_door, vault_door.getUnlocalizedName());
|
||||
GameRegistry.registerBlock(blast_door, blast_door.getUnlocalizedName());
|
||||
GameRegistry.registerBlock(transision_seal, transision_seal.getUnlocalizedName());
|
||||
|
||||
//Doors
|
||||
GameRegistry.registerBlock(door_metal, door_metal.getUnlocalizedName());
|
||||
|
||||
123
src/main/java/com/hbm/blocks/generic/BlockDoorGeneric.java
Normal file
123
src/main/java/com/hbm/blocks/generic/BlockDoorGeneric.java
Normal file
@ -0,0 +1,123 @@
|
||||
package com.hbm.blocks.generic;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.hbm.blocks.BlockDummyable;
|
||||
import com.hbm.tileentity.DoorDecl;
|
||||
import com.hbm.tileentity.TileEntityDoorGeneric;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class BlockDoorGeneric extends BlockDummyable {
|
||||
|
||||
public DoorDecl type;
|
||||
|
||||
public BlockDoorGeneric(Material materialIn, DoorDecl type){
|
||||
super(materialIn);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta){
|
||||
if(meta >= 12)
|
||||
return new TileEntityDoorGeneric();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getDimensions(){
|
||||
return type.getDimensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer playerIn, int side, float hitX, float hitY, float hitZ){
|
||||
if(!world.isRemote && !playerIn.isSneaking()) {
|
||||
int[] pos1 = findCore(world, x, y, z);
|
||||
if(pos1 == null)
|
||||
return false;
|
||||
TileEntityDoorGeneric door = (TileEntityDoorGeneric) world.getTileEntity(pos1[0], pos1[1], pos1[2]);
|
||||
|
||||
if(door != null) {
|
||||
return door.tryToggle(playerIn);
|
||||
}
|
||||
}
|
||||
if(!playerIn.isSneaking())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLadder(IBlockAccess world, int x, int y, int z, EntityLivingBase entity) {
|
||||
TileEntity te = world.getTileEntity(x, y, z);
|
||||
int meta = world.getBlockMetadata(x, y, z);
|
||||
boolean open = hasExtra(meta) || (te instanceof TileEntityDoorGeneric && ((TileEntityDoorGeneric)te).shouldUseBB);
|
||||
return type.isLadder(open);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCollisionBoxesToList(World worldIn, int x, int y, int z, AxisAlignedBB entityBox, List collidingBoxes, Entity entityIn) {
|
||||
AxisAlignedBB box = getCollisionBoundingBoxFromPool(worldIn, x, y, z);
|
||||
if(box.minY == 0 && box.maxY == 0)
|
||||
return;
|
||||
super.addCollisionBoxesToList( worldIn, x, y, z, entityBox, collidingBoxes, entityIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNeighborBlockChange(World world, int x, int y, int z, Block blockIn){
|
||||
|
||||
if(!world.isRemote){
|
||||
|
||||
int[] corePos = findCore(world, x, y, z);
|
||||
if(corePos != null){
|
||||
TileEntity core = world.getTileEntity(corePos[0], corePos[1], corePos[2]);
|
||||
if(core instanceof TileEntityDoorGeneric){
|
||||
TileEntityDoorGeneric door = (TileEntityDoorGeneric)core;
|
||||
door.updateRedstonePower(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onNeighborBlockChange( world, x, y, z, blockIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getSelectedBoundingBoxFromPool(World source, int x, int y, int z) {
|
||||
int meta = source.getBlockMetadata(x, y, z);
|
||||
TileEntity te = source.getTileEntity(x, y, z);
|
||||
int[] core = this.findCore(source, x, y, z);
|
||||
boolean open = hasExtra(meta) || (te instanceof TileEntityDoorGeneric && ((TileEntityDoorGeneric)te).shouldUseBB);
|
||||
if(core == null){
|
||||
return AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1);
|
||||
}
|
||||
TileEntity te2 = source.getTileEntity(core[0], core[1], core[2]);
|
||||
ForgeDirection dir = ForgeDirection.getOrientation(te2.getBlockMetadata() - BlockDummyable.offset);
|
||||
AxisAlignedBB box = type.getBlockBound(x - core[0], y - core[1], z - core[2], open ); //.rotate(dir.getBlockRotation().add(Rotation.COUNTERCLOCKWISE_90)), open); TODO: add rotation
|
||||
//System.out.println(te2.getBlockMetadata()-offset);
|
||||
switch(te2.getBlockMetadata()-offset){
|
||||
case 2:
|
||||
return AxisAlignedBB.getBoundingBox(1-box.minX, box.minY, 1-box.minZ, 1-box.maxX, box.maxY, 1-box.maxZ);
|
||||
case 4:
|
||||
return AxisAlignedBB.getBoundingBox(1-box.minZ, box.minY, box.minX, 1-box.maxZ, box.maxY, box.maxX);
|
||||
case 3:
|
||||
return AxisAlignedBB.getBoundingBox(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ);
|
||||
case 5:
|
||||
return AxisAlignedBB.getBoundingBox(box.minZ, box.minY, 1-box.minX, box.maxZ, box.maxY, 1-box.maxX);
|
||||
}
|
||||
return AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1);
|
||||
}
|
||||
|
||||
}
|
||||
6
src/main/java/com/hbm/interfaces/IAnimatedDoor.java
Normal file
6
src/main/java/com/hbm/interfaces/IAnimatedDoor.java
Normal file
@ -0,0 +1,6 @@
|
||||
package com.hbm.interfaces;
|
||||
|
||||
public interface IAnimatedDoor extends IDoor {
|
||||
|
||||
public void handleNewState(byte state);
|
||||
}
|
||||
20
src/main/java/com/hbm/interfaces/IDoor.java
Normal file
20
src/main/java/com/hbm/interfaces/IDoor.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.hbm.interfaces;
|
||||
|
||||
public interface IDoor {
|
||||
|
||||
public void open();
|
||||
public void close();
|
||||
public DoorState getState();
|
||||
public void toggle();
|
||||
public default boolean setTexture(String tex) {
|
||||
return false;
|
||||
}
|
||||
public default void setTextureState(byte tex) { };
|
||||
|
||||
public enum DoorState {
|
||||
CLOSED,
|
||||
OPEN,
|
||||
CLOSING,
|
||||
OPENING;
|
||||
}
|
||||
}
|
||||
@ -72,6 +72,7 @@ import com.hbm.render.tileentity.*;
|
||||
import com.hbm.render.util.MissilePart;
|
||||
import com.hbm.sound.AudioWrapper;
|
||||
import com.hbm.sound.AudioWrapperClient;
|
||||
import com.hbm.tileentity.TileEntityDoorGeneric;
|
||||
import com.hbm.tileentity.bomb.*;
|
||||
import com.hbm.tileentity.conductor.*;
|
||||
import com.hbm.tileentity.deco.*;
|
||||
@ -263,6 +264,7 @@ public class ClientProxy extends ServerProxy {
|
||||
//doors
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityVaultDoor.class, new RenderVaultDoor());
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityBlastDoor.class, new RenderBlastDoor());
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityDoorGeneric.class, new RenderDoorGeneric());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -656,12 +658,13 @@ public class ClientProxy extends ServerProxy {
|
||||
FMLCommonHandler.instance().bus().register(handler);
|
||||
|
||||
AdvancedModelLoader.registerModelHandler(new HmfModelLoader());
|
||||
ResourceManager.loadAnimatedModels();
|
||||
|
||||
registerTileEntitySpecialRenderer();
|
||||
registerItemRenderer();
|
||||
registerEntityRenderer();
|
||||
registerBlockRenderer();
|
||||
|
||||
|
||||
RenderingRegistry.addNewArmourRendererPrefix("5");
|
||||
RenderingRegistry.addNewArmourRendererPrefix("6");
|
||||
RenderingRegistry.addNewArmourRendererPrefix("7");
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package com.hbm.main;
|
||||
|
||||
import com.hbm.animloader.AnimatedModel;
|
||||
import com.hbm.animloader.Animation;
|
||||
import com.hbm.animloader.ColladaLoader;
|
||||
import com.hbm.lib.RefStrings;
|
||||
import com.hbm.render.loader.HFRWavefrontObject;
|
||||
|
||||
@ -257,6 +260,10 @@ public class ResourceManager {
|
||||
public static final IModelCustom blast_door_slider = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/blast_door_slider.obj"));
|
||||
public static final IModelCustom blast_door_block = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/blast_door_block.obj"));
|
||||
|
||||
//Transission Seal
|
||||
public static AnimatedModel transition_seal;
|
||||
public static Animation transition_seal_anim;
|
||||
|
||||
//Tesla Coil
|
||||
public static final IModelCustom tesla = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/tesla.obj"));
|
||||
public static final IModelCustom teslacrab = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/mobs/teslacrab.obj"));
|
||||
@ -561,6 +568,9 @@ public class ResourceManager {
|
||||
public static final ResourceLocation blast_door_tooth_tex = new ResourceLocation(RefStrings.MODID, "textures/models/blast_door_tooth.png");
|
||||
public static final ResourceLocation blast_door_slider_tex = new ResourceLocation(RefStrings.MODID, "textures/models/blast_door_slider.png");
|
||||
public static final ResourceLocation blast_door_block_tex = new ResourceLocation(RefStrings.MODID, "textures/models/blast_door_block.png");
|
||||
|
||||
//Doors
|
||||
public static final ResourceLocation transition_seal_tex = new ResourceLocation(RefStrings.MODID, "textures/models/doors/transition_seal.png");
|
||||
|
||||
//Tesla Coil
|
||||
public static final ResourceLocation tesla_tex = new ResourceLocation(RefStrings.MODID, "textures/models/tesla.png");
|
||||
@ -1163,4 +1173,9 @@ public class ResourceManager {
|
||||
public static final IModelCustom deb_zirnox_element = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/zirnox/deb_element.obj"));
|
||||
public static final IModelCustom deb_zirnox_exchanger = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/zirnox/deb_exchanger.obj"));
|
||||
public static final IModelCustom deb_zirnox_shrapnel = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/zirnox/deb_shrapnel.obj"));
|
||||
|
||||
public static void loadAnimatedModels(){
|
||||
transition_seal = ColladaLoader.load(new ResourceLocation(RefStrings.MODID, "models/doors/seal.dae"), true);
|
||||
transition_seal_anim = ColladaLoader.loadAnim(24040, new ResourceLocation(RefStrings.MODID, "models/doors/seal.dae"));
|
||||
}
|
||||
}
|
||||
|
||||
72
src/main/java/com/hbm/packet/TEDoorAnimationPacket.java
Normal file
72
src/main/java/com/hbm/packet/TEDoorAnimationPacket.java
Normal file
@ -0,0 +1,72 @@
|
||||
package com.hbm.packet;
|
||||
|
||||
import com.hbm.interfaces.IAnimatedDoor;
|
||||
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
public class TEDoorAnimationPacket implements IMessage {
|
||||
|
||||
public int x, y, z;
|
||||
public byte state;
|
||||
public byte texture;
|
||||
|
||||
public TEDoorAnimationPacket() {
|
||||
}
|
||||
|
||||
public TEDoorAnimationPacket(int x, int y, int z, byte state) {
|
||||
this(x, y, z, state, (byte) -1);
|
||||
}
|
||||
|
||||
public TEDoorAnimationPacket(int x, int y, int z, byte state, byte tex) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.state = state;
|
||||
this.texture = tex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
x = buf.readInt();
|
||||
y = buf.readInt();
|
||||
z = buf.readInt();
|
||||
state = buf.readByte();
|
||||
if(buf.readableBytes() == 1){
|
||||
texture = buf.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeInt(x);
|
||||
buf.writeInt(y);
|
||||
buf.writeInt(z);
|
||||
buf.writeByte(state);
|
||||
if(texture != -1){
|
||||
buf.writeByte(texture);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Handler implements IMessageHandler<TEDoorAnimationPacket, IMessage> {
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public IMessage onMessage(TEDoorAnimationPacket m, MessageContext ctx) {
|
||||
|
||||
TileEntity te = Minecraft.getMinecraft().theWorld.getTileEntity(m.x, m.y, m.z);
|
||||
if(te instanceof IAnimatedDoor){
|
||||
((IAnimatedDoor) te).handleNewState(m.state);
|
||||
((IAnimatedDoor) te).setTextureState(m.texture);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
101
src/main/java/com/hbm/render/WavefrontObjDisplayList.java
Normal file
101
src/main/java/com/hbm/render/WavefrontObjDisplayList.java
Normal file
@ -0,0 +1,101 @@
|
||||
package com.hbm.render;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.hbm.render.loader.HFRWavefrontObject;
|
||||
import com.hbm.render.loader.S_GroupObject;
|
||||
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraftforge.client.model.IModelCustom;
|
||||
import net.minecraftforge.client.model.obj.GroupObject;
|
||||
import net.minecraftforge.client.model.obj.WavefrontObject;
|
||||
|
||||
public class WavefrontObjDisplayList implements IModelCustom {
|
||||
|
||||
public List<Pair<String, Integer>> nameToCallList = new ArrayList<>();
|
||||
|
||||
public WavefrontObjDisplayList(WavefrontObject obj) {
|
||||
Tessellator tes = Tessellator.instance;
|
||||
for(GroupObject g : obj.groupObjects){
|
||||
int list = GL11.glGenLists(1);
|
||||
GL11.glNewList(list, GL11.GL_COMPILE);
|
||||
tes.startDrawing(g.glDrawingMode);
|
||||
g.render(tes);
|
||||
tes.draw();
|
||||
GL11.glEndList();
|
||||
nameToCallList.add(Pair.of(g.name, list));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public WavefrontObjDisplayList(HFRWavefrontObject obj) {
|
||||
for(S_GroupObject g : obj.groupObjects){
|
||||
int list = GL11.glGenLists(1);
|
||||
GL11.glNewList(list, GL11.GL_COMPILE);
|
||||
g.render();
|
||||
GL11.glEndList();
|
||||
nameToCallList.add(Pair.of(g.name, list));
|
||||
}
|
||||
}
|
||||
|
||||
public int getListForName(String name){
|
||||
for(Pair<String, Integer> p : nameToCallList){
|
||||
if(p.getLeft().equalsIgnoreCase(name)){
|
||||
return p.getRight();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "obj_list";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderAll() {
|
||||
for(Pair<String, Integer> p : nameToCallList)
|
||||
GL11.glCallList(p.getRight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderOnly(String... groupNames) {
|
||||
for(Pair<String, Integer> p : nameToCallList){
|
||||
for(String name : groupNames){
|
||||
if(p.getLeft().equalsIgnoreCase(name)){
|
||||
GL11.glCallList(p.getRight());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderPart(String partName) {
|
||||
for(Pair<String, Integer> p : nameToCallList){
|
||||
if(p.getLeft().equalsIgnoreCase(partName)){
|
||||
GL11.glCallList(p.getRight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderAllExcept(String... excludedGroupNames) {
|
||||
for(Pair<String, Integer> p : nameToCallList){
|
||||
boolean skip = false;
|
||||
for(String name : excludedGroupNames){
|
||||
if(p.getLeft().equalsIgnoreCase(name)){
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!skip){
|
||||
GL11.glCallList(p.getRight());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
125
src/main/java/com/hbm/render/tileentity/RenderDoorGeneric.java
Normal file
125
src/main/java/com/hbm/render/tileentity/RenderDoorGeneric.java
Normal file
@ -0,0 +1,125 @@
|
||||
package com.hbm.render.tileentity;
|
||||
|
||||
import java.nio.DoubleBuffer;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.hbm.animloader.AnimatedModel;
|
||||
import com.hbm.animloader.Animation;
|
||||
import com.hbm.animloader.AnimationWrapper;
|
||||
import com.hbm.animloader.AnimationWrapper.EndResult;
|
||||
import com.hbm.animloader.AnimationWrapper.EndType;
|
||||
import com.hbm.blocks.BlockDummyable;
|
||||
import com.hbm.main.ResourceManager;
|
||||
import com.hbm.render.WavefrontObjDisplayList;
|
||||
import com.hbm.tileentity.DoorDecl;
|
||||
import com.hbm.tileentity.TileEntityDoorGeneric;
|
||||
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.MathHelper;
|
||||
|
||||
public class RenderDoorGeneric extends TileEntitySpecialRenderer {
|
||||
|
||||
private static DoubleBuffer buf = null;
|
||||
|
||||
private static final float[] tran = new float[3];
|
||||
private static final float[] orig = new float[3];
|
||||
private static final float[] rot = new float[3];
|
||||
|
||||
@Override
|
||||
public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float partialTicks){
|
||||
|
||||
TileEntityDoorGeneric te = (TileEntityDoorGeneric) tile;
|
||||
|
||||
if(buf == null){
|
||||
buf = GLAllocation.createDirectByteBuffer(8*4).asDoubleBuffer();
|
||||
}
|
||||
DoorDecl door = te.doorType;
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslated(x+0.5, y, z+0.5);
|
||||
|
||||
switch(te.getBlockMetadata() - BlockDummyable.offset) {
|
||||
case 2: GL11.glRotatef(0+90, 0F, 1F, 0F); break;
|
||||
case 4: GL11.glRotatef(90+90, 0F, 1F, 0F); break;
|
||||
case 3: GL11.glRotatef(180+90, 0F, 1F, 0F); break;
|
||||
case 5: GL11.glRotatef(270+90, 0F, 1F, 0F); break;
|
||||
}
|
||||
door.doOffsetTransform();
|
||||
|
||||
double[][] clip = door.getClippingPlanes();
|
||||
for(int i = 0; i < clip.length; i ++){
|
||||
GL11.glEnable(GL11.GL_CLIP_PLANE0+i);
|
||||
buf.put(clip[i]);
|
||||
buf.rewind();
|
||||
GL11.glClipPlane(GL11.GL_CLIP_PLANE0+i, buf);
|
||||
}
|
||||
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
|
||||
AnimatedModel animModel = door.getAnimatedModel();
|
||||
if(animModel != null){
|
||||
Animation anim = door.getAnim();
|
||||
bindTexture(door.getTextureForPart(""));
|
||||
long time = System.currentTimeMillis();
|
||||
long startTime = te.state > 1 ? te.animStartTime : time;
|
||||
boolean reverse = te.state == 1 || te.state == 2;
|
||||
AnimationWrapper w = new AnimationWrapper(startTime, anim).onEnd(new EndResult(EndType.STAY));
|
||||
if(reverse)
|
||||
w.reverse();
|
||||
animModel.controller.setAnim(w);
|
||||
animModel.renderAnimated(System.currentTimeMillis());
|
||||
} else {
|
||||
WavefrontObjDisplayList model = door.getModel();
|
||||
|
||||
long ms = System.currentTimeMillis()-te.animStartTime;
|
||||
float openTicks = MathHelper.clamp_float(te.state == 2 || te.state == 0 ? door.timeToOpen()*50-ms : ms, 0, door.timeToOpen()*50)*0.02F;
|
||||
for(Pair<String, Integer> p : model.nameToCallList){
|
||||
if(!door.doesRender(p.getLeft(), false))
|
||||
continue;
|
||||
GL11.glPushMatrix();
|
||||
bindTexture(door.getTextureForPart(p.getLeft()));
|
||||
doPartTransform(door, p.getLeft(), openTicks, false);
|
||||
GL11.glCallList(p.getRight());
|
||||
for(String name : door.getChildren(p.getLeft())){
|
||||
if(!door.doesRender(name, true))
|
||||
continue;
|
||||
GL11.glPushMatrix();
|
||||
bindTexture(door.getTextureForPart(name));
|
||||
doPartTransform(door, name, openTicks, true);
|
||||
model.renderPart(name);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < clip.length; i ++){
|
||||
GL11.glDisable(GL11.GL_CLIP_PLANE0+i);
|
||||
}
|
||||
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glShadeModel(GL11.GL_FLAT);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
public void doPartTransform(DoorDecl door, String name, float openTicks, boolean child){
|
||||
door.getTranslation(name, openTicks, child, tran);
|
||||
door.getOrigin(name, orig);
|
||||
door.getRotation(name, openTicks, rot);
|
||||
GL11.glTranslated(orig[0], orig[1], orig[2]);
|
||||
if(rot[0] != 0)
|
||||
GL11.glRotated(rot[0], 1, 0, 0);
|
||||
if(rot[1] != 0)
|
||||
GL11.glRotated(rot[1], 0, 1, 0);
|
||||
if(rot[2] != 0)
|
||||
GL11.glRotated(rot[2], 0, 0, 1);
|
||||
GL11.glTranslated(-orig[0]+tran[0], -orig[1]+tran[1], -orig[2]+tran[2]);
|
||||
}
|
||||
}
|
||||
219
src/main/java/com/hbm/tileentity/DoorDecl.java
Normal file
219
src/main/java/com/hbm/tileentity/DoorDecl.java
Normal file
@ -0,0 +1,219 @@
|
||||
package com.hbm.tileentity;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.hbm.animloader.AnimatedModel;
|
||||
import com.hbm.animloader.Animation;
|
||||
import com.hbm.main.ResourceManager;
|
||||
import com.hbm.render.WavefrontObjDisplayList;
|
||||
import com.hbm.util.BobMathUtil;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public abstract class DoorDecl {
|
||||
|
||||
public static final DoorDecl TRANSITION_SEAL = new DoorDecl(){
|
||||
|
||||
@Override
|
||||
public String getOpenSoundStart() {
|
||||
return "hbm:door.TransitionSealOpen";
|
||||
};
|
||||
|
||||
@Override
|
||||
public float getSoundVolume(){
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void getTranslation(String partName, float openTicks, boolean child, float[] trans) {
|
||||
if(!partName.equals("base")){
|
||||
set(trans, 0, 3.5F*getNormTime(openTicks), 0);
|
||||
} else {
|
||||
super.getTranslation(partName, openTicks, child, trans);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void doOffsetTransform() {
|
||||
GL11.glTranslated(0, 0, 0.5);
|
||||
};
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public double[][] getClippingPlanes() {
|
||||
return super.getClippingPlanes();
|
||||
};
|
||||
|
||||
@Override
|
||||
public int timeToOpen() {
|
||||
return 480;
|
||||
};
|
||||
|
||||
@Override
|
||||
public int[][] getDoorOpenRanges(){
|
||||
//3 is tall
|
||||
//4 is wide
|
||||
return new int[][]{{-9, 2, 0, 20, 20, 1}};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getDimensions(){
|
||||
return new int[]{23, 0, 0, 0, 13, 12};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getBlockBound(int x, int y, int z, boolean open) {
|
||||
return super.getBlockBound(x, y, z, open);
|
||||
};
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public ResourceLocation getTextureForPart(String partName){
|
||||
return ResourceManager.transition_seal_tex;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public Animation getAnim() {
|
||||
return ResourceManager.transition_seal_anim;
|
||||
};
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public AnimatedModel getAnimatedModel() {
|
||||
return ResourceManager.transition_seal;
|
||||
};
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public WavefrontObjDisplayList getModel(){
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
//Format: x, y, z, tangent amount 1 (how long the door would be if it moved up), tangent amount 2 (door places blocks in this direction), axis (0-x, 1-y, 2-z)
|
||||
public abstract int[][] getDoorOpenRanges();
|
||||
|
||||
public abstract int[] getDimensions();
|
||||
|
||||
public float getDoorRangeOpenTime(int ticks, int idx){
|
||||
return getNormTime(ticks);
|
||||
}
|
||||
|
||||
public int timeToOpen(){
|
||||
return 20;
|
||||
}
|
||||
|
||||
public float getNormTime(float time){
|
||||
return getNormTime(time, 0, timeToOpen());
|
||||
}
|
||||
|
||||
public float getNormTime(float time, float min, float max){
|
||||
return BobMathUtil.remap01_clamp(time, min, max);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public abstract ResourceLocation getTextureForPart(String partName);
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public abstract WavefrontObjDisplayList getModel();
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public AnimatedModel getAnimatedModel(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public Animation getAnim(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void getTranslation(String partName, float openTicks, boolean child, float[] trans){
|
||||
set(trans, 0, 0, 0);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void getRotation(String partName, float openTicks, float[] rot){
|
||||
set(rot, 0, 0, 0);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void getOrigin(String partName, float[] orig){
|
||||
set(orig, 0, 0, 0);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean doesRender(String partName, boolean child){
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final String[] nothing = new String[]{};
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public String[] getChildren(String partName){
|
||||
return nothing;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public double[][] getClippingPlanes(){
|
||||
return new double[][]{};
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void doOffsetTransform(){
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBlockBound(int x, int y, int z, boolean open){
|
||||
return open ? AxisAlignedBB.getBoundingBox(0, 0, 0, 0, 0, 0) : AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1);
|
||||
}
|
||||
|
||||
public boolean isLadder(boolean open){
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getOpenSoundLoop(){
|
||||
return null;
|
||||
}
|
||||
|
||||
//Hack
|
||||
public String getSoundLoop2(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCloseSoundLoop(){
|
||||
return getOpenSoundLoop();
|
||||
}
|
||||
|
||||
public String getOpenSoundStart(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCloseSoundStart(){
|
||||
return getOpenSoundStart();
|
||||
}
|
||||
|
||||
public String getOpenSoundEnd(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCloseSoundEnd(){
|
||||
return getOpenSoundEnd();
|
||||
}
|
||||
|
||||
public float getSoundVolume(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
public float[] set(float[] f, float x, float y, float z){
|
||||
f[0] = x;
|
||||
f[1] = y;
|
||||
f[2] = z;
|
||||
return f;
|
||||
};
|
||||
}
|
||||
365
src/main/java/com/hbm/tileentity/TileEntityDoorGeneric.java
Normal file
365
src/main/java/com/hbm/tileentity/TileEntityDoorGeneric.java
Normal file
@ -0,0 +1,365 @@
|
||||
|
||||
package com.hbm.tileentity;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.hbm.blocks.BlockDummyable;
|
||||
import com.hbm.blocks.generic.BlockDoorGeneric;
|
||||
import com.hbm.interfaces.IAnimatedDoor;
|
||||
import com.hbm.main.MainRegistry;
|
||||
import com.hbm.packet.PacketDispatcher;
|
||||
import com.hbm.packet.TEDoorAnimationPacket;
|
||||
import com.hbm.sound.AudioWrapper;
|
||||
import com.hbm.tileentity.machine.TileEntityLockableBase;
|
||||
import com.hbm.util.Tuple.Triplet;
|
||||
|
||||
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class TileEntityDoorGeneric extends TileEntityLockableBase implements IAnimatedDoor {
|
||||
|
||||
//0: closed, 1: open, 2: closing, 3: opening
|
||||
public byte state = 0;
|
||||
public DoorDecl doorType;
|
||||
public int openTicks = 0;
|
||||
public long animStartTime = 0;
|
||||
public int redstonePower;
|
||||
public boolean shouldUseBB = false;
|
||||
public Set<Triplet<Integer, Integer, Integer>> activatedBlocks = new HashSet<>(4);
|
||||
|
||||
private AudioWrapper audio;
|
||||
private AudioWrapper audio2;
|
||||
|
||||
@Override
|
||||
public void updateEntity(){
|
||||
if(state == 3) {
|
||||
openTicks++;
|
||||
if(openTicks >= doorType.timeToOpen()) {
|
||||
openTicks = doorType.timeToOpen();
|
||||
}
|
||||
} else if(state == 2) {
|
||||
openTicks--;
|
||||
if(openTicks <= 0) {
|
||||
openTicks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(worldObj.isRemote) {
|
||||
|
||||
} else {
|
||||
int[][] ranges = doorType.getDoorOpenRanges();
|
||||
ForgeDirection dir = ForgeDirection.getOrientation(getBlockMetadata() - BlockDummyable.offset);
|
||||
|
||||
if(state == 3) {
|
||||
|
||||
for(int i = 0; i < ranges.length; i++) {
|
||||
|
||||
int[] range = ranges[i];
|
||||
int[] startPos = new int[] {range[0], range[1], range[2]};
|
||||
float time = doorType.getDoorRangeOpenTime(openTicks, i);
|
||||
|
||||
for(int j = 0; j < Math.abs(range[3]); j++) {
|
||||
|
||||
if((float)j / (Math.abs(range[3] - 1)) > time)
|
||||
break;
|
||||
|
||||
for(int k = 0; k < range[4]; k++) {
|
||||
int[] add = new int[] {0, 0, 0};
|
||||
switch(range[5]){
|
||||
case 0: add = new int[] {0, k, (int)Math.signum(range[3]) * j}; break;
|
||||
case 1: add = new int[] {k, (int)Math.signum(range[3]) * j, 0}; break;
|
||||
case 2: add = new int[] {(int)Math.signum(range[3]) * j, k, 0}; break;
|
||||
}
|
||||
/*Rotation r = dir.getBlockRotation();
|
||||
if(dir.toEnumFacing().getAxis() == EnumFacing.Axis.X)
|
||||
r = r.add(Rotation.CLOCKWISE_180);
|
||||
int[] finalPos = new int[]{} startPos.add(add).rotate(r).add(pos);
|
||||
|
||||
if(finalPos.equals(this.pos)) {
|
||||
this.shouldUseBB = true;
|
||||
} else {
|
||||
((BlockDummyable)getBlockType()).makeExtra(worldObj, finalPos.getX(), finalPos.getY(), finalPos.getZ());
|
||||
}_*/ //TODO: whatever just get these errors out of my face
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if(state == 2){
|
||||
|
||||
for(int i = 0; i < ranges.length; i++) {
|
||||
|
||||
int[] range = ranges[i];
|
||||
|
||||
int[] startPos = new int[] {range[0], range[1], range[2]};
|
||||
float time = doorType.getDoorRangeOpenTime(openTicks, i);
|
||||
|
||||
for(int j = Math.abs(range[3])-1; j >= 0; j--) {
|
||||
|
||||
if((float)j / (Math.abs(range[3] - 1)) < time)
|
||||
break;
|
||||
|
||||
for(int k = 0; k < range[4]; k++) {
|
||||
int[] add = new int[] {0, 0, 0};
|
||||
switch(range[5]){
|
||||
case 0: add = new int[] {0, k, (int)Math.signum(range[3]) * j}; break;
|
||||
case 1: add = new int[] {k, (int)Math.signum(range[3]) * j, 0}; break;
|
||||
case 2: add = new int[] {(int)Math.signum(range[3]) * j, k, 0}; break;
|
||||
}
|
||||
|
||||
/*Rotation r = dir.getBlockRotation();
|
||||
if(dir.toEnumFacing().getAxis() == EnumFacing.Axis.X)
|
||||
r = r.add(Rotation.CLOCKWISE_180);
|
||||
BlockPos finalPos = startPos.add(add).rotate(r).add(pos);
|
||||
if(finalPos.equals(this.pos)) {
|
||||
this.shouldUseBB = false;
|
||||
} else {
|
||||
((BlockDummyable)getBlockType()).removeExtra(world, finalPos.getX(), finalPos.getY(), finalPos.getZ());
|
||||
}*/ //TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(state == 3 && openTicks == doorType.timeToOpen()) {
|
||||
state = 1;
|
||||
}
|
||||
if(state == 2 && openTicks == 0) {
|
||||
state = 0;
|
||||
}
|
||||
PacketDispatcher.wrapper.sendToAllAround(new TEDoorAnimationPacket(xCoord, yCoord, zCoord, state, (byte)(shouldUseBB ? 1 : 0)), new TargetPoint(worldObj.provider.dimensionId, xCoord, yCoord, zCoord, 100));
|
||||
|
||||
if(redstonePower == -1 && state == 0){
|
||||
tryToggle(-1);
|
||||
} else if(redstonePower > 0 && state == 1){
|
||||
tryToggle(-1);
|
||||
}
|
||||
if(redstonePower == -1){
|
||||
redstonePower = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload() {
|
||||
if(audio != null) {
|
||||
audio.stopSound();
|
||||
audio = null;
|
||||
}
|
||||
if(audio2 != null) {
|
||||
audio2.stopSound();
|
||||
audio2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
//@Override TODO: figure this one out
|
||||
public void onLoad(){
|
||||
doorType = ((BlockDoorGeneric)this.getBlockType()).type;
|
||||
}
|
||||
|
||||
public boolean tryToggle(EntityPlayer player){
|
||||
if(state == 0 && redstonePower > 0){
|
||||
//Redstone "power locks" doors, just like minecraft iron doors
|
||||
return false;
|
||||
}
|
||||
if(this.state == 0) {
|
||||
if(!worldObj.isRemote && canAccess(player)) {
|
||||
this.state = 3;
|
||||
}
|
||||
return true;
|
||||
} else if(this.state == 1) {
|
||||
if(!worldObj.isRemote && canAccess(player)) {
|
||||
this.state = 2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean tryToggle(int passcode){
|
||||
if(this.isLocked() && passcode != this.lock)
|
||||
return false;
|
||||
if(this.state == 0) {
|
||||
if(!worldObj.isRemote) {
|
||||
this.state = 3;
|
||||
}
|
||||
return true;
|
||||
} else if(this.state == 1) {
|
||||
if(!worldObj.isRemote) {
|
||||
this.state = 2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(){
|
||||
if(state == 0)
|
||||
toggle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(){
|
||||
if(state == 1)
|
||||
toggle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoorState getState(){
|
||||
return DoorState.values()[state];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle(){
|
||||
if(state == 0) {
|
||||
state = 3;
|
||||
} else if(state == 1) {
|
||||
state = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: sound loops
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void handleNewState(byte state){
|
||||
if(this.state != state) {
|
||||
if(this.state == 0 && state == 3){
|
||||
if(audio == null){
|
||||
//audio = MainRegistry.proxy.getLoopedSoundStartStop(world, doorType.getOpenSoundLoop(), doorType.getOpenSoundStart(), doorType.getOpenSoundEnd(), SoundCategory.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), doorType.getSoundVolume(), 1);
|
||||
//audio.startSound();
|
||||
}
|
||||
if(audio2 == null && doorType.getSoundLoop2() != null){
|
||||
//audio2 = MainRegistry.proxy.getLoopedSoundStartStop(world, doorType.getSoundLoop2(), null, null, SoundCategory.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), doorType.getSoundVolume(), 1);
|
||||
//audio2.startSound();
|
||||
}
|
||||
}
|
||||
if(this.state == 1 && state == 2){
|
||||
if(audio == null){
|
||||
//audio = MainRegistry.proxy.getLoopedSoundStartStop(world, doorType.getCloseSoundLoop(), doorType.getCloseSoundStart(), doorType.getCloseSoundEnd(), SoundCategory.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), doorType.getSoundVolume(), 1);
|
||||
//audio.startSound();
|
||||
}
|
||||
if(audio2 == null && doorType.getSoundLoop2() != null){
|
||||
//audio2 = MainRegistry.proxy.getLoopedSoundStartStop(world, doorType.getSoundLoop2(), null, null, SoundCategory.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), doorType.getSoundVolume(), 1);
|
||||
//audio2.startSound();
|
||||
}
|
||||
}
|
||||
if((this.state == 3 && state == 1) || (this.state == 2 && state == 0)){
|
||||
if(audio != null){
|
||||
audio.stopSound();
|
||||
audio = null;
|
||||
}
|
||||
if(audio2 != null){
|
||||
audio2.stopSound();
|
||||
audio2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.state = state;
|
||||
if(state > 1)
|
||||
animStartTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
//Ah yes piggy backing on this packet
|
||||
@Override
|
||||
public void setTextureState(byte tex){
|
||||
if(tex > 0)
|
||||
shouldUseBB = true;
|
||||
else
|
||||
shouldUseBB = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getRenderBoundingBox(){
|
||||
return INFINITE_EXTENT_AABB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxRenderDistanceSquared(){
|
||||
return 65536D;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(NBTTagCompound tag){
|
||||
this.state = tag.getByte("state");
|
||||
this.openTicks = tag.getInteger("openTicks");
|
||||
this.animStartTime = tag.getInteger("animStartTime");
|
||||
this.redstonePower = tag.getInteger("redstoned");
|
||||
this.shouldUseBB = tag.getBoolean("shouldUseBB");
|
||||
NBTTagCompound activatedBlocks = tag.getCompoundTag("activatedBlocks");
|
||||
this.activatedBlocks.clear();
|
||||
for(int i = 0; i < activatedBlocks.func_150296_c().size()/3; i ++){
|
||||
this.activatedBlocks.add(new Triplet(activatedBlocks.getInteger("x"+i), activatedBlocks.getInteger("y"+i), activatedBlocks.getInteger("z"+i)));
|
||||
}
|
||||
super.readFromNBT(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(NBTTagCompound tag){
|
||||
super.writeToNBT(tag);
|
||||
|
||||
tag.setByte("state", state);
|
||||
tag.setInteger("openTicks", openTicks);
|
||||
tag.setLong("animStartTime", animStartTime);
|
||||
tag.setInteger("redstoned", redstonePower);
|
||||
tag.setBoolean("shouldUseBB", shouldUseBB);
|
||||
NBTTagCompound activatedBlocks = new NBTTagCompound();
|
||||
int i = 0;
|
||||
for(Triplet<Integer, Integer, Integer> p : this.activatedBlocks){
|
||||
activatedBlocks.setInteger("x"+i, p.getX());
|
||||
activatedBlocks.setInteger("y"+i, p.getY());
|
||||
activatedBlocks.setInteger("z"+i, p.getZ());
|
||||
i++;
|
||||
}
|
||||
tag.setTag("activatedBlocks", activatedBlocks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
super.validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate(){
|
||||
super.invalidate();
|
||||
if(audio != null) {
|
||||
audio.stopSound();
|
||||
audio = null;
|
||||
}
|
||||
if(audio2 != null) {
|
||||
audio2.stopSound();
|
||||
audio2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateRedstonePower(int x, int y, int z){
|
||||
//Drillgon200: Best I could come up with without having to use dummy tile entities
|
||||
Triplet<Integer, Integer, Integer> pos = new Triplet(x, y, z);
|
||||
boolean powered = worldObj.isBlockIndirectlyGettingPowered(x, y, z);
|
||||
boolean contained = activatedBlocks.contains(pos);
|
||||
if(!contained && powered){
|
||||
activatedBlocks.add(pos);
|
||||
if(redstonePower == -1){
|
||||
redstonePower = 0;
|
||||
}
|
||||
redstonePower++;
|
||||
} else if(contained && !powered){
|
||||
activatedBlocks.remove(pos);
|
||||
redstonePower--;
|
||||
if(redstonePower == 0){
|
||||
redstonePower = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -189,6 +189,8 @@ public class TileMappings {
|
||||
put(TileEntityLoot.class, "tileentity_ntm_loot");
|
||||
put(TileEntityBobble.class, "tileentity_ntm_bobblehead");
|
||||
|
||||
put(TileEntityDoorGeneric.class, "tileentity_ntm_door");
|
||||
|
||||
put(TileEntityProxyInventory.class, "tileentity_proxy_inventory");
|
||||
put(TileEntityProxyEnergy.class, "tileentity_proxy_power");
|
||||
put(TileEntityProxyCombo.class, "tileentity_proxy_combo");
|
||||
|
||||
@ -9,11 +9,24 @@ import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class BobMathUtil {
|
||||
|
||||
public static Vec3 interpVec(Vec3 vec1, Vec3 vec2, float interp) {
|
||||
return Vec3.createVectorHelper(
|
||||
interp(vec1.xCoord, vec2.xCoord, interp),
|
||||
interp(vec1.yCoord, vec2.yCoord, interp),
|
||||
interp(vec1.zCoord, vec2.zCoord, interp)
|
||||
);
|
||||
}
|
||||
|
||||
public static double interp(double x, double y, float interp) {
|
||||
return x + (y - x) * interp;
|
||||
}
|
||||
|
||||
public static double getAngleFrom2DVecs(double x1, double z1, double x2, double z2) {
|
||||
|
||||
double upper = x1 * x2 + z1 * z2;
|
||||
@ -46,6 +59,14 @@ public class BobMathUtil {
|
||||
return ((num - min1) / (max1 - min1)) * (max2 - min2) + min2;
|
||||
}
|
||||
|
||||
public static float remap01(float num, float min1, float max1){
|
||||
return (num - min1) / (max1 - min1);
|
||||
}
|
||||
|
||||
public static float remap01_clamp(float num, float min1, float max1){
|
||||
return MathHelper.clamp_float((num - min1) / (max1 - min1), 0, 1);
|
||||
}
|
||||
|
||||
public static ForgeDirection[] getShuffledDirs() {
|
||||
|
||||
ForgeDirection[] dirs = new ForgeDirection[6];
|
||||
|
||||
2044
src/main/resources/assets/hbm/models/doors/seal.dae
Normal file
2044
src/main/resources/assets/hbm/models/doors/seal.dae
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 259 KiB |
Loading…
x
Reference in New Issue
Block a user