package makeo.gadomancy.common.blocks.tiles; import cpw.mods.fml.common.ObfuscationReflectionHelper; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import makeo.gadomancy.api.ClickBehavior; import makeo.gadomancy.common.Gadomancy; import makeo.gadomancy.common.entities.fake.AdvancedFakePlayer; import makeo.gadomancy.common.network.PacketHandler; import makeo.gadomancy.common.network.packets.PacketStartAnimation; import makeo.gadomancy.common.registration.RegisteredBlocks; import makeo.gadomancy.common.utils.NBTHelper; import net.minecraft.client.Minecraft; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ISidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.ItemInWorldManager; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.storage.IPlayerFileData; import net.minecraft.world.storage.SaveHandler; import net.minecraftforge.common.util.ForgeDirection; import thaumcraft.api.aspects.Aspect; import thaumcraft.api.aspects.AspectList; import thaumcraft.common.Thaumcraft; import thaumcraft.common.config.ConfigItems; import thaumcraft.common.items.wands.ItemWandCasting; import thaumcraft.common.items.wands.foci.ItemFocusPrimal; import thaumcraft.common.lib.research.ResearchManager; import java.io.File; import java.util.ArrayList; import java.util.Random; import java.util.UUID; /** * This class is part of the Gadomancy Mod * Gadomancy is Open Source and distributed under the * GNU LESSER GENERAL PUBLIC LICENSE * for more read the LICENSE file * * Created by makeo @ 05.10.2015 22:32 */ public class TileInfusionClaw extends SynchronizedTileEntity implements IInventory, ISidedInventory { private static final UUID FAKE_UUID = UUID.fromString("b23c8c3f-d7bd-49b3-970a-8e86728bab82"); private static final Random RANDOM = new Random(); private static final ItemWandCasting WAND_ITEM = (ItemWandCasting) ConfigItems.itemWandCasting; private static final ItemFocusPrimal WAND_FOCUS = (ItemFocusPrimal) ConfigItems.itemFocusPrimal; private static final AspectList MAX_WAND_COST = new AspectList().add(Aspect.WATER, 250).add(Aspect.AIR, 250).add(Aspect.EARTH, 250).add(Aspect.FIRE, 250).add(Aspect.ORDER, 250).add(Aspect.ENTROPY, 250); private ItemInWorldManager im = null; private Boolean redstoneState = null; private int count = 0; private String player = null; private ItemStack wandStack = null; private boolean isLocked = false; private int cooldown; @SideOnly(Side.CLIENT) public float lastRenderTick; /** * 0-3: heightMov sides * 4-7: widthMov sides * 8: sides exp. speed * 9: center exp. speed * 10: rotation center * 11: primal orb offset */ @SideOnly(Side.CLIENT) public float[] animationStates; public TileInfusionClaw() { if(Gadomancy.proxy.getSide() == Side.CLIENT) { animationStates = new float[12]; EntityLivingBase entity = Minecraft.getMinecraft().renderViewEntity; lastRenderTick = entity == null ? 0 : entity.ticksExisted; } } @Override public void updateEntity() { World world = getWorldObj(); if(!world.isRemote) { if(redstoneState == null) { redstoneState = world.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord); } if(cooldown > 0) { cooldown--; if(cooldown == (int)(7.5f*20)) { performClickBlock(); } } if(count > 20) { count = 0; if(yCoord > 0) { //Comparator... world.notifyBlockChange(xCoord, yCoord, zCoord, getBlockType()); } } count++; } } @Override public void readCustomNBT(NBTTagCompound compound) { if(compound.hasKey("player")) { player = compound.getString("player"); } wandStack = NBTHelper.getStack(compound, "wandStack"); isLocked = compound.getBoolean("isLocked"); } @Override public void writeCustomNBT(NBTTagCompound compound) { if(hasOwner()) { compound.setString("player", player); } if(wandStack != null) { NBTHelper.setStack(compound, "wandStack", wandStack); } compound.setBoolean("isLocked", isLocked); } private void markForUpdate() { markDirty(); getWorldObj().markBlockForUpdate(xCoord, yCoord, zCoord); } public void updateRedstone(boolean state) { if(redstoneState != null && state && !redstoneState) { startClickBlock(); } redstoneState = state; } public boolean isLocked() { return isLocked; } public void setIsLocked(boolean isLocked) { this.isLocked = isLocked; if(!getWorldObj().isRemote) { markForUpdate(); } } public boolean setOwner(EntityPlayer player) { World world = getWorldObj(); if(!world.isRemote && isValidOwner(player)) { this.player = player.getCommandSenderName(); markForUpdate(); return true; } return false; } public boolean isValidOwner(EntityPlayer player) { return !AdvancedFakePlayer.isFakePlayer(player); } private ArrayList<String> research = null; private void loadResearch(EntityPlayer fakePlayer) { boolean online = false; for(String username : MinecraftServer.getServer().getAllUsernames()) { if(username.equals(player)) { online = true; break; } } if(online) { this.research = ResearchManager.getResearchForPlayer(player); } else { if(research == null) { Thaumcraft.proxy.getCompletedResearch().put(fakePlayer.getCommandSenderName(), new ArrayList<String>()); IPlayerFileData playerNBTManagerObj = MinecraftServer.getServer().worldServerForDimension(0).getSaveHandler().getSaveHandler(); SaveHandler sh = (SaveHandler)playerNBTManagerObj; File dir = ObfuscationReflectionHelper.getPrivateValue(SaveHandler.class, sh, "playersDirectory", "field_75771_c"); File file1 = new File(dir, player + ".thaum"); File file2 = new File(dir, player + ".thaumbak"); ResearchManager.loadPlayerData(fakePlayer, file1, file2, false); this.research = ResearchManager.getResearchForPlayerSafe(fakePlayer.getCommandSenderName()); } } Thaumcraft.proxy.getCompletedResearch().put(fakePlayer.getCommandSenderName(), research == null ? new ArrayList<String>() : research); } public String getOwner() { return player; } public boolean hasOwner() { return player != null; } private void startClickBlock() { if(!isRunning()) { ClickBehavior behavior = getClickBehavior(getWorldObj(), xCoord, yCoord-1, zCoord); if(behavior != null && (!behavior.hasVisCost() || hasSufficientVis())) { startRunning(); } } } private void performClickBlock() { World world = getWorldObj(); int x = xCoord; int y = yCoord - 1; int z = zCoord; ClickBehavior behavior = getClickBehavior(world, x, y, z); if(behavior != null) { AdvancedFakePlayer fakePlayer = new AdvancedFakePlayer((WorldServer) world, FAKE_UUID); loadResearch(fakePlayer); if(behavior.hasVisCost()) { if(hasSufficientVis()) { consumeVis(fakePlayer); } else { return; } } if(im == null) { im = new ItemInWorldManager(world); } else { im.setWorld((WorldServer) world); } fakePlayer.setHeldItem(wandStack); this.im.activateBlockOrUseItem(fakePlayer, world, wandStack, x, y, z, ForgeDirection.UP.ordinal(), 0.5F, 0.5F, 0.5F); addInstability(behavior); } } private ClickBehavior getClickBehavior(World world, int x, int y, int z) { if(y >= 0 && !world.isRemote && world instanceof WorldServer && hasOwner() && !world.isAirBlock(x, y, z) && wandStack != null && wandStack.stackSize > 0) { return RegisteredBlocks.getClawClickBehavior(world, x, y, z); } return null; } public boolean isRunning() { if(getWorldObj().isRemote) { return animationStates[8] + animationStates[9] + animationStates[11] != 0; } return cooldown > 0; } private void startRunning() { PacketHandler.INSTANCE.sendToAllAround(new PacketStartAnimation(PacketStartAnimation.ID_INFUSIONCLAW, xCoord, yCoord, zCoord), new NetworkRegistry.TargetPoint(getWorldObj().provider.dimensionId, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, 48)); cooldown = 22*20; } private void addInstability(ClickBehavior behavior) { int instability = 23; int maxVis = WAND_ITEM.getMaxVis(wandStack); instability += maxVis < 100 ? 3 : -2; instability -= Math.floor((maxVis > 300 ? 300 : maxVis) / 300f * 10f); instability -= WAND_ITEM.isStaff(wandStack) ? 6 : -1; instability += Math.floor((WAND_ITEM.getCap(wandStack).getBaseCostModifier() - 0.4) * 3); instability -= WAND_ITEM.getCap(wandStack) == ConfigItems.WAND_CAP_VOID ? 3 : 0; instability -= WAND_ITEM.getRod(wandStack) == ConfigItems.STAFF_ROD_PRIMAL ? 6 : 0; behavior.addInstability(instability); } private boolean hasSufficientVis() { return wandStack != null && wandStack.stackSize > 0 && WAND_ITEM.consumeAllVis(wandStack, null, MAX_WAND_COST, false, false); } private void consumeVis(EntityPlayer player) { WAND_ITEM.consumeAllVis(wandStack, player, WAND_FOCUS.getVisCost(wandStack), true, false); markForUpdate(); } @Override public int getSizeInventory() { return 1; } @Override public ItemStack getStackInSlot(int slot) { return wandStack; } @Override public ItemStack decrStackSize(int slot, int amount) { if(isRunning()) { return null; } if(amount > 0) { ItemStack result = wandStack.copy(); wandStack = null; markForUpdate(); return result; } return null; } @Override public ItemStack getStackInSlotOnClosing(int p_70304_1_) { return null; } @Override public void setInventorySlotContents(int slot, ItemStack stack) { wandStack = stack; markForUpdate(); } @Override public String getInventoryName() { return null; } @Override public boolean hasCustomInventoryName() { return false; } @Override public int getInventoryStackLimit() { return 1; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return true; } @Override public void openInventory() { } @Override public void closeInventory() { } @Override public boolean isItemValidForSlot(int slot, ItemStack stack) { if(isRunning()) { return false; } if(stack.getItem() == WAND_ITEM) { return !WAND_ITEM.isSceptre(stack) && WAND_ITEM.getFocus(stack) == null; } return false; } @Override public int[] getAccessibleSlotsFromSide(int side) { return new int[]{0}; } @Override public boolean canInsertItem(int slot, ItemStack stack, int side) { return !isRunning() && side > 0 && side < 6; } @Override public boolean canExtractItem(int slot, ItemStack stack, int side) { return (!isLocked() || !hasSufficientVis()) && canInsertItem(slot, stack, side); } }