package com.flansmod.common; import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import com.flansmod.common.driveables.ContainerDriveableInventory; import com.flansmod.common.driveables.ContainerDriveableMenu; import com.flansmod.common.driveables.DriveablePart; import com.flansmod.common.driveables.DriveableType; import com.flansmod.common.driveables.EntityDriveable; import com.flansmod.common.driveables.EntitySeat; import com.flansmod.common.driveables.EnumDriveablePart; import com.flansmod.common.driveables.mechas.ContainerMechaInventory; import com.flansmod.common.driveables.mechas.EntityMecha; import com.flansmod.common.guns.ContainerGunModTable; import com.flansmod.common.guns.boxes.ContainerGunBox; import com.flansmod.common.guns.boxes.GunBoxType; import com.flansmod.common.network.PacketBreakSound; import com.flansmod.common.paintjob.ContainerPaintjobTable; import com.flansmod.common.paintjob.TileEntityPaintjobTable; import com.flansmod.common.parts.EnumPartCategory; import com.flansmod.common.parts.ItemPart; import com.flansmod.common.parts.PartType; import com.flansmod.common.teams.ArmourBoxType; import com.flansmod.common.types.EnumType; import com.flansmod.common.types.InfoType; public class CommonProxy { protected static Pattern zipJar = Pattern.compile("(.+).(zip|jar)$"); /** Returns the list of content pack files, and on the client, adds the content pack resources and models to the classpath */ public List<File> getContentList(Method method, ClassLoader classloader) { List<File> contentPacks = new ArrayList<File>(); for (File file : FlansMod.flanDir.listFiles()) { //Load folders and valid zip files if (file.isDirectory() || zipJar.matcher(file.getName()).matches()) { //Add the directory to the content pack list FlansMod.log("Loaded content pack : " + file.getName()); contentPacks.add(file); } } FlansMod.log("Loaded content pack list server side."); return contentPacks; } public void addMissingJSONs(HashMap<Integer, InfoType> types) { } /** A ton of client only methods follow */ public void load() { } public void forceReload() { } public void registerRenderers() { } public void doTutorialStuff(EntityPlayer player, EntityDriveable entityType) { } public void changeControlMode(EntityPlayer player) { } public boolean mouseControlEnabled() { return false; } public void openDriveableMenu(EntityPlayer player, World world, EntityDriveable driveable) { } public <T> T loadModel(String s, String shortName, Class<T> typeClass) { return null; } public void loadSound(String contentPack, String type, String sound) { } public boolean isThePlayer(EntityPlayer player) { return false; } public void buyGun(GunBoxType type, InfoType gun) { } /** Gets the client GUI element from ClientProxy */ public Object getClientGui(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; } /** Gets the container for the specified GUI */ public Container getServerGui(int ID, EntityPlayer player, World world, int x, int y, int z) { switch(ID) { case 0 : return null; //Driveable crafting. No server side case 1 : return null; //Driveable repair. No server side case 2: return new ContainerGunModTable(player.inventory, world); case 3: return new ContainerDriveableMenu(player.inventory, world); case 4: return new ContainerDriveableMenu(player.inventory, world, true, ((EntitySeat)player.ridingEntity).driveable); case 5: return new ContainerGunBox(player.inventory); //Plane inventory screens case 6: return new ContainerDriveableInventory(player.inventory, world, ((EntitySeat)player.ridingEntity).driveable, 0); case 7: return new ContainerDriveableInventory(player.inventory, world, ((EntitySeat)player.ridingEntity).driveable, 1); case 8: return new ContainerDriveableMenu(player.inventory, world, true, ((EntitySeat)player.ridingEntity).driveable); case 9: return new ContainerDriveableInventory(player.inventory, world, ((EntitySeat)player.ridingEntity).driveable, 2); case 10: return new ContainerMechaInventory(player.inventory, world, (EntityMecha)((EntitySeat)player.ridingEntity).driveable); case 11 : return null; //Armour box. No server side case 12 : return new ContainerDriveableInventory(player.inventory, world, ((EntitySeat)player.ridingEntity).driveable, 3); case 13: return new ContainerPaintjobTable(player.inventory, world, (TileEntityPaintjobTable)world.getTileEntity(new BlockPos(x, y, z))); } return null; } /** Play a block break sound here */ public void playBlockBreakSound(int x, int y, int z, Block blockHit) { FlansMod.packetHandler.sendToAll(new PacketBreakSound(x, y, z, blockHit)); } public void craftDriveable(EntityPlayer player, DriveableType type) { //Create a temporary copy of the player inventory for backup purposes InventoryPlayer temporaryInventory = new InventoryPlayer(null); temporaryInventory.copyInventory(player.inventory); //This becomes false if some recipe element is not found on the player boolean canCraft = true; //Iterate over rows then columns for(ItemStack recipeStack : type.driveableRecipe) { //The total amount of items found that match this recipe stack int totalAmountFound = 0; //Iterate over the player's inventory for(int n = 0; n < player.inventory.getSizeInventory(); n++) { //Get the stack in each slot ItemStack stackInSlot = player.inventory.getStackInSlot(n); //If the stack is what we want if(stackInSlot != null && stackInSlot.getItem() == recipeStack.getItem() && stackInSlot.getItemDamage() == recipeStack.getItemDamage()) { //Work out the amount to take from the stack int amountFound = Math.min(stackInSlot.stackSize, recipeStack.stackSize - totalAmountFound); //Take it stackInSlot.stackSize -= amountFound; //Check for empty stacks if(stackInSlot.stackSize <= 0) stackInSlot = null; //Put the modified stack back in the inventory player.inventory.setInventorySlotContents(n, stackInSlot); //Increase the amount found counter totalAmountFound += amountFound; //If we have enough, stop looking if(totalAmountFound == recipeStack.stackSize) break; } } //If we didn't find enough, give the stack a red outline if(totalAmountFound < recipeStack.stackSize) { //For some reason, the player sent a craft packet, despite being unable to canCraft = false; break; } } //Some item was missing. Restore inventory and return if(!canCraft) { player.inventory.copyInventory(temporaryInventory); return; } //Now we no longer need the temporary inventory backup, so we will use it to find the best stack of engines //Collect up all the engines into neat and tidy stacks so we can find if any of them are big enough and which of those stacks are best HashMap<PartType, ItemStack> engines = new HashMap<PartType, ItemStack>(); //Find some suitable engines for(int n = 0; n < temporaryInventory.getSizeInventory(); n++) { //Get the stack in each slot ItemStack stackInSlot = temporaryInventory.getStackInSlot(n); //Check to see if its a part if(stackInSlot != null && stackInSlot.getItem() instanceof ItemPart) { PartType partType = ((ItemPart)stackInSlot.getItem()).type; //Check its an engine if(partType.category == EnumPartCategory.ENGINE && partType.worksWith.contains(EnumType.getFromObject(type))) { //If we already have engines of this type, add these ones to the stack if(engines.containsKey(partType)) { engines.get(partType).stackSize += stackInSlot.stackSize; } //Else, make this the first stack else engines.put(partType, stackInSlot); } } } //Find the stack of engines that is fastest but which also has enough for this driveable float bestEngineSpeed = -1F; ItemStack bestEngineStack = null; for(PartType part : engines.keySet()) { //If this engine outperforms the currently selected best one and there are enough of them, swap if(part.engineSpeed > bestEngineSpeed && engines.get(part).stackSize >= type.numEngines()) { bestEngineSpeed = part.engineSpeed; bestEngineStack = engines.get(part); } } //If the player doesn't have any suitable engines, return if(bestEngineStack == null) { player.inventory.copyInventory(temporaryInventory); return; } //Remove the engines from the inventory int numEnginesAcquired = 0; for(int n = 0; n < player.inventory.getSizeInventory(); n++) { //Get the stack in each slot ItemStack stackInSlot = player.inventory.getStackInSlot(n); //Check to see if its the engine we want if(stackInSlot != null && stackInSlot.getItem() == bestEngineStack.getItem()) { //Work out the amount to take from the stack int amountFound = Math.min(stackInSlot.stackSize, type.numEngines() - numEnginesAcquired); //Take it stackInSlot.stackSize -= amountFound; //Check for empty stacks if(stackInSlot.stackSize <= 0) stackInSlot = null; //Put the modified stack back in the inventory player.inventory.setInventorySlotContents(n, stackInSlot); //Increase the amount found counter numEnginesAcquired += amountFound; //If we have enough, stop looking if(numEnginesAcquired == type.numEngines()) break; } } //Give them their brand new shiny driveable item :D ItemStack driveableStack = new ItemStack(type.item); NBTTagCompound tags = new NBTTagCompound(); tags.setString("Engine", ((ItemPart)bestEngineStack.getItem()).type.shortName); tags.setString("Type", type.shortName); for(EnumDriveablePart part : EnumDriveablePart.values()) { tags.setInteger(part.getShortName() + "_Health", type.health.get(part) == null ? 0 : type.health.get(part).health); tags.setBoolean(part.getShortName() + "_Fire", false); } driveableStack.setTagCompound(tags); if(!player.inventory.addItemStackToInventory(driveableStack)) player.dropPlayerItemWithRandomChoice(driveableStack, false); } public void repairDriveable(EntityPlayer driver, EntityDriveable driving, DriveablePart part) { //If any of this parts parent parts are broken, then it cannot be repaired for(EnumDriveablePart parent : part.type.getParents()) { if(!driving.isPartIntact(parent)) return; } //Create a temporary copy of the player inventory for backup purposes InventoryPlayer temporaryInventory = new InventoryPlayer(null); temporaryInventory.copyInventory(driver.inventory); //This becomes false if some recipe element is not found on the player boolean canRepair = true; //Get the array of stacks needed ArrayList<ItemStack> stacksNeeded = driving.getDriveableType().getItemsRequired(part, driving.getDriveableData().engine); //Draw the stacks that should be in each slot for(ItemStack stackNeeded : stacksNeeded) { //The total amount of items found that match this recipe stack int totalAmountFound = 0; //Iterate over the temporary inventory for(int m = 0; m < temporaryInventory.getSizeInventory(); m++) { //Get the stack in each slot ItemStack stackInSlot = temporaryInventory.getStackInSlot(m); //If the stack is what we want if(stackInSlot != null && stackInSlot.getItem() == stackNeeded.getItem() && stackInSlot.getItemDamage() == stackNeeded.getItemDamage()) { //Work out the amount to take from the stack int amountFound = Math.min(stackInSlot.stackSize, stackNeeded.stackSize - totalAmountFound); //Take it stackInSlot.stackSize -= amountFound; //Check for empty stacks if(stackInSlot.stackSize <= 0) stackInSlot = null; //Put the modified stack back in the inventory temporaryInventory.setInventorySlotContents(m, stackInSlot); //Increase the amount found counter totalAmountFound += amountFound; //If we have enough, stop looking if(totalAmountFound == stackNeeded.stackSize) break; } } if(totalAmountFound < stackNeeded.stackSize) canRepair = false; } if(canRepair) { driver.inventory.copyInventory(temporaryInventory); part.health = Math.max(1, part.maxHealth / 10); part.onFire = false; part.dead = false; driving.checkParts(); } } public boolean isScreenOpen() { return false; } public boolean isKeyDown(int key) { return false; } public boolean keyDown(int keycode) { return false; } public void buyArmour(String shortName, int piece, ArmourBoxType type) { } }