Created
February 7, 2017 07:18
-
-
Save Daomephsta/b0cd6c20384cc6ca5e13e5407e928378 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.einsteinsci.betterbeginnings.tileentity; | |
import java.util.*; | |
import javax.annotation.Nullable; | |
import com.google.common.collect.Lists; | |
import net.einsteinsci.betterbeginnings.config.BBConfig; | |
import net.einsteinsci.betterbeginnings.inventory.ItemHandlerInfusionRepair; | |
import net.einsteinsci.betterbeginnings.register.RegisterItems; | |
import net.einsteinsci.betterbeginnings.register.recipe.elements.RecipeElement; | |
import net.einsteinsci.betterbeginnings.util.*; | |
import net.einsteinsci.betterbeginnings.util.Util; | |
import net.minecraft.block.state.IBlockState; | |
import net.minecraft.enchantment.Enchantment; | |
import net.minecraft.enchantment.EnchantmentData; | |
import net.minecraft.entity.item.EntityItem; | |
import net.minecraft.entity.player.EntityPlayer; | |
import net.minecraft.init.Items; | |
import net.minecraft.item.ItemStack; | |
import net.minecraft.nbt.NBTTagCompound; | |
import net.minecraft.nbt.NBTTagList; | |
import net.minecraft.network.NetworkManager; | |
import net.minecraft.network.play.server.SPacketUpdateTileEntity; | |
import net.minecraft.tileentity.TileEntity; | |
import net.minecraft.util.*; | |
import net.minecraft.util.math.AxisAlignedBB; | |
import net.minecraft.util.math.BlockPos; | |
import net.minecraft.world.IWorldNameable; | |
import net.minecraft.world.World; | |
import net.minecraftforge.common.capabilities.Capability; | |
import net.minecraftforge.items.*; | |
public class TileEntityInfusionRepair extends TileEntity implements ITickable, IWorldNameable | |
{ | |
private static final String INV_TAG = "Items"; | |
private static final String MODE = "Mode"; | |
private static final String CUSTOM_NAME = "CustomName"; | |
private static final String HEALTH_TAKEN = "HealthTaken"; | |
private static final String LEVELS_NEEDED = "LevelsNeeded"; | |
private static final String LEVELS_TAKEN = "LevelsTaken"; | |
private static final int SLOT_ENCH_ITEM = 0; | |
private static final Random rand = new Random(); | |
private IItemHandlerModifiable mainHandler; | |
private Stack<RecipeElement> pendingIngredients = new Stack<RecipeElement>(); | |
private Mode mode = Mode.NONE; | |
private float healthTaken; | |
private int xpLevelsTaken; | |
private int xpLevelsNeeded; | |
private AxisAlignedBB searchBox; | |
private String tileName; | |
public TileEntityInfusionRepair() | |
{ | |
this.mainHandler = new ItemHandlerInfusionRepair(10); | |
} | |
public void activate(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, @Nullable ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) | |
{ | |
if(Prep1_11.isEmpty(heldItem) || hasEnchItem()) return; | |
if(heldItem.getItem() == RegisterItems.cloth) | |
{ | |
mode = Mode.DIFFUSION; | |
} | |
else if(heldItem.isItemEnchanted()) | |
{ | |
mode = Mode.REPAIR; | |
pendingIngredients.clear(); | |
pendingIngredients.addAll(InfusionRepairUtil.getRequiredStacks(heldItem)); | |
xpLevelsNeeded = InfusionRepairUtil.getTakenLevels(heldItem); | |
} | |
else | |
return; | |
ItemStack newStack = heldItem.copy(); | |
newStack.stackSize = 1; | |
mainHandler.setStackInSlot(heldItem.isItemEnchanted() ? SLOT_ENCH_ITEM : 1, newStack); | |
heldItem.stackSize--; | |
} | |
@Override | |
public void update() | |
{ | |
switch (mode) | |
{ | |
case NONE: | |
break; | |
case DIFFUSION: | |
absorbItems(); | |
diffuse(); | |
break; | |
case REPAIR: | |
absorbItems(); | |
repair(); | |
break; | |
default: | |
return; | |
} | |
} | |
private void absorbItems() | |
{ | |
List<EntityItem> items = worldObj.getEntitiesWithinAABB(EntityItem.class, searchBox); | |
IBlockState state = worldObj.getBlockState(pos); | |
for (EntityItem entityItem : items) | |
{ | |
if(tryAbsorbDroppedItem(entityItem, state)) | |
{ | |
markDirty(); | |
worldObj.notifyBlockUpdate(pos, state, state, 8); | |
} | |
if(entityItem.getEntityItem().stackSize == 0) | |
entityItem.setDead(); | |
} | |
} | |
private boolean tryAbsorbDroppedItem(EntityItem item, IBlockState state) | |
{ | |
ItemStack newStack = Prep1_11.getEmptyStack(); | |
ItemStack stack = item.getEntityItem(); | |
switch(mode) | |
{ | |
case DIFFUSION: | |
if(isIngredientPresent(stack)) return false; | |
if(stack.getItem() == Items.BOOK || stack.isItemEnchanted()) | |
{ | |
newStack = stack.copy(); | |
newStack.stackSize = 1; | |
if(!worldObj.isRemote) stack.stackSize--; | |
} | |
break; | |
case REPAIR: | |
; | |
for(Iterator<RecipeElement> iter = pendingIngredients.iterator(); iter.hasNext();) | |
{ | |
RecipeElement currentIngredient = iter.next(); | |
if(currentIngredient.matches(stack)) | |
{ | |
newStack = stack.copy(); | |
newStack.stackSize = Math.min(currentIngredient.getStackSize(), stack.stackSize); | |
currentIngredient.setStackSize(currentIngredient.getStackSize() - Math.min(currentIngredient.getStackSize(), stack.stackSize)); | |
if(currentIngredient.getStackSize() == 0) | |
iter.remove(); | |
if(!worldObj.isRemote) stack.stackSize -= newStack.stackSize; | |
break; | |
} | |
} | |
break; | |
default: | |
break; | |
} | |
if(newStack == null) return false; | |
boolean slotFound = false; | |
if(newStack.isItemEnchanted()) | |
{ | |
mainHandler.setStackInSlot(SLOT_ENCH_ITEM, newStack); | |
slotFound = true; | |
} | |
else | |
{ | |
//attempt to insert stacks into inv | |
for(int s = SLOT_ENCH_ITEM + 1; s < mainHandler.getSlots(); s++) | |
{ | |
ItemStack slotStack = mainHandler.getStackInSlot(s); | |
if (ItemHandlerHelper.canItemStacksStack(newStack, slotStack)) | |
{ | |
CapUtils.incrementStack(mainHandler, s, newStack.stackSize); | |
slotFound = true; | |
break; | |
} | |
if(Prep1_11.isEmpty(slotStack)) | |
{ | |
mainHandler.setStackInSlot(s, newStack); | |
slotFound = true; | |
break; | |
} | |
} | |
} | |
return slotFound; | |
} | |
private boolean isIngredientPresent(ItemStack stack) | |
{ | |
for(int s = 0; s < mainHandler.getSlots(); s++) | |
{ | |
ItemStack slotStack = mainHandler.getStackInSlot(s); | |
if(ItemStack.areItemsEqual(stack, slotStack) && ItemStack.areItemStackTagsEqual(stack, slotStack)) | |
return true; | |
} | |
return false; | |
} | |
private void diffuse() | |
{ | |
//Check all ingredients are present | |
if(canDiffuse()) | |
{ | |
IBlockState state = worldObj.getBlockState(pos); | |
//Find the enchanted item | |
ItemStack enchItem = mainHandler.getStackInSlot(SLOT_ENCH_ITEM); | |
//Take health | |
if(healthTaken != BBConfig.diffusionHealthTaken) | |
{ | |
for (int i = 0; i < 2; i++) | |
{ | |
double x = rand.nextDouble() * 0.4 + 0.3; | |
double y = rand.nextDouble() * 0.5 + 0.5; | |
double z = rand.nextDouble() * 0.4 + 0.3; | |
double vx = rand.nextDouble() * 0.02 - 0.01; | |
double vy = rand.nextDouble() * 0.035 + 0.02; | |
double vz = rand.nextDouble() * 0.02 - 0.01; | |
worldObj.spawnParticle(EnumParticleTypes.HEART, pos.getX() + x, pos.getY() + y + 1, | |
pos.getZ() + z, vx, vy, vz); | |
} | |
//Get player on top and damage them | |
List<EntityPlayer> playersOnTop = worldObj.getEntitiesWithinAABB(EntityPlayer.class, searchBox); | |
if(!playersOnTop.isEmpty()) | |
{ | |
EntityPlayer player = playersOnTop.get(0); | |
if (player.attackEntityFrom(Util.DIFFUSION_DAMAGE, 0.5F)) | |
healthTaken += 0.5F; | |
} | |
worldObj.notifyBlockUpdate(pos, state, state, 8); | |
markDirty(); | |
} | |
else | |
{ | |
NBTTagList enchList = enchItem.getEnchantmentTagList(); | |
if(enchList != null) | |
{ | |
//Choose random enchant | |
int chosenEnchIndex = rand.nextInt(enchList.tagCount()); | |
NBTTagCompound chosenEnchNBT = enchList.getCompoundTagAt(chosenEnchIndex); | |
EnchantmentData chosenEnchData = new EnchantmentData(Enchantment.getEnchantmentByID(chosenEnchNBT.getShort("id")), chosenEnchNBT.getShort("lvl")); | |
//Remove the enchant | |
enchList.removeTag(chosenEnchIndex); | |
if(enchList.hasNoTags()) enchItem.getTagCompound().removeTag("ench"); | |
//Damage the ench item | |
if(enchItem.isItemStackDamageable()) | |
enchItem.damageItem(enchItem.getMaxDamage() / 5, null); | |
if(enchItem.getItemDamage() > enchItem.getMaxDamage()) | |
mainHandler.setStackInSlot(SLOT_ENCH_ITEM, null); | |
//Create an enchanted book for the enchantment | |
ItemStack enchBook = new ItemStack(Items.ENCHANTED_BOOK); | |
Items.ENCHANTED_BOOK.addEnchantment(enchBook, chosenEnchData); | |
//Spawn the enchanted book & the disenchanted item | |
if(!worldObj.isRemote) | |
{ | |
worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX(), pos.getY() + 1, pos.getZ(), enchBook)); | |
if(Prep1_11.isValid(mainHandler.getStackInSlot(SLOT_ENCH_ITEM))) | |
worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX(), pos.getY() + 1, pos.getZ(), mainHandler.getStackInSlot(SLOT_ENCH_ITEM))); | |
worldObj.notifyBlockUpdate(pos, state, state, 8); | |
markDirty(); | |
} | |
//Consume everything else in the inventory | |
for(int s = 0; s < mainHandler.getSlots(); s++) | |
{ | |
mainHandler.setStackInSlot(s, null); | |
} | |
worldObj.notifyBlockUpdate(pos, state, state, 8); | |
markDirty(); | |
} | |
mode = Mode.NONE; | |
} | |
} | |
} | |
private void repair() | |
{ | |
if(canRepair()) | |
{ | |
IBlockState state = worldObj.getBlockState(pos); | |
//Find the enchanted item | |
ItemStack enchItem = mainHandler.getStackInSlot(SLOT_ENCH_ITEM); | |
if(xpLevelsTaken < xpLevelsNeeded) | |
{ | |
for (int i = 0; i < 2; i++) | |
{ | |
double x = rand.nextDouble() * 0.8 + 0.3; | |
double y = rand.nextDouble() * 0.1 + 0.2; | |
double z = rand.nextDouble() * 0.8 + 0.3; | |
double vx = rand.nextDouble() * 0.02 - 0.01; | |
double vy = rand.nextDouble() * 0.035 + 0.02; | |
double vz = rand.nextDouble() * 0.02 - 0.01; | |
worldObj.spawnParticle(EnumParticleTypes.VILLAGER_HAPPY, pos.getX() + x, pos.getY() + y + 1, | |
pos.getZ() + z, vx, vy, vz); | |
} | |
//Get player on top and damage them | |
List<EntityPlayer> playersOnTop = worldObj.getEntitiesWithinAABB(EntityPlayer.class, searchBox); | |
if(!playersOnTop.isEmpty()) | |
{ | |
EntityPlayer player = playersOnTop.get(0); | |
player.removeExperienceLevel(1); | |
xpLevelsTaken++; | |
worldObj.notifyBlockUpdate(pos, state, state, 8); | |
markDirty(); | |
} | |
} | |
else | |
{ | |
enchItem.setItemDamage(0); | |
//Spawn the repair item | |
if(!worldObj.isRemote) | |
{ | |
worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX(), pos.getY() + 1, pos.getZ(), mainHandler.getStackInSlot(SLOT_ENCH_ITEM))); | |
} | |
//Consume everything else in the inventory | |
for(int s = 0; s < mainHandler.getSlots(); s++) | |
{ | |
mainHandler.setStackInSlot(s, null); | |
} | |
mode = Mode.NONE; | |
markDirty(); | |
this.xpLevelsTaken = 0; | |
worldObj.notifyBlockUpdate(pos, state, state, 8); | |
} | |
} | |
} | |
private boolean canDiffuse() | |
{ | |
boolean foundBook = false; | |
boolean foundEnchItem = false; | |
for(int s = 0; s < mainHandler.getSlots(); s++) | |
{ | |
ItemStack stack = mainHandler.getStackInSlot(s); | |
if(Prep1_11.isValid(stack)) | |
{ | |
if(stack.getItem() == Items.BOOK) | |
foundBook = true; | |
else if(stack.isItemEnchanted()) | |
foundEnchItem = true; | |
} | |
} | |
return foundBook && foundEnchItem; | |
} | |
private boolean canRepair() | |
{ | |
return pendingIngredients.isEmpty(); | |
} | |
private boolean hasEnchItem() | |
{ | |
return mainHandler.getStackInSlot(SLOT_ENCH_ITEM) != null;//STACKNULL | |
} | |
public Stack<RecipeElement> getPendingIngredients() | |
{ | |
return pendingIngredients; | |
} | |
@Override | |
public void setPos(BlockPos pos) | |
{ | |
super.setPos(pos); | |
searchBox = new AxisAlignedBB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 2, pos.getZ() + 1); | |
} | |
@Override | |
public SPacketUpdateTileEntity getUpdatePacket() | |
{ | |
NBTTagCompound tag = new NBTTagCompound(); | |
writeToNBT(tag); | |
return new SPacketUpdateTileEntity(pos, 1, tag); | |
} | |
@Override | |
public void onDataPacket(NetworkManager manager, SPacketUpdateTileEntity packet) | |
{ | |
readFromNBT(packet.getNbtCompound()); | |
} | |
@Override | |
public NBTTagCompound getUpdateTag() | |
{ | |
return this.writeToNBT(new NBTTagCompound()); | |
} | |
@Override | |
public void handleUpdateTag(NBTTagCompound tag) | |
{ | |
this.readFromNBT(tag); | |
} | |
@Override | |
public boolean hasCapability(Capability<?> capability, EnumFacing facing) | |
{ | |
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) | |
return true; | |
return super.hasCapability(capability, facing); | |
} | |
@Override | |
public <T> T getCapability(Capability<T> capability, EnumFacing facing) | |
{ | |
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) | |
return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(mainHandler); | |
return super.getCapability(capability, facing); | |
} | |
@Override | |
public String getName() | |
{ | |
return tileName; | |
} | |
@Override | |
public boolean hasCustomName() | |
{ | |
return tileName != null; | |
} | |
@Override | |
public void readFromNBT(NBTTagCompound compound) | |
{ | |
super.readFromNBT(compound); | |
CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.readNBT(mainHandler, null, compound.getTag(INV_TAG)); | |
mode = Mode.valueOf(compound.getString(MODE)); | |
if (compound.hasKey(CUSTOM_NAME)) | |
{ | |
tileName = compound.getString(CUSTOM_NAME); | |
} | |
xpLevelsNeeded = compound.getInteger(LEVELS_NEEDED); | |
xpLevelsTaken = compound.getInteger(LEVELS_TAKEN); | |
healthTaken = compound.getFloat(HEALTH_TAKEN); | |
} | |
@Override | |
public NBTTagCompound writeToNBT(NBTTagCompound compound) | |
{ | |
compound.setTag(INV_TAG, CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.writeNBT(mainHandler, null)); | |
compound.setString(MODE, mode.name()); | |
if (hasCustomName()) | |
{ | |
compound.setString(CUSTOM_NAME, tileName); | |
} | |
compound.setInteger(LEVELS_NEEDED, xpLevelsNeeded); | |
compound.setInteger(LEVELS_TAKEN, xpLevelsTaken); | |
compound.setFloat(HEALTH_TAKEN, healthTaken); | |
return super.writeToNBT(compound); | |
} | |
enum Mode | |
{ | |
NONE, | |
DIFFUSION, | |
REPAIR; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment