/* This file is part of Project-Zed. Project-Zed is free software: you can redistribute it and/or modify it under the terms of the GNU General Public * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Project-Zed is * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along * with Project-Zed. If not, see <http://www.gnu.org/licenses/> */ package com.projectzed.mod.tileentity.machine; import com.hockeyhurd.hcorelib.api.math.Rect; import com.hockeyhurd.hcorelib.api.math.Vector2; import com.hockeyhurd.hcorelib.api.math.Vector3; import com.hockeyhurd.hcorelib.api.math.VectorHelper; import com.hockeyhurd.hcorelib.api.util.ChunkHelper; import com.projectzed.api.tileentity.AbstractTileEntityGeneric; import com.projectzed.api.util.IChunkLoadable; import com.projectzed.mod.ProjectZed; import com.projectzed.mod.handler.PacketHandler; import com.projectzed.mod.handler.message.MessageTileEntityLoader; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.ForgeChunkManager; import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.ForgeChunkManager.Type; /** * Class containing tileentity code for industrialLoader. * * @author hockeyhurd * @version Apr 19, 2015 */ public class TileEntityIndustrialLoader extends AbstractTileEntityGeneric implements IChunkLoadable { private Ticket heldChunk; public static final byte MIN_RADII = 1; public static final byte MAX_RADII = 3; // temp lowered from 6 to 3 until decided how to overcome forge chunk loading limitations. private byte radii = 1; private byte lastRadii = 1; private boolean markedForReinitChunksLoaded = false; private Chunk[] chunksLoaded; private Rect<Integer> chunkBoundary; public TileEntityIndustrialLoader() { super(); setCustomName("industrialLoader"); chunkBoundary = new Rect<Integer>(0, 0, 0, 0); } @Override public int getSizeInventory() { return 0; } @Override public int getInventoryStackLimit() { return 0; } @Override protected void initContentsArray() { } @Override protected void initSlotsArray() { } @Override public void setCustomName(String name) { this.customName = name; } @Override public boolean isItemValidForSlot(int slot, ItemStack stack) { return false; } @Override public int[] getSlotsForFace(EnumFacing side) { return new int[0]; } @Override public boolean canInsertItem(int slot, ItemStack stack, EnumFacing side) { return false; } @Override public boolean canExtractItem(int slot, ItemStack stack, EnumFacing side) { return false; } @Override public int getField(int id) { return 0; } @Override public void setField(int id, int value) { } @Override public int getFieldCount() { return 0; } @Override public void readNBT(NBTTagCompound comp) { super.readNBT(comp); this.radii = comp.getByte("ChunkRadii"); this.lastRadii = this.radii; } @Override public void saveNBT(NBTTagCompound comp) { super.saveNBT(comp); comp.setByte("ChunkRadii", this.radii); // unloadChunk(); } /*@Override public Packet getDescriptionPacket() { return PacketHandler.INSTANCE.getPacketFrom(new MessageTileEntityLoader(this)); }*/ @Override public NBTTagCompound getUpdateTag() { PacketHandler.INSTANCE.getPacketFrom(new MessageTileEntityLoader(this)); final NBTTagCompound comp = getTileData(); saveNBT(comp); return comp; } @Override public void onDataPacket(NetworkManager manager, SPacketUpdateTileEntity packet) { PacketHandler.INSTANCE.getPacketFrom(new MessageTileEntityLoader(this)); } /** * Gets the radii of the chunks loaded. * * @return Byte radii. */ public byte getRadii() { return radii; } /** * Sets the radii of the chunk loader. * * @param radii Byte radii to set. */ public void setRadii(byte radii) { this.radii = radii; } @Override public void update() { super.update(); if (!worldObj.isRemote && worldObj.getTotalWorldTime() % 20L == 0) { if (chunksLoaded != null && markedForReinitChunksLoaded) reinitChunksLoaded(); PacketHandler.INSTANCE.sendToAll(new MessageTileEntityLoader(this, getRadii())); if (this.lastRadii != this.radii) { loadChunk(null); this.lastRadii = this.radii; } } } // DO CHUNK LOADING HERE: @Override public void invalidate() { // forceChunkLoading(null); unloadChunk(); super.invalidate(); } @Override public void validate() { // forceChunkLoading(null); loadChunk(null); super.validate(); } @Override public void loadChunk(Ticket ticket) { if (ticket != null) { if (this.heldChunk != null) unloadChunk(); this.heldChunk = ticket; Vector2<Integer> vec = new Vector2<Integer>(pos.getX() >> 4, pos.getZ() >> 4); chunkBoundary.min.x = -this.radii + 1; chunkBoundary.min.y = -this.radii + 1; chunkBoundary.max.x = (int) this.radii; chunkBoundary.max.y = (int) this.radii; Vector2<Integer> current = new Vector2<Integer>(); for (int x = -this.radii + 1; x < this.radii; x++) { for (int y = -this.radii + 1; y < this.radii; y++) { current.x = vec.x + x; current.y = vec.y + y; ForgeChunkManager.forceChunk(this.heldChunk, new ChunkPos(vec.x + x, vec.y + y)); } } } else { if (this.heldChunk != null) unloadChunk(); Ticket newTicket = ForgeChunkManager.requestTicket(ProjectZed.instance, this.worldObj, Type.NORMAL); newTicket.getModData().setInteger("xCoord", pos.getX()); newTicket.getModData().setInteger("yCoord", pos.getY()); newTicket.getModData().setInteger("zCoord", pos.getZ()); this.heldChunk = newTicket; Vector2<Integer> vec = new Vector2<Integer>(pos.getX() >> 4, pos.getZ() >> 4); chunkBoundary.min.x = -this.radii + 1; chunkBoundary.min.y = -this.radii + 1; chunkBoundary.max.x = (int) this.radii; chunkBoundary.max.y = (int) this.radii; Vector2<Integer> current = new Vector2<Integer>(); for (int x = -this.radii + 1; x < this.radii; x++) { for (int y = -this.radii + 1; y < this.radii; y++) { current.x = vec.x + x; current.y = vec.y + y; ForgeChunkManager.forceChunk(this.heldChunk, new ChunkPos(current.x, current.y)); } } } } private int getCalculatedArrayLength() { return (radii + (radii - 1)) * (radii + (radii - 1)); } private void reinitChunksLoaded() { if (!markedForReinitChunksLoaded || chunkBoundary == null) return; final int calculatedSize = getCalculatedArrayLength(); if (chunksLoaded == null || chunksLoaded.length != calculatedSize) chunksLoaded = new Chunk[calculatedSize]; Vector2<Integer> vec = new Vector2<Integer>(pos.getX() >> 4, pos.getZ() >> 4); Vector2<Integer> current = new Vector2<Integer>(); int counter = 0; for (int x = -radii + 1; x < radii; x++) { for (int z = -radii + 1; z < radii; z++) { current.x = vec.x + x; current.y = vec.y + z; chunksLoaded[counter++] = ChunkHelper.getChunkFromChunkCoordinates(worldObj, current); } } markedForReinitChunksLoaded = false; } /* * (non-Javadoc) * @see com.projectzed.api.util.IChunkLoadable#unloadChunk() */ @Override public void unloadChunk() { if (this.heldChunk != null) { ForgeChunkManager.releaseTicket(this.heldChunk); this.heldChunk = null; chunksLoaded = null; } } @Override public Chunk[] getChunksLoaded() { if (chunksLoaded == null || chunksLoaded.length != getCalculatedArrayLength()) { markedForReinitChunksLoaded = true; reinitChunksLoaded(); } return chunksLoaded; } @Override public Vector3<Integer> worldVec() { return VectorHelper.toVector3i(pos); } @Override public Rect<Integer> loadedChunkBoundary() { return chunkBoundary; } @Override public World getWorld() { return worldObj; } }