/** Runes of Wizardry Mod for Minecraft
* Licensed under the GNU GPL version 3
*
* this file was created by Xilef11 on 2016-01-09
*/
package com.zpig333.runesofwizardry.tileentity;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagIntArray;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import com.zpig333.runesofwizardry.api.DustRegistry;
import com.zpig333.runesofwizardry.api.IRune;
import com.zpig333.runesofwizardry.api.RuneEntity;
import com.zpig333.runesofwizardry.core.WizardryLogger;
/** This TileEntity replaces a TileEntityDustPlaced when a rune is formed.
* @author Xilef11
*
*/
public class TileEntityDustActive extends TileEntityDustPlaced implements ITickable {
private long ticksExisted=0;
public StarData stardata = null;
public BeamData beamdata=null;
public TileEntityDustActive() {
super();
}
/**
* Returns the number of ticks since this was created
* @return the number of times the update() method was called on this.
*/
public long ticksExisted(){
return ticksExisted;
}
/* (non-Javadoc)
* @see com.zpig333.runesofwizardry.tileentity.TileEntityDustPlaced#getMaxRenderDistanceSquared()
*/
@Override
public double getMaxRenderDistanceSquared() {
if((this.beamdata!=null && this.beamdata.doRender)||(this.stardata!=null && this.stardata.doRender)){
return 65536.0D;
}else{
return super.getMaxRenderDistanceSquared();
}
}
/* (non-Javadoc)
* @see net.minecraft.tileentity.TileEntity#getRenderBoundingBox()
*/
@Override
public AxisAlignedBB getRenderBoundingBox() {
if((this.stardata!=null && this.stardata.doRender)||(this.beamdata!=null && this.beamdata.doRender)){
return INFINITE_EXTENT_AABB;
}else{
return super.getRenderBoundingBox();
}
}
/* (non-Javadoc)
* @see net.minecraft.server.gui.IUpdatePlayerListBox#update()
*/
@Override
public void update() {
if(!initialised)init();
ticksExisted++;
if(rune!=null)rune.update();
}
public void setupStar(int inner, int outer, float size, float sizeY,Vec3d offset){
stardata = new StarData(inner, outer, size, sizeY, offset);
}
public void setupStar(int inner, int outer, float size, float sizeY){
stardata = new StarData(inner, outer, size, sizeY);
}
public void setupStar(int inner, int outer){
setupStar(inner,outer,1,1);
}
public void setupBeam(int color, BeamType type,Vec3d offset){
beamdata = new BeamData(color,type,offset);
}
public void setupBeam(int color, BeamType type){
beamdata = new BeamData(color,type);
}
public void setDrawStar(boolean value){
if(stardata!=null)stardata.doRender=value;
}
public void setDrawBeam(boolean value){
if(beamdata!=null)beamdata.doRender=value;
}
/* (non-Javadoc)
* @see com.zpig333.runesofwizardry.tileentity.TileEntityDustPlaced#readFromNBT(net.minecraft.nbt.NBTTagCompound)
*/
@Override
public void readFromNBT(NBTTagCompound tagCompound) {
super.readFromNBT(tagCompound);
ticksExisted = tagCompound.getLong("ticksExisted");
String runeID = tagCompound.getString("runeID");
//read the blockpos
Set<BlockPos> posSet = new LinkedHashSet<BlockPos>();
NBTTagList positions = tagCompound.getTagList("dustPositions", 11);//11 is int array
for(int i=0;i<positions.tagCount();i++){
int[] p = positions.getIntArrayAt(i);
posSet.add(new BlockPos(p[0], p[1], p[2]));
}
//read the Rune's ItemStacks
NBTTagList tagList = tagCompound.getTagList("Pattern",10);
List<ArrayElement> items = new LinkedList<ArrayElement>();
int maxRow=0,maxCol=0;
for (int i = 0; i < tagList.tagCount(); i++) {
NBTTagCompound tag = tagList.getCompoundTagAt(i);
int r = tag.getInteger("Row");
int c = tag.getInteger("Col");
ItemStack s = new ItemStack(tag);
items.add(new ArrayElement(r, c, s));
if(r>maxRow)maxRow=r;
if(c>maxCol)maxCol=c;
}
//make sure its the right size
int modR = maxRow%TileEntityDustPlaced.ROWS;
if(modR!=0)maxRow+=(TileEntityDustPlaced.ROWS-modR);
int modC = maxCol%TileEntityDustPlaced.COLS;
if(modC!=0)maxCol+=(TileEntityDustPlaced.COLS-modC);
ItemStack[][] stacks = new ItemStack[maxRow+1][maxCol+1];
for(ArrayElement a:items){
stacks[a.row][a.col]=a.stack;
}
EnumFacing facing = EnumFacing.byName(tagCompound.getString("Facing"));
boolean renders = tagCompound.getBoolean("renderActive");
//re-create the rune
IRune rune = DustRegistry.getRuneByID(runeID);
if(rune==null){
WizardryLogger.logError("Active Dust at "+getPos()+" loaded invalid runeID "+runeID+" from NBT");
this.rune=null;//this should make the rune do nothing.
}else{
RuneEntity entity = rune.createRune(stacks,facing, posSet, this);
entity.renderActive=renders;
this.rune=entity;
//init should get called on the first tick to set up the other dust blocks
initialised=false;
this.rune.readFromNBT(tagCompound);
}
if(tagCompound.hasKey("star")){
stardata = new StarData();
stardata.readNBT(tagCompound.getCompoundTag("star"));
}
if(tagCompound.hasKey("beam")){
beamdata = new BeamData();
beamdata.readNBT(tagCompound.getCompoundTag("beam"));
}
}
private boolean initialised=false;
private void init(){
if(initialised ||rune==null|| world==null)return;
for(BlockPos p : rune.dustPositions){
TileEntity te = world.getTileEntity(p);
if(te instanceof TileEntityDustPlaced){
((TileEntityDustPlaced)te).setRune(rune);
}else{
WizardryLogger.logError("TileEntity at pos: "+p+" wasn't placed dust! (TEDustActive#init)");
}
}
rune.isAnyBlockPowered();
initialised=true;
}
/* (non-Javadoc)
* @see com.zpig333.runesofwizardry.tileentity.TileEntityDustPlaced#writeToNBT(net.minecraft.nbt.NBTTagCompound)
*/
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
super.writeToNBT(tagCompound);
if(rune!=null){
rune.writeToNBT(tagCompound);
tagCompound.setString("runeID", DustRegistry.getRuneID(rune.creator));
//write the rune's blockpos set
NBTTagList positions = new NBTTagList();
for(BlockPos p: rune.dustPositions){
NBTTagIntArray current = new NBTTagIntArray(new int[]{p.getX(),p.getY(),p.getZ()});
positions.appendTag(current);
}
tagCompound.setTag("dustPositions",positions);
//write the rune's ItemStacks
NBTTagList itemList = new NBTTagList();
for (int r = 0; r < rune.placedPattern.length; r++) {
for(int c=0;c<rune.placedPattern[r].length;c++){
ItemStack stack = rune.placedPattern[r][c];
NBTTagCompound tag = new NBTTagCompound();
if (!stack.isEmpty()) {
stack.writeToNBT(tag);
tag.setInteger("Row", r);
tag.setInteger("Col", c);
itemList.appendTag(tag);
}
}
}
tagCompound.setTag("Pattern", itemList);
tagCompound.setTag("Facing", new NBTTagString(rune.face.getName()));
tagCompound.setBoolean("renderActive", rune.renderActive);
}
tagCompound.setLong("ticksExisted", ticksExisted);
if(stardata!=null)tagCompound.setTag("star", stardata.writeNBT(new NBTTagCompound()));
if(beamdata!=null)tagCompound.setTag("beam", beamdata.writeNBT(new NBTTagCompound()));
return tagCompound;
}
//
private class ArrayElement{
private int row;
private int col;
private ItemStack stack;
private ArrayElement(int r, int c, ItemStack s){
row=r;
col=c;
stack=s;
}
}
/** This class holds the data and some utility methods to configure rendering of the star**/
public static class StarData{
public int innercolor, outercolor;
public boolean doRender;
public float scale, yscale;
//offset from the active TE
public Vec3d offset;
private StarData(){
//empty constructor for when we want to read from NBT
doRender=false;
}
public StarData(int inner, int outer, float size, float sizeY,Vec3d offset){
innercolor=inner;
outercolor = outer;
scale=size;
yscale=sizeY;
doRender=false;
this.offset=offset;
}
public StarData(int inner, int outer, float size, float sizeY){
this(inner,outer,size,sizeY,new Vec3d(0,0,0));
}
public NBTTagCompound writeNBT(NBTTagCompound tag){
tag.setInteger("starInner", innercolor);
tag.setInteger("starOuter", outercolor);
tag.setFloat("starScale", scale);
tag.setFloat("starScaleY", yscale);
tag.setBoolean("starRender", doRender);
tag.setDouble("starOffsetX", offset.xCoord);
tag.setDouble("starOffsetY", offset.yCoord);
tag.setDouble("starOffsetZ", offset.zCoord);
return tag;
}
public void readNBT(NBTTagCompound tag){
innercolor = tag.getInteger("starInner");
outercolor = tag.getInteger("starOuter");
scale = tag.getFloat("starScale");
yscale = tag.getFloat("starScaleY");
doRender=tag.getBoolean("starRender");
double dx = tag.getDouble("starOffsetX"),
dy = tag.getDouble("starOffsetY"),
dz = tag.getDouble("starOffsetZ");
offset=new Vec3d(dx,dy,dz);
}
}
public static enum BeamType {BEACON, SPIRAL, RINGS,CUSTOM};
/** This class holds the data and some utility methods to configure rendering of the beam**/
public static class BeamData{
public int color;
public boolean doRender;
public BeamType type;
public Vec3d offset;
/** if false, the beam will "vibrate" instead of rotating like the normal beacon**/
public boolean doesRotate;
public int height;
public double beamRadius,glowRadius;
/** If the beam type is CUSTOM, you must set this field manually**/
public ResourceLocation customTexture;
/** If the beam type is CUSTOM, you must set this field manually**/
public double customTexScale;
private BeamData(){
doRender=false;
}
public BeamData(int color, BeamType type,Vec3d offset){
this.color=color;
this.type=type;
doRender=false;
this.offset=offset;
this.doesRotate=true;
this.height=128;
this.beamRadius=0.2;
this.glowRadius=0.25;
}
public BeamData(int color, BeamType type){
this(color,type,new Vec3d(0,0,0));
}
public NBTTagCompound writeNBT(NBTTagCompound tag){
tag.setInteger("beamColor", color);
tag.setString("beamType", type.name());
tag.setBoolean("beamRender", doRender);
tag.setBoolean("beamRotate", doesRotate);
tag.setInteger("beamHeight", height);
tag.setDouble("beamOffsetX", offset.xCoord);
tag.setDouble("beamOffsetY", offset.yCoord);
tag.setDouble("beamOffsetZ", offset.zCoord);
tag.setDouble("beamRad", beamRadius);
tag.setDouble("beamGlowRad", glowRadius);
if(type==BeamType.CUSTOM){
tag.setString("beamCustomTex", customTexture!=null?customTexture.toString():null);
tag.setDouble("beamTexScale",customTexScale);
}
return tag;
}
public void readNBT(NBTTagCompound tag){
color = tag.getInteger("beamColor");
doRender=tag.getBoolean("beamRender");
doesRotate = tag.getBoolean("beamRotate");
height = tag.getInteger("beamHeight");
type = BeamType.valueOf(tag.getString("beamType"));
offset = new Vec3d(tag.getDouble("beamOffsetX"),tag.getDouble("beamOffsetY"),tag.getDouble("beamOffsetZ"));
beamRadius=tag.getDouble("beamRad");
glowRadius=tag.getDouble("beamGlowRad");
if(type==BeamType.CUSTOM){
customTexture=new ResourceLocation(tag.getString("beamCustomTex"));
customTexScale=tag.getDouble("beamTexScale");
}
}
}
}