├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src └── main │ ├── java │ └── codechicken │ │ ├── core │ │ ├── gui │ │ │ ├── IGuiActionListener.java │ │ │ ├── ClickCounter.java │ │ │ ├── GuiWidget.java │ │ │ ├── GuiCCButton.java │ │ │ ├── GuiScreenWidget.java │ │ │ ├── GuiScrollSlot.java │ │ │ ├── GuiCCTextField.java │ │ │ └── GuiScrollPane.java │ │ ├── inventory │ │ │ ├── IContainerSyncVar.java │ │ │ ├── SlotHandleClicks.java │ │ │ ├── SlotDummyOutput.java │ │ │ ├── IntegerSync.java │ │ │ ├── ContainerSynchronised.java │ │ │ ├── SlotDummy.java │ │ │ ├── GuiContainerWidget.java │ │ │ ├── MappedInventoryAccess.java │ │ │ └── ContainerExtended.java │ │ ├── internal │ │ │ └── CCCEventHandler.java │ │ ├── commands │ │ │ ├── ServerCommand.java │ │ │ ├── PlayerCommand.java │ │ │ └── CoreCommand.java │ │ ├── fluid │ │ │ ├── TankAccess.java │ │ │ ├── ExtendedFluidTank.java │ │ │ └── FluidUtils.java │ │ ├── ModDescriptionEnhancer.java │ │ ├── launch │ │ │ ├── CodeChickenCorePlugin.java │ │ │ ├── FingerprintChecker.java │ │ │ └── DepLoader.java │ │ └── CCUpdateChecker.java │ │ └── obfuscator │ │ ├── ILogStreams.java │ │ ├── DummyOutputStream.java │ │ ├── SystemLogStreams.java │ │ ├── IHeirachyEvaluator.java │ │ ├── ObfDirection.java │ │ ├── ObfRemapper.java │ │ ├── ConstantObfuscator.java │ │ ├── ObfuscationRun.java │ │ └── ObfuscationMap.java │ └── resources │ ├── mcmod.info │ ├── ccc_at.cfg │ └── assets │ └── codechickencore │ └── asm │ └── tweaks.asm ├── curse_upload.json ├── .gitignore ├── README.md ├── settings.gradle ├── LICENSE.txt ├── gradlew.bat └── gradlew /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCBProject/CodeChickenCore/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/IGuiActionListener.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | public interface IGuiActionListener { 4 | void actionPerformed(String actionCommand, Object... params); 5 | } -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/ILogStreams.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import java.io.PrintStream; 4 | 5 | public interface ILogStreams { 6 | PrintStream err(); 7 | 8 | PrintStream out(); 9 | } 10 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 14 12:28:28 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-bin.zip 7 | -------------------------------------------------------------------------------- /curse_upload.json: -------------------------------------------------------------------------------- 1 | { 2 | "archivesBase" : "codechicken.CodeChickenCore", 3 | "displayName" : "CodeChicken Core", 4 | "projectId" : "243822", 5 | "uploadSRC" : false, 6 | "relations" : [ 7 | { 8 | "slug" : "codechicken-lib-1-8", 9 | "type" : "requiredLibrary" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/DummyOutputStream.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import java.io.OutputStream; 4 | 5 | public class DummyOutputStream extends OutputStream { 6 | public static DummyOutputStream instance = new DummyOutputStream(); 7 | 8 | @Override 9 | public void write(int b) { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "modid": "CodeChickenCore", 4 | "name": "CodeChicken Core", 5 | "description": "Base common code for all chickenbones mods.", 6 | "version": "${version}", 7 | "mcversion": "${mc_version}", 8 | "url": "http://www.minecraftforum.net/topic/909223", 9 | "authorList": [ "ChickenBones" ] 10 | } 11 | ] -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/IContainerSyncVar.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import codechicken.lib.packet.PacketCustom; 4 | 5 | public interface IContainerSyncVar { 6 | boolean changed(); 7 | 8 | void reset(); 9 | 10 | void writeChange(PacketCustom packet); 11 | 12 | void readChange(PacketCustom packet); 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Stolen form AE2 Repo. :D 2 | # exclude all 3 | 4 | /* 5 | 6 | # Include important folders 7 | 8 | # Gradle stuff 9 | !gradle/ 10 | !gradlew 11 | !gradlew.bat 12 | !build.gradle 13 | !build.properties 14 | !settings.gradle 15 | 16 | # Other Files. 17 | !LICENSE.txt 18 | !README.md 19 | !curse_upload.json 20 | 21 | # Include git important files 22 | !.gitmodules 23 | !.gitignore 24 | 25 | # Include Important Folders 26 | !src/ 27 | !libs/ 28 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/SystemLogStreams.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import java.io.PrintStream; 4 | 5 | public class SystemLogStreams implements ILogStreams { 6 | public static SystemLogStreams inst = new SystemLogStreams(); 7 | 8 | @Override 9 | public PrintStream err() { 10 | return System.err; 11 | } 12 | 13 | @Override 14 | public PrintStream out() { 15 | return System.out; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CodeChickenCore 2 | ============== 3 | 4 | **Note: As of 1.11, CodeChickenCore is dead. Please use [CodeChickenLib](https://github.com/TheCBProject/CodeChickenLib) in it's place, which contains all of it's core functionality. All tweaks have been moved to [CCTweaks](https://github.com/TheCBProject/CCTweaks).** 5 | 6 | This is the core of all ChickenBones mods. 7 | 8 | Current maven: http://chickenbones.net/maven/ 9 | 10 | Join us on IRC: 11 | - Server: Esper.net 12 | - Channel: #ChickenBones 13 | -------------------------------------------------------------------------------- /src/main/resources/ccc_at.cfg: -------------------------------------------------------------------------------- 1 | # CodeChickenCore Access Transformer 2 | public net.minecraft.client.renderer.texture.TextureMap field_94252_e # mapUploadedSprites 3 | 4 | public net.minecraft.server.management.PlayerProfileCache$ProfileEntry 5 | public net.minecraft.server.management.PlayerProfileCache field_152661_c # usernameToProfileEntryMap 6 | 7 | public net.minecraft.util.registry.RegistryNamespaced field_148759_a # underlyingIntegerMap 8 | public net.minecraft.util.registry.RegistrySimple field_82596_a # registryObjects 9 | public net.minecraft.item.Item field_179220_a # BLOCK_TO_ITEM 10 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/internal/CCCEventHandler.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.internal; 2 | 3 | import codechicken.core.CCUpdateChecker; 4 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 5 | import net.minecraftforge.fml.common.gameevent.TickEvent; 6 | import net.minecraftforge.fml.common.gameevent.TickEvent.Phase; 7 | 8 | public class CCCEventHandler { 9 | 10 | @SubscribeEvent 11 | public void clientTick(TickEvent.ClientTickEvent event) { 12 | if (event.phase == Phase.END) { 13 | CCUpdateChecker.tick(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/SlotHandleClicks.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.ClickType; 5 | import net.minecraft.inventory.IInventory; 6 | import net.minecraft.inventory.Slot; 7 | import net.minecraft.item.ItemStack; 8 | 9 | public abstract class SlotHandleClicks extends Slot { 10 | public SlotHandleClicks(IInventory inv, int slot, int x, int y) { 11 | super(inv, slot, x, y); 12 | } 13 | 14 | public abstract ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, ClickType clickType); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/SlotDummyOutput.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.ClickType; 5 | import net.minecraft.inventory.IInventory; 6 | import net.minecraft.item.ItemStack; 7 | 8 | public class SlotDummyOutput extends SlotHandleClicks { 9 | public SlotDummyOutput(IInventory inv, int slot, int x, int y) { 10 | super(inv, slot, x, y); 11 | } 12 | 13 | @Override 14 | public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, ClickType clickType) { 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; 4 | 5 | import java.util.List; 6 | 7 | public interface IHeirachyEvaluator { 8 | /** 9 | * @param desc The mapping descriptor of the class to evaluate heirachy for 10 | * @return A list of parents (srg or obf names) 11 | */ 12 | List getParents(ObfuscationEntry desc); 13 | 14 | /** 15 | * @param srg_class The srg name of the class in question 16 | * @return True if this class does not inherit from any obfuscated class. 17 | */ 18 | boolean isLibClass(ObfuscationEntry desc); 19 | } 20 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This settings file was auto generated by the Gradle buildInit task 3 | * by 'sunstrike' at '21/11/13 14:14' with Gradle 1.9 4 | * 5 | * The settings file is used to specify which projects to include in your build. 6 | * In a single project build this file can be empty or even removed. 7 | * 8 | * Detailed information about configuring a multi-project build in Gradle can be found 9 | * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html 10 | */ 11 | 12 | /* 13 | // To declare projects as part of a multi-project build use the 'include' method 14 | include 'shared' 15 | include 'api' 16 | include 'services:webservice' 17 | */ 18 | 19 | rootProject.name = 'CodeChickenCore' 20 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/IntegerSync.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import codechicken.lib.packet.PacketCustom; 4 | 5 | public abstract class IntegerSync implements IContainerSyncVar { 6 | public int c_value; 7 | 8 | @Override 9 | public boolean changed() { 10 | return getValue() != c_value; 11 | } 12 | 13 | @Override 14 | public void reset() { 15 | c_value = getValue(); 16 | } 17 | 18 | @Override 19 | public void writeChange(PacketCustom packet) { 20 | packet.writeInt(getValue()); 21 | } 22 | 23 | @Override 24 | public void readChange(PacketCustom packet) { 25 | c_value = packet.readInt(); 26 | } 27 | 28 | public abstract int getValue(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/commands/ServerCommand.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.commands; 2 | 3 | import net.minecraft.command.ICommandSender; 4 | import net.minecraft.server.MinecraftServer; 5 | 6 | public abstract class ServerCommand extends CoreCommand { 7 | @Override 8 | public void execute(MinecraftServer server, ICommandSender sender, String[] args) { 9 | handleCommand(args, (MinecraftServer) sender); 10 | } 11 | 12 | @Override 13 | public boolean checkPermission(MinecraftServer server, ICommandSender sender) { 14 | return super.checkPermission(server, sender) && sender instanceof MinecraftServer; 15 | } 16 | 17 | public abstract void handleCommand(String[] args, MinecraftServer listener); 18 | 19 | public final boolean isOpOnly() { 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/ObfDirection.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import codechicken.lib.asm.ObfMapping; 4 | import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; 5 | 6 | public class ObfDirection { 7 | public boolean obfuscate; 8 | public boolean srg; 9 | public boolean srg_cst; 10 | 11 | public ObfDirection setObfuscate(boolean obfuscate) { 12 | this.obfuscate = obfuscate; 13 | return this; 14 | } 15 | 16 | public ObfDirection setSearge(boolean srg) { 17 | this.srg = srg; 18 | return this; 19 | } 20 | 21 | public ObfDirection setSeargeConstants(boolean srg_cst) { 22 | this.srg_cst = srg_cst; 23 | return this; 24 | } 25 | 26 | public ObfMapping obfuscate(ObfuscationEntry map) { 27 | return srg ? map.srg : obfuscate ? map.obf : map.mcp; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/fluid/TankAccess.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.fluid; 2 | 3 | import net.minecraft.util.EnumFacing; 4 | import net.minecraftforge.fluids.FluidStack; 5 | import net.minecraftforge.fluids.IFluidHandler; 6 | 7 | @Deprecated 8 | public class TankAccess { 9 | public IFluidHandler tank; 10 | public EnumFacing face; 11 | 12 | public TankAccess(IFluidHandler tank, EnumFacing face) { 13 | this.tank = tank; 14 | this.face = face; 15 | } 16 | 17 | public TankAccess(IFluidHandler tank, int side) { 18 | this(tank, EnumFacing.values()[side]); 19 | } 20 | 21 | public int fill(FluidStack resource, boolean doFill) { 22 | return tank.fill(face, resource, doFill); 23 | } 24 | 25 | public FluidStack drain(int maxDrain, boolean doDrain) { 26 | return tank.drain(face, maxDrain, doDrain); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 ChickenBones 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/resources/assets/codechickencore/asm/tweaks.asm: -------------------------------------------------------------------------------- 1 | #A bunch of vanilla tweaks 2 | 3 | list d_environmentallyFriendlyCreepers 4 | ALOAD 0 5 | GETFIELD net/minecraft/entity/monster/EntityCreeper.field_70170_p:Lnet/minecraft/world/World; #worldObj 6 | INVOKEVIRTUAL net/minecraft/world/World.func_82736_K()Lnet/minecraft/world/GameRules; #getGameRules 7 | LDC "mobGriefing" 8 | INVOKEVIRTUAL net/minecraft/world/GameRules.func_82766_b(Ljava/lang/String;)Z #getGameRuleBooleanValue 9 | 10 | list environmentallyFriendlyCreepers 11 | ICONST_0 12 | 13 | list softLeafReplace 14 | ALOAD 0 15 | ALOAD 1 16 | ILOAD 2 17 | ILOAD 3 18 | ILOAD 4 19 | INVOKEVIRTUAL net/minecraft/block/Block.isAir(Lnet/minecraft/world/IBlockAccess;III)Z #forge method 20 | IRETURN 21 | 22 | list n_doFireTick 23 | LDC "doFireTick" 24 | INVOKEVIRTUAL net/minecraft/world/GameRules.func_82766_b(Ljava/lang/String;)Z #getGameRuleBooleanValue 25 | IFEQ LRET 26 | 27 | list doFireTick 28 | ALOAD 1 29 | ILOAD 2 30 | ILOAD 3 31 | ILOAD 4 32 | ALOAD 5 33 | INVOKESTATIC codechicken/core/featurehack/TweakTransformerHelper.quenchFireTick(Lnet/minecraft/world/World;IIILjava/util/Random;)V 34 | LSKIP 35 | 36 | list finiteWater 37 | ALOAD 0 38 | GETFIELD net/minecraft/block/BlockDynamicLiquid.field_149815_a:I 39 | ICONST_2 40 | IF_ICMPLT LEND -------------------------------------------------------------------------------- /src/main/java/codechicken/core/commands/PlayerCommand.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.commands; 2 | 3 | import codechicken.lib.raytracer.RayTracer; 4 | import net.minecraft.command.ICommandSender; 5 | import net.minecraft.entity.Entity; 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraft.entity.player.EntityPlayerMP; 8 | import net.minecraft.server.MinecraftServer; 9 | import net.minecraft.util.math.BlockPos; 10 | import net.minecraft.world.WorldServer; 11 | 12 | public abstract class PlayerCommand extends CoreCommand { 13 | @Override 14 | public boolean checkPermission(MinecraftServer server, ICommandSender player) { 15 | return super.checkPermission(server, player) && player instanceof EntityPlayer; 16 | } 17 | 18 | @Override 19 | public void handleCommand(String command, String playername, String[] args, ICommandSender listener) { 20 | EntityPlayerMP player = (EntityPlayerMP) listener; 21 | handleCommand(getWorld(player), player, args); 22 | } 23 | 24 | public abstract void handleCommand(WorldServer world, EntityPlayerMP player, String[] args); 25 | 26 | public static BlockPos traceBlock(EntityPlayerMP player, float reach) { 27 | return RayTracer.retrace(player, reach).getBlockPos(); 28 | } 29 | 30 | public static Entity traceEntity(EntityPlayerMP player, float reach) { 31 | return RayTracer.retrace(player, reach).entityHit; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/ClickCounter.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | import com.google.common.base.Objects; 4 | 5 | import java.util.Map; 6 | import java.util.TreeMap; 7 | 8 | public class ClickCounter { 9 | public class ClickCount { 10 | public T clicked; 11 | public long time; 12 | public int count; 13 | 14 | public boolean update(T clicked) { 15 | if (!Objects.equal(this.clicked, clicked)) { 16 | this.clicked = clicked; 17 | count = 0; 18 | time = Long.MIN_VALUE; 19 | return false; 20 | } 21 | return true; 22 | } 23 | } 24 | 25 | public Map buttons = new TreeMap(); 26 | 27 | public ClickCount getCount(int button) { 28 | ClickCount c = buttons.get(button); 29 | if (c == null) { 30 | buttons.put(button, c = new ClickCount()); 31 | } 32 | return c; 33 | } 34 | 35 | public void mouseDown(T clicked, int button) { 36 | ClickCount c = getCount(button); 37 | c.update(clicked); 38 | } 39 | 40 | public int mouseUp(T clicked, int button) { 41 | ClickCount c = getCount(button); 42 | if (!c.update(clicked)) { 43 | return 0; 44 | } 45 | 46 | long time = System.currentTimeMillis(); 47 | if (time - c.time < 500) { 48 | c.count++; 49 | } else { 50 | c.count = 1; 51 | } 52 | c.time = time; 53 | return c.count; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/ContainerSynchronised.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import codechicken.lib.packet.PacketCustom; 4 | import net.minecraft.entity.player.EntityPlayerMP; 5 | import net.minecraft.inventory.Container; 6 | import net.minecraft.item.ItemStack; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | public abstract class ContainerSynchronised extends ContainerExtended { 13 | private ArrayList syncVars = new ArrayList(); 14 | 15 | public abstract PacketCustom createSyncPacket(); 16 | 17 | @Override 18 | public final void detectAndSendChanges() { 19 | super.detectAndSendChanges(); 20 | 21 | for (int i = 0; i < syncVars.size(); i++) { 22 | IContainerSyncVar var = syncVars.get(i); 23 | if (var.changed()) { 24 | PacketCustom packet = createSyncPacket(); 25 | packet.writeByte(i); 26 | var.writeChange(packet); 27 | sendContainerPacket(packet); 28 | var.reset(); 29 | } 30 | } 31 | } 32 | 33 | @Override 34 | public void sendContainerAndContentsToPlayer(Container container, List list, List playerCrafters) { 35 | super.sendContainerAndContentsToPlayer(container, list, playerCrafters); 36 | for (int i = 0; i < syncVars.size(); i++) { 37 | IContainerSyncVar var = syncVars.get(i); 38 | PacketCustom packet = createSyncPacket(); 39 | packet.writeByte(i); 40 | var.writeChange(packet); 41 | var.reset(); 42 | for (EntityPlayerMP player : playerCrafters) { 43 | packet.sendToPlayer(player); 44 | } 45 | } 46 | } 47 | 48 | public void addSyncVar(IContainerSyncVar var) { 49 | syncVars.add(var); 50 | } 51 | 52 | @Override 53 | public final void handleOutputPacket(PacketCustom packet) { 54 | syncVars.get(packet.readUByte()).readChange(packet); 55 | } 56 | 57 | public List getSyncedVars() { 58 | return Collections.unmodifiableList(syncVars); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/ModDescriptionEnhancer.java: -------------------------------------------------------------------------------- 1 | package codechicken.core; 2 | 3 | import codechicken.lib.util.ReflectionManager; 4 | import net.minecraft.util.text.TextFormatting; 5 | import net.minecraftforge.common.ForgeVersion; 6 | import net.minecraftforge.common.ForgeVersion.CheckResult; 7 | import net.minecraftforge.common.ForgeVersion.Status; 8 | import net.minecraftforge.fml.common.FMLCommonHandler; 9 | import net.minecraftforge.fml.common.ModContainer; 10 | import net.minecraftforge.fml.common.versioning.ComparableVersion; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | @SuppressWarnings("unchecked") 16 | public class ModDescriptionEnhancer { 17 | public static void enhanceMod(Object mod) { 18 | ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod); 19 | mc.getMetadata().description = enhanceDesc(mc.getMetadata().description); 20 | } 21 | 22 | public static String enhanceDesc(String desc) { 23 | int supportersIdx = desc.indexOf("Supporters:"); 24 | if (supportersIdx < 0) { 25 | return desc; 26 | } 27 | 28 | String supportersList = desc.substring(supportersIdx); 29 | supportersList = supportersList.replaceAll("\\b(\\w+)\\b", TextFormatting.AQUA + "$1"); 30 | return desc.substring(0, supportersIdx) + supportersList; 31 | } 32 | 33 | public static void setUpdateStatus(String modId, Status status, ComparableVersion version) { 34 | try { 35 | ModContainer modContainer = FMLCommonHandler.instance().findContainerFor(modId); 36 | Map changes = new HashMap(); 37 | CheckResult result = ReflectionManager.newInstance(CheckResult.class, status, version, changes, ""); 38 | setUpdateStatus(modContainer, result); 39 | } catch (Exception e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | 44 | public static void setUpdateStatus(ModContainer container, CheckResult result) { 45 | try { 46 | Map resultMap = ReflectionManager.getField(ForgeVersion.class, Map.class, null, "results"); 47 | synchronized (resultMap) { 48 | resultMap.put(container, result); 49 | } 50 | 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/GuiWidget.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.FontRenderer; 5 | import net.minecraft.client.gui.Gui; 6 | import net.minecraft.client.gui.GuiScreen; 7 | import net.minecraft.client.renderer.texture.TextureManager; 8 | import net.minecraft.util.ResourceLocation; 9 | 10 | public class GuiWidget extends Gui { 11 | protected static final ResourceLocation guiTex = new ResourceLocation("textures/gui/widgets.png"); 12 | 13 | public GuiScreen parentScreen; 14 | public TextureManager renderEngine; 15 | public FontRenderer fontRenderer; 16 | 17 | public int x; 18 | public int y; 19 | public int width; 20 | public int height; 21 | 22 | public GuiWidget(int x, int y, int width, int height) { 23 | setSize(x, y, width, height); 24 | } 25 | 26 | public void setSize(int x, int y, int width, int height) { 27 | this.x = x; 28 | this.y = y; 29 | this.width = width; 30 | this.height = height; 31 | } 32 | 33 | public boolean pointInside(int px, int py) { 34 | return px >= x && px < x + width && py >= y && py < y + height; 35 | } 36 | 37 | public void sendAction(String actionCommand, Object... params) { 38 | sendAction(parentScreen, actionCommand, params); 39 | } 40 | 41 | public static void sendAction(GuiScreen screen, String actionCommand, Object... params) { 42 | if (actionCommand != null && screen instanceof IGuiActionListener) { 43 | ((IGuiActionListener) screen).actionPerformed(actionCommand, params); 44 | } 45 | } 46 | 47 | public void mouseClicked(int x, int y, int button) { 48 | } 49 | 50 | public void mouseReleased(int x, int y, int button) { 51 | } 52 | 53 | public void mouseDragged(int x, int y, int button, long time) { 54 | } 55 | 56 | public void update() { 57 | } 58 | 59 | public void draw(int mousex, int mousey, float frame) { 60 | } 61 | 62 | public void keyTyped(char c, int keycode) { 63 | } 64 | 65 | public void mouseScrolled(int x, int y, int scroll) { 66 | } 67 | 68 | public void onAdded(GuiScreen s) { 69 | Minecraft mc = Minecraft.getMinecraft(); 70 | parentScreen = s; 71 | renderEngine = mc.renderEngine; 72 | fontRenderer = mc.fontRendererObj; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.launch; 2 | 3 | import codechicken.core.CCUpdateChecker; 4 | import codechicken.core.internal.CCCEventHandler; 5 | import codechicken.lib.CodeChickenLib; 6 | import codechicken.lib.config.ConfigFile; 7 | import net.minecraftforge.common.MinecraftForge; 8 | import net.minecraftforge.fml.common.Mod; 9 | import net.minecraftforge.fml.common.Mod.EventHandler; 10 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 11 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 12 | import net.minecraftforge.fml.relauncher.FMLInjectionData; 13 | import org.apache.logging.log4j.LogManager; 14 | import org.apache.logging.log4j.Logger; 15 | 16 | import java.io.File; 17 | 18 | @Mod(modid = "CodeChickenCore", name = "CodeChicken Core", dependencies = "required-after:CodeChickenLib@[" + CodeChickenLib.version + ",)", acceptedMinecraftVersions = CodeChickenLib.mcVersion, certificateFingerprint = "f1850c39b2516232a2108a7bd84d1cb5df93b261") 19 | public class CodeChickenCorePlugin { 20 | public static final String version = "${mod_version}"; 21 | 22 | public static File minecraftDir; 23 | public static String currentMcVersion; 24 | public static Logger logger = LogManager.getLogger("CodeChickenCore"); 25 | 26 | public static ConfigFile config; 27 | 28 | public static void loadConfig() { 29 | if (config == null) { 30 | config = new ConfigFile(new File(minecraftDir, "config/CodeChickenCore.cfg")).setComment("CodeChickenCore configuration file."); 31 | } 32 | } 33 | 34 | public CodeChickenCorePlugin() { 35 | if (minecraftDir != null) { 36 | return;//get called twice, once for IFMLCallHook 37 | } 38 | 39 | minecraftDir = (File) FMLInjectionData.data()[6]; 40 | currentMcVersion = (String) FMLInjectionData.data()[4]; 41 | 42 | loadConfig(); 43 | } 44 | 45 | @EventHandler 46 | public void preInit(FMLPreInitializationEvent event) { 47 | FingerprintChecker.runFingerprintChecks(); 48 | } 49 | 50 | @EventHandler 51 | public void init(FMLInitializationEvent event) { 52 | if (event.getSide().isClient()) { 53 | if (config.getTag("checkUpdates").getBooleanValue(true)) { 54 | CCUpdateChecker.updateCheck("CodeChickenCore"); 55 | } 56 | 57 | MinecraftForge.EVENT_BUS.register(new CCCEventHandler()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/SlotDummy.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import codechicken.lib.inventory.InventoryUtils; 4 | import net.minecraft.entity.player.EntityPlayer; 5 | import net.minecraft.inventory.ClickType; 6 | import net.minecraft.inventory.IInventory; 7 | import net.minecraft.item.ItemStack; 8 | 9 | public class SlotDummy extends SlotHandleClicks { 10 | public final int stackLimit; 11 | 12 | public SlotDummy(IInventory inv, int slot, int x, int y) { 13 | this(inv, slot, x, y, 64); 14 | } 15 | 16 | public SlotDummy(IInventory inv, int slot, int x, int y, int limit) { 17 | super(inv, slot, x, y); 18 | stackLimit = limit; 19 | } 20 | 21 | @Override 22 | public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, ClickType clickType) { 23 | ItemStack held = player.inventory.getItemStack(); 24 | boolean shift = clickType == ClickType.QUICK_MOVE; 25 | slotClick(held, button, shift); 26 | return null; 27 | } 28 | 29 | public void slotClick(ItemStack held, int button, boolean shift) { 30 | ItemStack tstack = getStack(); 31 | if (held != null && (tstack == null || !InventoryUtils.canStack(held, tstack))) { 32 | int quantity = Math.min(held.stackSize, stackLimit); 33 | if (shift) { 34 | quantity = Math.min(stackLimit, held.getMaxStackSize() * 16); 35 | } 36 | if (button == 1) { 37 | quantity = 1; 38 | } 39 | putStack(InventoryUtils.copyStack(held, quantity)); 40 | } else if (tstack != null) { 41 | int inc; 42 | if (held != null) { 43 | inc = button == 1 ? -held.stackSize : held.stackSize; 44 | if (shift) { 45 | inc *= 16; 46 | } 47 | } else { 48 | inc = button == 1 ? -1 : 1; 49 | if (shift) { 50 | inc *= 16; 51 | } 52 | } 53 | int quantity = tstack.stackSize + inc; 54 | if (quantity <= 0) { 55 | putStack(null); 56 | } else { 57 | putStack(InventoryUtils.copyStack(tstack, quantity)); 58 | } 59 | } 60 | } 61 | 62 | @Override 63 | public void putStack(ItemStack stack) { 64 | if (stack != null && stack.stackSize > stackLimit) { 65 | stack = InventoryUtils.copyStack(stack, stackLimit); 66 | } 67 | super.putStack(stack); 68 | } 69 | 70 | @Override 71 | public boolean canTakeStack(EntityPlayer playerIn) { 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/ObfRemapper.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; 4 | import org.objectweb.asm.commons.Remapper; 5 | 6 | public class ObfRemapper extends Remapper { 7 | public final ObfuscationMap obf; 8 | public ObfDirection dir; 9 | 10 | public ObfRemapper(ObfuscationMap obf, ObfDirection dir) { 11 | this.obf = obf; 12 | this.dir = dir; 13 | } 14 | 15 | @Override 16 | public String map(String name) { 17 | if (name.indexOf('$') >= 0) { 18 | return map(name.substring(0, name.indexOf('$'))) + name.substring(name.indexOf('$')); 19 | } 20 | 21 | ObfuscationEntry map; 22 | if (dir.obfuscate) { 23 | map = obf.lookupMcpClass(name); 24 | } else { 25 | map = obf.lookupObfClass(name); 26 | } 27 | 28 | if (map != null) { 29 | return dir.obfuscate(map).s_owner; 30 | } 31 | 32 | return name; 33 | } 34 | 35 | @Override 36 | public String mapFieldName(String owner, String name, String desc) { 37 | ObfuscationEntry map; 38 | if (dir.obfuscate) { 39 | map = obf.lookupMcpField(owner, name); 40 | } else { 41 | map = obf.lookupObfField(owner, name); 42 | } 43 | 44 | if (map == null) { 45 | map = obf.lookupSrgField(owner, name); 46 | } 47 | 48 | if (map != null) { 49 | return dir.obfuscate(map).s_name; 50 | } 51 | 52 | return name; 53 | } 54 | 55 | @Override 56 | public String mapMethodName(String owner, String name, String desc) { 57 | if (owner.length() == 0 || owner.charAt(0) == '[') { 58 | return name; 59 | } 60 | 61 | ObfuscationEntry map; 62 | if (dir.obfuscate) { 63 | map = obf.lookupMcpMethod(owner, name, desc); 64 | } else { 65 | map = obf.lookupObfMethod(owner, name, desc); 66 | } 67 | 68 | if (map == null) { 69 | map = obf.lookupSrg(name); 70 | } 71 | 72 | if (map != null) { 73 | return dir.obfuscate(map).s_name; 74 | } 75 | 76 | return name; 77 | } 78 | 79 | @Override 80 | public Object mapValue(Object cst) { 81 | if (cst instanceof String) { 82 | if (dir.srg_cst) { 83 | ObfuscationEntry map = obf.lookupSrg((String) cst); 84 | if (map != null) { 85 | return dir.obfuscate(map).s_name; 86 | } 87 | } 88 | return cst; 89 | } 90 | 91 | return super.mapValue(cst); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/GuiCCButton.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.audio.PositionedSoundRecord; 5 | import net.minecraft.client.renderer.GlStateManager; 6 | import net.minecraft.init.SoundEvents; 7 | 8 | public class GuiCCButton extends GuiWidget { 9 | public String text; 10 | public String actionCommand; 11 | private boolean isEnabled = true; 12 | public boolean visible = true; 13 | 14 | public GuiCCButton(int x, int y, int width, int height, String text) { 15 | super(x, y, width, height); 16 | this.text = text; 17 | } 18 | 19 | public void setText(String s) { 20 | text = s; 21 | } 22 | 23 | public boolean isEnabled() { 24 | return isEnabled; 25 | } 26 | 27 | public void setEnabled(boolean b) { 28 | isEnabled = b; 29 | } 30 | 31 | @Override 32 | public void mouseClicked(int x, int y, int button) { 33 | if (isEnabled && pointInside(x, y) && actionCommand != null) { 34 | sendAction(actionCommand, button); 35 | Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); 36 | } 37 | } 38 | 39 | @Override 40 | public void draw(int mousex, int mousey, float frame) { 41 | if (!visible) { 42 | return; 43 | } 44 | 45 | drawButtonTex(mousex, mousey); 46 | if (text != null) { 47 | drawText(mousex, mousey); 48 | } 49 | } 50 | 51 | public void drawButtonTex(int mousex, int mousey) { 52 | GlStateManager.color(1, 1, 1, 1); 53 | renderEngine.bindTexture(guiTex); 54 | int state = getButtonTex(mousex, mousey); 55 | drawTexturedModalRect(x, y, 0, 46 + state * 20, width / 2, height / 2);//top left 56 | drawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + state * 20, width / 2, height / 2);//top right 57 | drawTexturedModalRect(x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom left 58 | drawTexturedModalRect(x + width / 2, y + height / 2, 200 - width / 2, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom right 59 | } 60 | 61 | public int getButtonTex(int mousex, int mousey) { 62 | return !isEnabled ? 0 : pointInside(mousex, mousey) ? 2 : 1; 63 | } 64 | 65 | public void drawText(int mousex, int mousey) { 66 | drawCenteredString(fontRenderer, text, x + width / 2, y + (height - 8) / 2, getTextColour(mousex, mousey)); 67 | } 68 | 69 | public int getTextColour(int mousex, int mousey) { 70 | return !isEnabled ? 0xFFA0A0A0 : pointInside(mousex, mousey) ? 0xFFFFFFA0 : 0xFFE0E0E0; 71 | } 72 | 73 | public GuiCCButton setActionCommand(String string) { 74 | actionCommand = string; 75 | return this; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/fluid/ExtendedFluidTank.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.fluid; 2 | 3 | import net.minecraft.nbt.NBTTagCompound; 4 | import net.minecraftforge.fluids.FluidStack; 5 | import net.minecraftforge.fluids.FluidTankInfo; 6 | import net.minecraftforge.fluids.IFluidTank; 7 | 8 | public class ExtendedFluidTank implements IFluidTank { 9 | private FluidStack fluid; 10 | private boolean changeType; 11 | private int capacity; 12 | 13 | public ExtendedFluidTank(FluidStack type, int capacity) { 14 | if (type == null) { 15 | type = FluidUtils.emptyFluid(); 16 | changeType = true; 17 | } 18 | fluid = FluidUtils.copy(type, 0); 19 | this.capacity = capacity; 20 | } 21 | 22 | public ExtendedFluidTank(int capacity) { 23 | this(null, capacity); 24 | } 25 | 26 | @Override 27 | public FluidStack getFluid() { 28 | return fluid.copy(); 29 | } 30 | 31 | @Override 32 | public int getCapacity() { 33 | return capacity; 34 | } 35 | 36 | public boolean canAccept(FluidStack type) { 37 | return type == null || (fluid.amount == 0 && changeType) || fluid.isFluidEqual(type); 38 | } 39 | 40 | @Override 41 | public int fill(FluidStack resource, boolean doFill) { 42 | if (resource == null) { 43 | return 0; 44 | } 45 | 46 | if (!canAccept(resource)) { 47 | return 0; 48 | } 49 | 50 | int tofill = Math.min(getCapacity() - fluid.amount, resource.amount); 51 | if (doFill && tofill > 0) { 52 | if (!fluid.isFluidEqual(resource)) { 53 | fluid = FluidUtils.copy(resource, fluid.amount + tofill); 54 | } else { 55 | fluid.amount += tofill; 56 | } 57 | onLiquidChanged(); 58 | } 59 | 60 | return tofill; 61 | } 62 | 63 | @Override 64 | public FluidStack drain(int maxDrain, boolean doDrain) { 65 | if (fluid.amount == 0 || maxDrain <= 0) { 66 | return null; 67 | } 68 | 69 | int todrain = Math.min(maxDrain, fluid.amount); 70 | if (doDrain && todrain > 0) { 71 | fluid.amount -= todrain; 72 | onLiquidChanged(); 73 | } 74 | return FluidUtils.copy(fluid, todrain); 75 | } 76 | 77 | public FluidStack drain(FluidStack resource, boolean doDrain) { 78 | if (resource == null || !resource.isFluidEqual(fluid)) { 79 | return null; 80 | } 81 | 82 | return drain(resource.amount, doDrain); 83 | } 84 | 85 | public void onLiquidChanged() { 86 | } 87 | 88 | public void fromTag(NBTTagCompound tag) { 89 | fluid = FluidUtils.read(tag); 90 | } 91 | 92 | public NBTTagCompound toTag() { 93 | return FluidUtils.write(fluid, new NBTTagCompound()); 94 | } 95 | 96 | @Override 97 | public int getFluidAmount() { 98 | return fluid.amount; 99 | } 100 | 101 | @Override 102 | public FluidTankInfo getInfo() { 103 | return new FluidTankInfo(this); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/ConstantObfuscator.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import codechicken.lib.asm.ObfMapping; 4 | import org.objectweb.asm.Opcodes; 5 | import org.objectweb.asm.tree.*; 6 | 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN; 11 | import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN; 12 | 13 | public class ConstantObfuscator implements Opcodes { 14 | public ObfRemapper obf; 15 | public List descCalls = new LinkedList(); 16 | public List classCalls = new LinkedList(); 17 | 18 | public ConstantObfuscator(ObfRemapper obf, String[] a_classCalls, String[] a_descCalls) { 19 | this.obf = obf; 20 | for (String callDesc : a_classCalls) { 21 | classCalls.add(ObfMapping.fromDesc(callDesc)); 22 | } 23 | 24 | for (String callDesc : a_descCalls) { 25 | descCalls.add(ObfMapping.fromDesc(callDesc)); 26 | } 27 | } 28 | 29 | public void transform(ClassNode cnode) { 30 | for (MethodNode method : cnode.methods) { 31 | for (AbstractInsnNode insn = method.instructions.getFirst(); insn != null; insn = insn.getNext()) { 32 | obfuscateInsnSeq(insn); 33 | } 34 | } 35 | } 36 | 37 | private void obfuscateInsnSeq(AbstractInsnNode insn) { 38 | if (matchesClass(insn)) { 39 | LdcInsnNode node1 = (LdcInsnNode) insn; 40 | node1.cst = obf.map((String) node1.cst); 41 | } 42 | if (matchesDesc(insn)) { 43 | LdcInsnNode node1 = (LdcInsnNode) insn; 44 | LdcInsnNode node2 = (LdcInsnNode) node1.getNext(); 45 | LdcInsnNode node3 = (LdcInsnNode) node2.getNext(); 46 | ObfMapping mapping = new ObfMapping((String) node1.cst, (String) node2.cst, (String) node3.cst).map(obf); 47 | node1.cst = mapping.s_owner; 48 | node2.cst = mapping.s_name; 49 | node3.cst = mapping.s_desc; 50 | } 51 | } 52 | 53 | private boolean matchesClass(AbstractInsnNode insn) { 54 | if (insn.getType() != LDC_INSN) { 55 | return false; 56 | } 57 | insn = insn.getNext(); 58 | if (insn == null || insn.getType() != METHOD_INSN) { 59 | return false; 60 | } 61 | for (ObfMapping m : classCalls) { 62 | if (m.matches((MethodInsnNode) insn)) { 63 | return true; 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | private boolean matchesDesc(AbstractInsnNode insn) { 70 | if (insn.getType() != LDC_INSN) { 71 | return false; 72 | } 73 | insn = insn.getNext(); 74 | if (insn == null || insn.getType() != LDC_INSN) { 75 | return false; 76 | } 77 | insn = insn.getNext(); 78 | if (insn == null || insn.getType() != LDC_INSN) { 79 | return false; 80 | } 81 | insn = insn.getNext(); 82 | if (insn == null || insn.getType() != METHOD_INSN) { 83 | return false; 84 | } 85 | for (ObfMapping m : descCalls) { 86 | if (m.matches((MethodInsnNode) insn)) { 87 | return true; 88 | } 89 | } 90 | return false; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/fluid/FluidUtils.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.fluid; 2 | 3 | import codechicken.lib.inventory.InventoryUtils; 4 | import net.minecraft.entity.player.EntityPlayer; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.nbt.NBTTagCompound; 7 | import net.minecraft.util.EnumHand; 8 | import net.minecraftforge.fluids.*; 9 | import net.minecraftforge.fluids.capability.IFluidHandler; 10 | 11 | public class FluidUtils { 12 | public static int B = FluidContainerRegistry.BUCKET_VOLUME; 13 | public static FluidStack water = new FluidStack(FluidRegistry.WATER, 1000); 14 | public static FluidStack lava = new FluidStack(FluidRegistry.LAVA, 1000); 15 | 16 | public static boolean fillTankWithContainer(IFluidHandler tank, EntityPlayer player) { 17 | ItemStack stack = player.getHeldItem(EnumHand.MAIN_HAND); 18 | FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(stack); 19 | 20 | if (liquid == null) { 21 | return false; 22 | } 23 | 24 | if (tank.fill(liquid, false) != liquid.amount && !player.capabilities.isCreativeMode) { 25 | return false; 26 | } 27 | 28 | tank.fill(liquid, true); 29 | 30 | if (!player.capabilities.isCreativeMode) { 31 | InventoryUtils.consumeItem(player.inventory, player.inventory.currentItem); 32 | } 33 | 34 | player.inventoryContainer.detectAndSendChanges(); 35 | return true; 36 | } 37 | 38 | public static boolean emptyTankIntoContainer(IFluidHandler tank, EntityPlayer player, FluidStack tankLiquid) { 39 | ItemStack stack = player.getHeldItem(EnumHand.MAIN_HAND); 40 | 41 | if (!FluidContainerRegistry.isEmptyContainer(stack)) { 42 | return false; 43 | } 44 | 45 | ItemStack filled = FluidContainerRegistry.fillFluidContainer(tankLiquid, stack); 46 | FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(filled); 47 | 48 | if (liquid == null || filled == null) { 49 | return false; 50 | } 51 | 52 | tank.drain(liquid.amount, true); 53 | 54 | if (!player.capabilities.isCreativeMode) { 55 | if (stack.stackSize == 1) { 56 | player.inventory.setInventorySlotContents(player.inventory.currentItem, filled); 57 | } else if (player.inventory.addItemStackToInventory(filled)) { 58 | stack.stackSize--; 59 | } else { 60 | return false; 61 | } 62 | } 63 | 64 | player.inventoryContainer.detectAndSendChanges(); 65 | return true; 66 | } 67 | 68 | public static FluidStack copy(FluidStack liquid, int quantity) { 69 | liquid = liquid.copy(); 70 | liquid.amount = quantity; 71 | return liquid; 72 | } 73 | 74 | public static FluidStack read(NBTTagCompound tag) { 75 | FluidStack stack = FluidStack.loadFluidStackFromNBT(tag); 76 | return stack != null ? stack : new FluidStack(new Fluid("none", null, null), 0); 77 | } 78 | 79 | public static NBTTagCompound write(FluidStack fluid, NBTTagCompound tag) { 80 | return fluid == null || fluid.getFluid() == null ? new NBTTagCompound() : fluid.writeToNBT(new NBTTagCompound()); 81 | } 82 | 83 | public static int getLuminosity(FluidStack stack, double density) { 84 | Fluid fluid = stack.getFluid(); 85 | if (fluid == null) { 86 | return 0; 87 | } 88 | int light = fluid.getLuminosity(stack); 89 | if (fluid.isGaseous()) { 90 | light = (int) (light * density); 91 | } 92 | return light; 93 | } 94 | 95 | public static FluidStack emptyFluid() { 96 | return new FluidStack(water, 0); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/commands/CoreCommand.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.commands; 2 | 3 | import codechicken.lib.util.ServerUtils; 4 | import net.minecraft.command.ICommand; 5 | import net.minecraft.command.ICommandSender; 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraft.entity.player.EntityPlayerMP; 8 | import net.minecraft.server.MinecraftServer; 9 | import net.minecraft.util.math.BlockPos; 10 | import net.minecraft.util.text.TextComponentTranslation; 11 | import net.minecraft.world.WorldServer; 12 | import net.minecraftforge.common.DimensionManager; 13 | import net.minecraftforge.fml.common.FMLCommonHandler; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | public abstract class CoreCommand implements ICommand { 19 | public static void chatT(ICommandSender sender, String s, Object... params) { 20 | sender.addChatMessage(new TextComponentTranslation(s, params)); 21 | } 22 | 23 | public static void chatOpsT(String s, Object... params) { 24 | for (EntityPlayerMP player : ServerUtils.getPlayers()) { 25 | if (FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().canSendCommands(player.getGameProfile())) { 26 | player.addChatMessage(new TextComponentTranslation(s, params)); 27 | } 28 | } 29 | } 30 | 31 | public abstract boolean isOpOnly(); 32 | 33 | @Override 34 | public String getCommandUsage(ICommandSender commandSender) { 35 | return "/" + getCommandName() + " help"; 36 | } 37 | 38 | @Override 39 | public void execute(MinecraftServer server, ICommandSender sender, String[] args) { 40 | if (args.length < minimumParameters() || args.length == 1 && args[0].equals("help")) { 41 | printHelp(sender); 42 | return; 43 | } 44 | 45 | String command = getCommandName(); 46 | for (String arg : args) { 47 | command += " " + arg; 48 | } 49 | 50 | handleCommand(command, sender.getName(), args, sender); 51 | } 52 | 53 | public abstract void handleCommand(String command, String playername, String[] args, ICommandSender listener); 54 | 55 | public abstract void printHelp(ICommandSender sender); 56 | 57 | public final EntityPlayerMP getPlayer(String name) { 58 | return ServerUtils.getPlayer(name); 59 | } 60 | 61 | public WorldServer getWorld(int dimension) { 62 | return DimensionManager.getWorld(dimension); 63 | } 64 | 65 | public WorldServer getWorld(EntityPlayer player) { 66 | return (WorldServer) player.worldObj; 67 | } 68 | 69 | @Override 70 | public int compareTo(ICommand o) { 71 | return getCommandName().compareTo(o.getCommandName()); 72 | } 73 | 74 | @Override 75 | public List getCommandAliases() { 76 | return new ArrayList(); 77 | } 78 | 79 | @Override 80 | public List getTabCompletionOptions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos pos) { 81 | return null; 82 | } 83 | 84 | @Override 85 | public boolean isUsernameIndex(String[] args, int index) { 86 | return false; 87 | } 88 | 89 | @Override 90 | public boolean checkPermission(MinecraftServer server, ICommandSender commandSender) { 91 | if (isOpOnly()) { 92 | if (commandSender instanceof EntityPlayer) { 93 | return FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().canSendCommands(((EntityPlayer) commandSender).getGameProfile()); 94 | } 95 | 96 | return commandSender instanceof MinecraftServer; 97 | } 98 | return true; 99 | } 100 | 101 | public abstract int minimumParameters(); 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/GuiContainerWidget.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import codechicken.core.gui.GuiWidget; 4 | import codechicken.core.gui.IGuiActionListener; 5 | import codechicken.lib.gui.GuiDraw; 6 | import net.minecraft.client.Minecraft; 7 | import net.minecraft.client.gui.inventory.GuiContainer; 8 | import net.minecraft.client.renderer.GlStateManager; 9 | import net.minecraft.inventory.Container; 10 | import org.lwjgl.input.Mouse; 11 | 12 | import java.awt.*; 13 | import java.io.IOException; 14 | import java.util.ArrayList; 15 | 16 | public class GuiContainerWidget extends GuiContainer implements IGuiActionListener { 17 | public ArrayList widgets = new ArrayList(); 18 | 19 | public GuiContainerWidget(Container inventorySlots) { 20 | this(inventorySlots, 176, 166); 21 | } 22 | 23 | public GuiContainerWidget(Container inventorySlots, int xSize, int ySize) { 24 | super(inventorySlots); 25 | this.xSize = xSize; 26 | this.ySize = ySize; 27 | } 28 | 29 | @Override 30 | public void setWorldAndResolution(Minecraft mc, int i, int j) { 31 | super.setWorldAndResolution(mc, i, j); 32 | if (widgets.isEmpty()) { 33 | addWidgets(); 34 | } 35 | } 36 | 37 | public void add(GuiWidget widget) { 38 | widgets.add(widget); 39 | widget.onAdded(this); 40 | } 41 | 42 | @Override 43 | protected void drawGuiContainerBackgroundLayer(float f, int mousex, int mousey) { 44 | GlStateManager.translate(guiLeft, guiTop, 0); 45 | drawBackground(); 46 | for (GuiWidget widget : widgets) { 47 | widget.draw(mousex - guiLeft, mousey - guiTop, f); 48 | } 49 | 50 | GlStateManager.translate(-guiLeft, -guiTop, 0); 51 | } 52 | 53 | public void drawBackground() { 54 | } 55 | 56 | @Override 57 | protected void mouseClicked(int x, int y, int button) throws IOException { 58 | super.mouseClicked(x, y, button); 59 | for (GuiWidget widget : widgets) { 60 | widget.mouseClicked(x - guiLeft, y - guiTop, button); 61 | } 62 | } 63 | 64 | @Override 65 | protected void mouseReleased(int x, int y, int button) { 66 | super.mouseReleased(x, y, button); 67 | for (GuiWidget widget : widgets) { 68 | widget.mouseReleased(x - guiLeft, y - guiTop, button); 69 | } 70 | } 71 | 72 | @Override 73 | protected void mouseClickMove(int x, int y, int button, long time) { 74 | super.mouseClickMove(x, y, button, time); 75 | for (GuiWidget widget : widgets) { 76 | widget.mouseDragged(x - guiLeft, y - guiTop, button, time); 77 | } 78 | } 79 | 80 | @Override 81 | public void updateScreen() { 82 | super.updateScreen(); 83 | if (mc.currentScreen == this) { 84 | for (GuiWidget widget : widgets) { 85 | widget.update(); 86 | } 87 | } 88 | } 89 | 90 | @Override 91 | public void keyTyped(char c, int keycode) throws IOException { 92 | super.keyTyped(c, keycode); 93 | for (GuiWidget widget : widgets) { 94 | widget.keyTyped(c, keycode); 95 | } 96 | } 97 | 98 | @Override 99 | public void handleMouseInput() throws IOException { 100 | super.handleMouseInput(); 101 | int i = Mouse.getEventDWheel(); 102 | if (i != 0) { 103 | Point p = GuiDraw.getMousePosition(); 104 | int scroll = i > 0 ? 1 : -1; 105 | for (GuiWidget widget : widgets) { 106 | widget.mouseScrolled(p.x, p.y, scroll); 107 | } 108 | } 109 | } 110 | 111 | @Override 112 | public void actionPerformed(String ident, Object... params) { 113 | } 114 | 115 | public void addWidgets() { 116 | } 117 | 118 | @Override 119 | public void onGuiClosed() { 120 | super.onGuiClosed(); 121 | widgets.clear(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/MappedInventoryAccess.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.util.text.ITextComponent; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | public class MappedInventoryAccess implements IInventory { 13 | public interface InventoryAccessor { 14 | boolean canAccessSlot(int slot); 15 | } 16 | 17 | public static final InventoryAccessor fullAccess = new InventoryAccessor() { 18 | public boolean canAccessSlot(int slot) { 19 | return true; 20 | } 21 | }; 22 | 23 | private ArrayList slotMap = new ArrayList(); 24 | private IInventory inv; 25 | private ArrayList accessors = new ArrayList(); 26 | 27 | public MappedInventoryAccess(IInventory inv, InventoryAccessor... accessors) { 28 | this.inv = inv; 29 | Collections.addAll(this.accessors, accessors); 30 | reset(); 31 | } 32 | 33 | public void reset() { 34 | slotMap.clear(); 35 | nextslot: 36 | for (int i = 0; i < inv.getSizeInventory(); i++) { 37 | for (InventoryAccessor a : accessors) { 38 | if (!a.canAccessSlot(i)) { 39 | continue nextslot; 40 | } 41 | } 42 | 43 | slotMap.add(i); 44 | } 45 | } 46 | 47 | @Override 48 | public int getSizeInventory() { 49 | return slotMap.size(); 50 | } 51 | 52 | @Override 53 | public ItemStack getStackInSlot(int slot) { 54 | return inv.getStackInSlot(slotMap.get(slot)); 55 | } 56 | 57 | @Override 58 | public ItemStack decrStackSize(int slot, int amount) { 59 | return inv.decrStackSize(slotMap.get(slot), amount); 60 | } 61 | 62 | @Override 63 | public ItemStack removeStackFromSlot(int slot) { 64 | return inv.removeStackFromSlot(slotMap.get(slot)); 65 | } 66 | 67 | @Override 68 | public void setInventorySlotContents(int slot, ItemStack stack) { 69 | inv.setInventorySlotContents(slotMap.get(slot), stack); 70 | } 71 | 72 | @Override 73 | public int getInventoryStackLimit() { 74 | return inv.getInventoryStackLimit(); 75 | } 76 | 77 | @Override 78 | public void markDirty() { 79 | inv.markDirty(); 80 | } 81 | 82 | @Override 83 | public boolean isUseableByPlayer(EntityPlayer player) { 84 | return inv.isUseableByPlayer(player); 85 | } 86 | 87 | public void addAccessor(InventoryAccessor accessor) { 88 | accessors.add(accessor); 89 | reset(); 90 | } 91 | 92 | @Override 93 | public boolean isItemValidForSlot(int slot, ItemStack stack) { 94 | return inv.isItemValidForSlot(slotMap.get(slot), stack); 95 | } 96 | 97 | @Override 98 | public void openInventory(EntityPlayer player) { 99 | inv.openInventory(player); 100 | } 101 | 102 | @Override 103 | public void closeInventory(EntityPlayer player) { 104 | inv.closeInventory(player); 105 | } 106 | 107 | @Override 108 | public int getField(int id) { 109 | return inv.getField(id); 110 | } 111 | 112 | @Override 113 | public void setField(int id, int value) { 114 | inv.setField(id, value); 115 | } 116 | 117 | @Override 118 | public int getFieldCount() { 119 | return inv.getFieldCount(); 120 | } 121 | 122 | @Override 123 | public void clear() { 124 | inv.clear(); 125 | } 126 | 127 | @Override 128 | public String getName() { 129 | return inv.getName(); 130 | } 131 | 132 | @Override 133 | public boolean hasCustomName() { 134 | return inv.hasCustomName(); 135 | } 136 | 137 | @Override 138 | public ITextComponent getDisplayName() { 139 | return inv.getDisplayName(); 140 | } 141 | 142 | public List accessors() { 143 | return accessors; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/GuiScreenWidget.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | import codechicken.lib.gui.GuiDraw; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.gui.GuiScreen; 6 | import net.minecraft.client.renderer.GlStateManager; 7 | import org.lwjgl.input.Mouse; 8 | 9 | import java.awt.*; 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | 13 | public class GuiScreenWidget extends GuiScreen implements IGuiActionListener { 14 | public ArrayList widgets = new ArrayList(); 15 | public int xSize, ySize, guiTop, guiLeft; 16 | 17 | public GuiScreenWidget() { 18 | this(176, 166); 19 | } 20 | 21 | public GuiScreenWidget(int xSize, int ySize) { 22 | super(); 23 | this.xSize = xSize; 24 | this.ySize = ySize; 25 | } 26 | 27 | @Override 28 | public void initGui() { 29 | guiTop = (height - ySize) / 2; 30 | guiLeft = (width - xSize) / 2; 31 | if (!widgets.isEmpty()) { 32 | resize(); 33 | } 34 | } 35 | 36 | public void reset() { 37 | widgets.clear(); 38 | initGui(); 39 | addWidgets(); 40 | resize(); 41 | } 42 | 43 | @Override 44 | public void setWorldAndResolution(Minecraft mc, int i, int j) { 45 | boolean init = this.mc == null; 46 | super.setWorldAndResolution(mc, i, j); 47 | if (init) { 48 | addWidgets(); 49 | resize(); 50 | } 51 | } 52 | 53 | public void add(GuiWidget widget) { 54 | widgets.add(widget); 55 | widget.onAdded(this); 56 | } 57 | 58 | @Override 59 | public void drawScreen(int mousex, int mousey, float f) { 60 | GlStateManager.translate(guiLeft, guiTop, 0); 61 | drawBackground(); 62 | for (GuiWidget widget : widgets) { 63 | widget.draw(mousex - guiLeft, mousey - guiTop, f); 64 | } 65 | drawForeground(); 66 | GlStateManager.translate(-guiLeft, -guiTop, 0); 67 | } 68 | 69 | public void drawBackground() { 70 | } 71 | 72 | public void drawForeground() { 73 | } 74 | 75 | @Override 76 | protected void mouseClicked(int x, int y, int button) throws IOException { 77 | super.mouseClicked(x, y, button); 78 | for (GuiWidget widget : widgets) { 79 | widget.mouseClicked(x - guiLeft, y - guiTop, button); 80 | } 81 | } 82 | 83 | @Override 84 | protected void mouseReleased(int x, int y, int button) { 85 | super.mouseReleased(x, y, button); 86 | for (GuiWidget widget : widgets) { 87 | widget.mouseReleased(x - guiLeft, y - guiTop, button); 88 | } 89 | } 90 | 91 | @Override 92 | protected void mouseClickMove(int x, int y, int button, long time) { 93 | super.mouseClickMove(x, y, button, time); 94 | for (GuiWidget widget : widgets) { 95 | widget.mouseDragged(x - guiLeft, y - guiTop, button, time); 96 | } 97 | } 98 | 99 | @Override 100 | public void updateScreen() { 101 | super.updateScreen(); 102 | if (mc.currentScreen == this) { 103 | for (GuiWidget widget : widgets) { 104 | widget.update(); 105 | } 106 | } 107 | } 108 | 109 | @Override 110 | public void keyTyped(char c, int keycode) throws IOException { 111 | super.keyTyped(c, keycode); 112 | for (GuiWidget widget : widgets) { 113 | widget.keyTyped(c, keycode); 114 | } 115 | } 116 | 117 | @Override 118 | public void handleMouseInput() throws IOException { 119 | super.handleMouseInput(); 120 | int i = Mouse.getEventDWheel(); 121 | if (i != 0) { 122 | Point p = GuiDraw.getMousePosition(); 123 | int scroll = i > 0 ? 1 : -1; 124 | for (GuiWidget widget : widgets) { 125 | widget.mouseScrolled(p.x, p.y, scroll); 126 | } 127 | } 128 | } 129 | 130 | @Override 131 | public void actionPerformed(String ident, Object... params) { 132 | } 133 | 134 | public void resize() { 135 | } 136 | 137 | public void addWidgets() { 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/CCUpdateChecker.java: -------------------------------------------------------------------------------- 1 | package codechicken.core; 2 | 3 | import codechicken.core.launch.CodeChickenCorePlugin; 4 | import com.google.common.base.Function; 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.util.text.TextComponentString; 7 | import net.minecraftforge.common.ForgeVersion; 8 | import net.minecraftforge.fml.common.Loader; 9 | import net.minecraftforge.fml.common.versioning.ComparableVersion; 10 | import net.minecraftforge.fml.relauncher.FMLInjectionData; 11 | 12 | import java.io.BufferedReader; 13 | import java.io.IOException; 14 | import java.io.InputStreamReader; 15 | import java.net.*; 16 | import java.util.ArrayList; 17 | 18 | public class CCUpdateChecker { 19 | private static final ArrayList updates = new ArrayList(); 20 | 21 | private static class ThreadUpdateCheck extends Thread { 22 | private final URL url; 23 | private final Function handler; 24 | 25 | public ThreadUpdateCheck(URL url, Function handler) { 26 | this.url = url; 27 | this.handler = handler; 28 | 29 | setName("CodeChicken Update Checker"); 30 | } 31 | 32 | @Override 33 | public void run() { 34 | try { 35 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 36 | conn.setRequestMethod("GET"); 37 | conn.setConnectTimeout(5000); 38 | conn.setReadTimeout(5000); 39 | BufferedReader read = new BufferedReader(new InputStreamReader(conn.getInputStream())); 40 | String ret = read.readLine(); 41 | read.close(); 42 | if (ret == null) { 43 | ret = ""; 44 | } 45 | handler.apply(ret); 46 | } catch (SocketTimeoutException ignored) { 47 | } catch (UnknownHostException ignored) { 48 | } catch (IOException iox) { 49 | iox.printStackTrace(); 50 | } 51 | } 52 | } 53 | 54 | public static void tick() { 55 | Minecraft mc = Minecraft.getMinecraft(); 56 | if (!mc.inGameHasFocus) { 57 | return; 58 | } 59 | 60 | synchronized (updates) { 61 | for (String updateMessage : updates) { 62 | mc.thePlayer.addChatMessage(new TextComponentString(updateMessage)); 63 | } 64 | updates.clear(); 65 | } 66 | } 67 | 68 | public static void addUpdateMessage(String s) { 69 | synchronized (updates) { 70 | updates.add(s); 71 | } 72 | } 73 | 74 | public static String mcVersion() { 75 | return (String) FMLInjectionData.data()[4]; 76 | } 77 | 78 | public static void updateCheck(final String mod, final String version) { 79 | updateCheck("http://www.chickenbones.net/Files/notification/version.php?" + 80 | "version=" + mcVersion() + "&" + 81 | "file=" + mod, new Function() { 82 | @Override 83 | public Void apply(String ret) { 84 | if (!ret.startsWith("Ret: ")) { 85 | CodeChickenCorePlugin.logger.error("Failed to check update for " + mod + " returned: " + ret); 86 | return null; 87 | } 88 | ComparableVersion newVersion = new ComparableVersion(ret.substring(5)); 89 | if (newVersion.compareTo(new ComparableVersion(version)) > 0) { 90 | ModDescriptionEnhancer.setUpdateStatus(mod, ForgeVersion.Status.OUTDATED, newVersion); 91 | addUpdateMessage("Version " + newVersion + " of " + mod + " is available"); 92 | } 93 | return null; 94 | } 95 | }); 96 | } 97 | 98 | public static void updateCheck(String mod) { 99 | updateCheck(mod, Loader.instance().getIndexedModList().get(mod).getVersion()); 100 | } 101 | 102 | public static void updateCheck(String url, Function handler) { 103 | try { 104 | new ThreadUpdateCheck(new URL(url), handler).start(); 105 | } catch (MalformedURLException e) { 106 | CodeChickenCorePlugin.logger.error("Malformed URL: " + url, e); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/launch/FingerprintChecker.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.launch; 2 | 3 | import codechicken.lib.fingerprint.FingerprintViolatedCrashCallable; 4 | import com.google.common.collect.ImmutableList; 5 | import net.minecraftforge.fml.common.*; 6 | import org.apache.logging.log4j.Level; 7 | 8 | import java.security.cert.Certificate; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Map.Entry; 14 | 15 | /** 16 | * Created by covers1624 on 13/12/2016. 17 | * To be packaged in each mod runtime, used to cross verify jar fingerprints. 18 | * Idea behind this: 19 | * A malicious user would have to override the fingerprint data in all mod jars this is packaged with in order to avoid detection. 20 | * This is not to be used as DRM. It is used simply to provide cross verification of jars. 21 | */ 22 | public class FingerprintChecker { 23 | 24 | private static final Map modCertMap = new HashMap(); 25 | private static final List invalidMods = new ArrayList(); 26 | 27 | static { 28 | //@formatter:off 29 | modCertMap.put("CodeChickenLib" , "f1850c39b2516232a2108a7bd84d1cb5df93b261"); 30 | modCertMap.put("CodeChickenCore" , "f1850c39b2516232a2108a7bd84d1cb5df93b261"); 31 | modCertMap.put("ChickenChunks" , "f1850c39b2516232a2108a7bd84d1cb5df93b261"); 32 | modCertMap.put("EnderStorage" , "f1850c39b2516232a2108a7bd84d1cb5df93b261"); 33 | modCertMap.put("Translocator" , "f1850c39b2516232a2108a7bd84d1cb5df93b261"); 34 | modCertMap.put("NotEnoughItems" , "f1850c39b2516232a2108a7bd84d1cb5df93b261"); 35 | modCertMap.put("forgemultipartcbe" , "f1850c39b2516232a2108a7bd84d1cb5df93b261"); 36 | //@formatter:on 37 | } 38 | 39 | public static void runFingerprintChecks() { 40 | try { 41 | ModContainer activeContainer = Loader.instance().activeModContainer(); 42 | for (Entry modEntry : Loader.instance().getIndexedModList().entrySet()) { 43 | for (Entry certEntry : modCertMap.entrySet()) { 44 | if (modEntry.getKey().equals(certEntry.getKey())) { 45 | Object modInstance = modEntry.getValue().getMod(); 46 | if (modInstance == null) { 47 | FMLLog.log(activeContainer.getModId() + " Fingerprint Verification", Level.FATAL, "Unable to do Fingerprint Verification for mod %s! ModContainer returned a null mod instance!", modEntry.getKey()); 48 | break; 49 | } 50 | if (modInstance.getClass().getName().contains("net.minecraftforge.")) { 51 | FMLLog.log(activeContainer.getModId() + " Fingerprint Verification", Level.FATAL, "Unable to do Fingerprint Verification for mod %s! ModContainer returned is a suspected FML class! [%s]", modEntry.getKey(), modInstance.getClass().getName()); 52 | } 53 | 54 | Certificate[] certificates = modInstance.getClass().getProtectionDomain().getCodeSource().getCertificates(); 55 | ImmutableList.Builder certBuilder = ImmutableList.builder(); 56 | if (certificates != null) { 57 | for (Certificate cert : certificates) { 58 | certBuilder.add(CertificateHelper.getFingerprint(cert)); 59 | } 60 | } 61 | 62 | ImmutableList certList = certBuilder.build(); 63 | 64 | String expectedFingerprint = certEntry.getValue(); 65 | 66 | if (expectedFingerprint != null && !expectedFingerprint.isEmpty()) { 67 | if (!certList.contains(expectedFingerprint)) { 68 | FMLLog.log(activeContainer.getModId() + " Fingerprint Verification", Level.FATAL, "The fingerprint for mod %s is invalid! Expected: %s", modEntry.getKey(), expectedFingerprint); 69 | invalidMods.add(modEntry.getKey()); 70 | break; 71 | } else { 72 | FMLLog.log(activeContainer.getModId() + " Fingerprint Verification", Level.DEBUG, "Valid fingerprint found for mod %s.", modEntry.getKey()); 73 | } 74 | } 75 | 76 | break; 77 | } 78 | } 79 | } 80 | FMLCommonHandler.instance().registerCrashCallable(new FingerprintViolatedCrashCallable(activeContainer.getModId(), invalidMods)); 81 | } catch (Exception e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/GuiScrollSlot.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | import org.lwjgl.input.Keyboard; 4 | 5 | import java.awt.*; 6 | 7 | public abstract class GuiScrollSlot extends GuiScrollPane { 8 | protected String actionCommand; 9 | public boolean focused; 10 | protected ClickCounter click = new ClickCounter(); 11 | public boolean smoothScroll = true; 12 | 13 | public GuiScrollSlot(int x, int y, int width, int height) { 14 | super(x, y, width, height); 15 | setMargins(3, 2, 3, 2); 16 | } 17 | 18 | public GuiScrollSlot setActionCommand(String s) { 19 | actionCommand = s; 20 | return this; 21 | } 22 | 23 | public void setSmoothScroll(boolean b) { 24 | smoothScroll = b; 25 | } 26 | 27 | public abstract int getSlotHeight(int slot); 28 | 29 | protected abstract int getNumSlots(); 30 | 31 | public void selectNext() { 32 | } 33 | 34 | public void selectPrev() { 35 | } 36 | 37 | /** 38 | * Coordinates are relative to slot area 39 | */ 40 | protected abstract void slotClicked(int slot, int button, int mx, int my, int count); 41 | 42 | protected abstract void drawSlot(int slot, int x, int y, int mx, int my, float frame); 43 | 44 | protected void unfocus() { 45 | } 46 | 47 | public void setFocused(boolean focus) { 48 | focused = focus; 49 | if (!focused) { 50 | unfocus(); 51 | } 52 | } 53 | 54 | @Override 55 | public int contentHeight() { 56 | return getSlotY(getNumSlots()); 57 | } 58 | 59 | public int getSlotY(int slot) { 60 | int h = 0; 61 | for (int i = 0; i < slot; i++) { 62 | h += getSlotHeight(i); 63 | } 64 | return h; 65 | } 66 | 67 | public int getSlot(int my) { 68 | if (my < 0) { 69 | return -1; 70 | } 71 | 72 | int y = 0; 73 | for (int i = 0; i < getNumSlots(); i++) { 74 | int h = getSlotHeight(i); 75 | if (my >= y && my < y + h) { 76 | return i; 77 | } 78 | y += h; 79 | } 80 | return -1; 81 | } 82 | 83 | public int getClickedSlot(int my) { 84 | return getSlot(my - windowBounds().y + scrolledPixels()); 85 | } 86 | 87 | @Override 88 | public int scrolledPixels() { 89 | int scrolled = super.scrolledPixels(); 90 | if (!smoothScroll) { 91 | int slot = getSlot(scrolled); 92 | int sloty = getSlotY(slot); 93 | int sloth = getSlotHeight(slot); 94 | scrolled = sloty + (int) ((scrolled - sloty) / (double) sloth + 0.5) * sloth; 95 | } 96 | return scrolled; 97 | } 98 | 99 | /** 100 | * @return -1 for left, 1 for right 101 | */ 102 | public int scrollbarAlignment() { 103 | return 1; 104 | } 105 | 106 | @Override 107 | public int scrollbarGuideAlignment() { 108 | return scrollbarAlignment(); 109 | } 110 | 111 | @Override 112 | public Rectangle scrollbarBounds() { 113 | Rectangle r = super.scrollbarBounds(); 114 | if (scrollbarAlignment() == -1) { 115 | r.x = x; 116 | } 117 | return r; 118 | } 119 | 120 | public void showSlot(int slot) { 121 | showSlot(getSlotY(slot), getSlotHeight(slot)); 122 | } 123 | 124 | @Override 125 | public void slotDown(int mx, int my, int button) { 126 | int slot = getSlot(my); 127 | click.mouseDown(slot >= 0 ? slot : null, button); 128 | } 129 | 130 | @Override 131 | public void slotUp(int mx, int my, int button) { 132 | int slot = getSlot(my); 133 | int c = click.mouseUp(slot >= 0 ? slot : null, button); 134 | if (c > 0 && slot >= 0) { 135 | slotClicked(slot, button, mx, my - getSlotY(slot), c); 136 | } 137 | } 138 | 139 | @Override 140 | public void keyTyped(char c, int keycode) { 141 | if (!focused) { 142 | return; 143 | } 144 | 145 | if (keycode == Keyboard.KEY_UP) { 146 | selectPrev(); 147 | } 148 | if (keycode == Keyboard.KEY_DOWN) { 149 | selectNext(); 150 | } 151 | if (keycode == Keyboard.KEY_RETURN && actionCommand != null) { 152 | sendAction(actionCommand); 153 | } 154 | } 155 | 156 | @Override 157 | public void drawContent(int mx, int my, float frame) { 158 | int scrolled = scrolledPixels(); 159 | Rectangle w = windowBounds(); 160 | int y = 0; 161 | for (int slot = 0; slot < getNumSlots(); slot++) { 162 | int h = getSlotHeight(slot); 163 | if (y + h > scrolled && y < scrolled + w.height) { 164 | drawSlot(slot, w.x, w.y + y - scrolledPixels(), mx, my - y, frame); 165 | } 166 | y += h; 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/GuiCCTextField.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | import net.minecraft.client.gui.GuiScreen; 4 | import net.minecraft.util.ChatAllowedCharacters; 5 | import org.lwjgl.input.Keyboard; 6 | 7 | public class GuiCCTextField extends GuiWidget { 8 | private String text; 9 | private boolean isFocused; 10 | private boolean isEnabled; 11 | 12 | public int maxStringLength; 13 | public int cursorCounter; 14 | public String actionCommand; 15 | 16 | private String allowedCharacters; 17 | 18 | public GuiCCTextField(int x, int y, int width, int height, String text) { 19 | super(x, y, width, height); 20 | isFocused = false; 21 | isEnabled = true; 22 | this.text = text; 23 | } 24 | 25 | public GuiCCTextField setActionCommand(String s) { 26 | actionCommand = s; 27 | return this; 28 | } 29 | 30 | public void setText(String s) { 31 | if (s.equals(text)) { 32 | return; 33 | } 34 | 35 | String oldText = text; 36 | text = s; 37 | onTextChanged(oldText); 38 | } 39 | 40 | public void onTextChanged(String oldText) { 41 | } 42 | 43 | public final String getText() { 44 | return text; 45 | } 46 | 47 | public final boolean isEnabled() { 48 | return isEnabled; 49 | } 50 | 51 | public void setEnabled(boolean b) { 52 | isEnabled = b; 53 | if (!isEnabled && isFocused) { 54 | setFocused(false); 55 | } 56 | } 57 | 58 | public final boolean isFocused() { 59 | return isFocused; 60 | } 61 | 62 | @Override 63 | public void update() { 64 | cursorCounter++; 65 | } 66 | 67 | @Override 68 | public void keyTyped(char c, int keycode) { 69 | if (!isEnabled || !isFocused) { 70 | return; 71 | } 72 | 73 | /*if(c == '\t')//tab 74 | { 75 | parentGuiScreen.selectNextField(); 76 | }*/ 77 | if (c == '\026')//paste 78 | { 79 | String s = GuiScreen.getClipboardString(); 80 | if (s == null || s.equals("")) { 81 | return; 82 | } 83 | 84 | for (int i = 0; i < s.length(); i++) { 85 | if (text.length() == maxStringLength) { 86 | return; 87 | } 88 | 89 | char tc = s.charAt(i); 90 | if (canAddChar(tc)) { 91 | setText(text + tc); 92 | } 93 | } 94 | } 95 | if (keycode == Keyboard.KEY_RETURN) { 96 | setFocused(false); 97 | sendAction(actionCommand, getText()); 98 | } 99 | 100 | if (keycode == Keyboard.KEY_BACK && text.length() > 0) { 101 | setText(text.substring(0, text.length() - 1)); 102 | } 103 | 104 | if ((text.length() < maxStringLength || maxStringLength == 0) && canAddChar(c)) { 105 | setText(text + c); 106 | } 107 | } 108 | 109 | public boolean canAddChar(char c) { 110 | return allowedCharacters == null ? ChatAllowedCharacters.isAllowedCharacter(c) : allowedCharacters.indexOf(c) >= 0; 111 | } 112 | 113 | @Override 114 | public void mouseClicked(int x, int y, int button) { 115 | if (isEnabled && pointInside(x, y)) { 116 | setFocused(true); 117 | if (button == 1) { 118 | setText(""); 119 | } 120 | } else { 121 | setFocused(false); 122 | } 123 | } 124 | 125 | public void setFocused(boolean focus) { 126 | if (focus == isFocused) { 127 | return; 128 | } 129 | isFocused = focus; 130 | onFocusChanged(); 131 | } 132 | 133 | public void onFocusChanged() { 134 | if (isFocused) { 135 | cursorCounter = 0; 136 | } 137 | } 138 | 139 | @Override 140 | public void draw(int i, int j, float f) { 141 | drawBackground(); 142 | drawText(); 143 | } 144 | 145 | public void drawBackground() { 146 | drawRect(x - 1, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0); 147 | drawRect(x, y, x + width, y + height, 0xff000000); 148 | } 149 | 150 | public String getDrawText() { 151 | String s = getText(); 152 | if (isEnabled && isFocused && (cursorCounter / 6) % 2 == 0) { 153 | s += "_"; 154 | } 155 | return s; 156 | } 157 | 158 | public void drawText() { 159 | drawString(fontRenderer, getDrawText(), x + 4, y + height / 2 - 4, getTextColour()); 160 | } 161 | 162 | public int getTextColour() { 163 | return isEnabled ? 0xe0e0e0 : 0x707070; 164 | } 165 | 166 | public GuiCCTextField setMaxStringLength(int i) { 167 | maxStringLength = i; 168 | return this; 169 | } 170 | 171 | public GuiCCTextField setAllowedCharacters(String s) { 172 | allowedCharacters = s; 173 | return this; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/gui/GuiScrollPane.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.gui; 2 | 3 | import codechicken.lib.math.MathHelper; 4 | import codechicken.lib.vec.Rectangle4i; 5 | 6 | import java.awt.*; 7 | 8 | public abstract class GuiScrollPane extends GuiWidget { 9 | protected int scrollclicky = -1; 10 | protected float scrollpercent; 11 | protected int scrollmousey; 12 | protected float percentscrolled; 13 | 14 | public int marginleft; 15 | public int margintop; 16 | public int marginright; 17 | public int marginbottom; 18 | 19 | public GuiScrollPane(int x, int y, int width, int height) { 20 | super(x, y, width, height); 21 | } 22 | 23 | public void setMargins(int left, int top, int right, int bottom) { 24 | marginleft = left; 25 | margintop = top; 26 | marginright = right; 27 | marginbottom = bottom; 28 | } 29 | 30 | public Rectangle windowBounds() { 31 | return new Rectangle(x + marginleft, y + margintop, width - marginleft - marginright, height - margintop - marginbottom); 32 | } 33 | 34 | public abstract int contentHeight(); 35 | 36 | public Dimension scrollbarDim() { 37 | int h = (int) ((windowBounds().getHeight() / contentHeight()) * height); 38 | return new Dimension(5, h > height ? height : h < height / 15 ? height / 15 : h); 39 | } 40 | 41 | public Rectangle scrollbarBounds() { 42 | Dimension dim = scrollbarDim(); 43 | return new Rectangle(x + width - dim.width, y + (int) ((height - dim.height) * percentscrolled + 0.4999), dim.width, dim.height); 44 | } 45 | 46 | public void scrollUp() { 47 | scroll(-5); 48 | } 49 | 50 | public void scrollDown() { 51 | scroll(5); 52 | } 53 | 54 | public void scroll(int i) { 55 | percentscrolled += i * height / (float) (2 * contentHeight()); 56 | calculatePercentScrolled(); 57 | } 58 | 59 | public void calculatePercentScrolled() { 60 | int barempty = height - scrollbarDim().height; 61 | if (isScrolling()) { 62 | int scrolldiff = scrollmousey - scrollclicky; 63 | percentscrolled = scrolldiff / (float) barempty + scrollpercent; 64 | } 65 | percentscrolled = (float) MathHelper.clip(percentscrolled, 0, 1); 66 | } 67 | 68 | public boolean isScrolling() { 69 | return scrollclicky >= 0; 70 | } 71 | 72 | public boolean hasScrollbar() { 73 | return contentHeight() > height; 74 | } 75 | 76 | /** 77 | * @return -1 for left, 0 for none, 1 for right 78 | */ 79 | public int scrollbarGuideAlignment() { 80 | return -1; 81 | } 82 | 83 | public void showSlot(int sloty, int slotHeight) { 84 | Rectangle w = windowBounds(); 85 | if (sloty + slotHeight > w.y + w.height) { 86 | int diff = sloty - (w.y + w.height - slotHeight); 87 | percentscrolled += diff / (double) (contentHeight() - w.height); 88 | calculatePercentScrolled(); 89 | } else if (sloty < w.y) { 90 | int diff = w.y - sloty; 91 | percentscrolled -= diff / (double) (contentHeight() - w.height); 92 | calculatePercentScrolled(); 93 | } 94 | } 95 | 96 | @Override 97 | public void mouseClicked(int mx, int my, int button) { 98 | Rectangle sbar = scrollbarBounds(); 99 | Rectangle w = windowBounds(); 100 | int barempty = height - sbar.height; 101 | 102 | if (button == 0 && 103 | sbar.height < height && //the scroll bar can move (not full length) 104 | mx >= sbar.x && mx <= sbar.x + sbar.width && 105 | my >= y && my <= y + height)//in the scroll pane 106 | { 107 | if (my < sbar.y) { 108 | percentscrolled = (my - y) / (float) barempty; 109 | calculatePercentScrolled(); 110 | } else if (my > sbar.y + sbar.height) { 111 | percentscrolled = (my - y - sbar.height + 1) / (float) barempty; 112 | calculatePercentScrolled(); 113 | } else { 114 | scrollclicky = my; 115 | scrollpercent = percentscrolled; 116 | scrollmousey = my; 117 | } 118 | } else if (w.contains(mx, my)) { 119 | slotDown(mx - w.x, my - w.y + scrolledPixels(), button); 120 | } 121 | } 122 | 123 | /** 124 | * Mouse down on slot area 125 | * Coordinates relative to slot content area 126 | */ 127 | public void slotDown(int mx, int my, int button) { 128 | } 129 | 130 | /** 131 | * Mouse up on slot area 132 | * Coordinates relative to slot content area 133 | */ 134 | public void slotUp(int mx, int my, int button) { 135 | } 136 | 137 | @Override 138 | public void mouseReleased(int mx, int my, int button) { 139 | Rectangle w = windowBounds(); 140 | if (isScrolling() && button == 0)//we were scrolling and we released mouse 141 | { 142 | scrollclicky = -1; 143 | } else if (w.contains(mx, my)) { 144 | slotUp(mx - w.x, my - w.y + scrolledPixels(), button); 145 | } 146 | } 147 | 148 | @Override 149 | public void mouseDragged(int mousex, int mousey, int button, long time) { 150 | if (isScrolling()) { 151 | int scrolldiff = mousey - scrollclicky; 152 | int sbarh = scrollbarDim().height; 153 | int barupallowed = (int) ((height - sbarh) * scrollpercent + 0.5); 154 | int bardownallowed = (height - sbarh) - barupallowed; 155 | 156 | if (-scrolldiff > barupallowed) { 157 | scrollmousey = scrollclicky - barupallowed; 158 | } else if (scrolldiff > bardownallowed) { 159 | scrollmousey = scrollclicky + bardownallowed; 160 | } else { 161 | scrollmousey = mousey; 162 | } 163 | 164 | calculatePercentScrolled(); 165 | } 166 | } 167 | 168 | public int scrolledPixels() { 169 | int scrolled = (int) ((contentHeight() - windowBounds().height) * percentscrolled + 0.5); 170 | if (scrolled < 0) { 171 | scrolled = 0; 172 | } 173 | return scrolled; 174 | } 175 | 176 | public Rectangle4i bounds() { 177 | return new Rectangle4i(x, y, width, height); 178 | } 179 | 180 | public boolean contains(int mx, int my) { 181 | return bounds().contains(mx, my); 182 | } 183 | 184 | @Override 185 | public void draw(int mx, int my, float frame) { 186 | Rectangle w = windowBounds(); 187 | drawBackground(frame); 188 | drawContent(mx - w.x, my + scrolledPixels() - w.y, frame); 189 | drawOverlay(frame); 190 | drawScrollbar(frame); 191 | } 192 | 193 | public void drawBackground(float frame) { 194 | drawRect(x, y, x + width, y + height, 0xff000000); 195 | } 196 | 197 | public abstract void drawContent(int mx, int my, float frame); 198 | 199 | public void drawOverlay(float frame) { 200 | //outlines 201 | drawRect(x, y - 1, x + width, y, 0xffa0a0a0);//top 202 | drawRect(x, y + height, x + width, y + height + 1, 0xffa0a0a0);//bottom 203 | drawRect(x - 1, y - 1, x, y + height + 1, 0xffa0a0a0);//left 204 | drawRect(x + width, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0);//right 205 | } 206 | 207 | public void drawScrollbar(float frame) { 208 | Rectangle r = scrollbarBounds(); 209 | 210 | drawRect(r.x, r.y, r.x + r.width, r.y + r.height, 0xFF8B8B8B);//corners 211 | drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, 0xFFF0F0F0);//topleft up 212 | drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, 0xFF555555);//bottom right down 213 | drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, 0xFFC6C6C6);//scrollbar 214 | 215 | int algn = scrollbarGuideAlignment(); 216 | if (algn != 0) { 217 | drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, 0xFF808080);//lineguide 218 | } 219 | } 220 | 221 | } 222 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/ObfuscationRun.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import com.google.common.base.Function; 4 | import org.objectweb.asm.ClassVisitor; 5 | import org.objectweb.asm.commons.RemappingClassAdapter; 6 | import org.objectweb.asm.tree.ClassNode; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.File; 10 | import java.io.FileReader; 11 | import java.io.PrintStream; 12 | import java.text.DecimalFormat; 13 | import java.util.LinkedList; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | public class ObfuscationRun implements ILogStreams { 18 | public final ObfDirection obfDir; 19 | public final ObfuscationMap obf; 20 | public final ObfRemapper obfMapper; 21 | public final ConstantObfuscator cstMappper; 22 | 23 | public File[] mappings; 24 | public Map config; 25 | 26 | private PrintStream out = System.out; 27 | private PrintStream err = System.err; 28 | private PrintStream quietStream = new PrintStream(DummyOutputStream.instance); 29 | 30 | private boolean verbose; 31 | private boolean quiet; 32 | 33 | public boolean clean; 34 | private long startTime; 35 | private boolean finished; 36 | 37 | public ObfuscationRun(boolean obfuscate, File[] mappings, Map config) { 38 | obfDir = new ObfDirection().setObfuscate(obfuscate); 39 | this.mappings = mappings; 40 | this.config = config; 41 | 42 | obf = new ObfuscationMap().setLog(this); 43 | obfMapper = new ObfRemapper(obf, obfDir); 44 | cstMappper = new ConstantObfuscator(obfMapper, config.get("classConstantCalls").split(","), config.get("descConstantCalls").split(",")); 45 | } 46 | 47 | public ObfuscationRun setClean() { 48 | clean = true; 49 | return this; 50 | } 51 | 52 | public ObfuscationRun setVerbose() { 53 | verbose = true; 54 | return this; 55 | } 56 | 57 | public ObfuscationRun setQuiet() { 58 | quiet = true; 59 | return this; 60 | } 61 | 62 | public ObfuscationRun setOut(PrintStream p) { 63 | out = p; 64 | return this; 65 | } 66 | 67 | public PrintStream out() { 68 | return quiet ? quietStream : out; 69 | } 70 | 71 | public PrintStream fine() { 72 | return verbose ? out : quietStream; 73 | } 74 | 75 | public ObfuscationRun setErr(PrintStream p) { 76 | err = p; 77 | return this; 78 | } 79 | 80 | public PrintStream err() { 81 | return quiet ? quietStream : err; 82 | } 83 | 84 | public ObfuscationRun setSearge() { 85 | obfDir.setSearge(true); 86 | return this; 87 | } 88 | 89 | public ObfuscationRun setSeargeConstants() { 90 | obfDir.setSeargeConstants(true); 91 | return this; 92 | } 93 | 94 | public void start() { 95 | startTime = System.currentTimeMillis(); 96 | } 97 | 98 | public static Map fillDefaults(Map config) { 99 | if (!config.containsKey("excludedPackages")) { 100 | config.put("excludedPackages", "java/;sun/;javax/;scala/;" + "argo/;org/lwjgl/;org/objectweb/;org/bouncycastle/;com/google/"); 101 | } 102 | if (!config.containsKey("ignore")) { 103 | config.put("ignore", "."); 104 | } 105 | if (!config.containsKey("classConstantCalls")) { 106 | config.put("classConstantCalls", "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;)V," + 107 | "codechicken/lib/asm/ObfMapping.subclass(Ljava/lang/String;)Lcodechicken/lib/asm/ObfMapping;," + 108 | "codechicken/lib/asm/ObfMapping.(Lcodechicken/lib/asm/ObfMapping;Ljava/lang/String;)V"); 109 | } 110 | if (!config.containsKey("descConstantCalls")) { 111 | config.put("descConstantCalls", "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + 112 | "org/objectweb/asm/MethodVisitor.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + 113 | "org/objectweb/asm/tree/MethodNode.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + 114 | "org/objectweb/asm/MethodVisitor.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + 115 | "org/objectweb/asm/tree/MethodNode.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + 116 | "org/objectweb/asm/tree/MethodInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + 117 | "org/objectweb/asm/tree/FieldInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); 118 | } 119 | 120 | return config; 121 | } 122 | 123 | public static void processLines(File file, Function function) { 124 | try { 125 | BufferedReader reader = new BufferedReader(new FileReader(file)); 126 | String line; 127 | while ((line = reader.readLine()) != null) { 128 | function.apply(line); 129 | } 130 | reader.close(); 131 | } catch (Exception e) { 132 | throw new RuntimeException(e); 133 | } 134 | } 135 | 136 | public static void processFiles(File dir, Function function, boolean recursive) { 137 | for (File file : dir.listFiles()) { 138 | if (file.isDirectory() && recursive) { 139 | processFiles(file, function, recursive); 140 | } else { 141 | function.apply(file); 142 | } 143 | } 144 | } 145 | 146 | public static void deleteDir(File directory, boolean remove) { 147 | if (!directory.exists()) { 148 | if (!remove) { 149 | directory.mkdirs(); 150 | } 151 | return; 152 | } 153 | for (File file : directory.listFiles()) { 154 | if (file.isDirectory()) { 155 | deleteDir(file, true); 156 | } else { 157 | if (!file.delete()) { 158 | throw new RuntimeException("Delete Failed: " + file); 159 | } 160 | } 161 | } 162 | if (remove) { 163 | if (!directory.delete()) { 164 | throw new RuntimeException("Delete Failed: " + directory); 165 | } 166 | } 167 | } 168 | 169 | public static File[] parseConfDir(File confDir) { 170 | File srgDir = new File(confDir, "conf"); 171 | if (!srgDir.exists()) { 172 | srgDir = confDir; 173 | } 174 | 175 | File srgs = new File(srgDir, "packaged.srg"); 176 | if (!srgs.exists()) { 177 | srgs = new File(srgDir, "joined.srg"); 178 | } 179 | if (!srgs.exists()) { 180 | throw new RuntimeException("Could not find packaged.srg or joined.srg"); 181 | } 182 | 183 | File mapDir = new File(confDir, "mappings"); 184 | if (!mapDir.exists()) { 185 | mapDir = confDir; 186 | } 187 | 188 | File methods = new File(mapDir, "methods.csv"); 189 | if (!methods.exists()) { 190 | throw new RuntimeException("Could not find methods.csv"); 191 | } 192 | File fields = new File(mapDir, "fields.csv"); 193 | if (!fields.exists()) { 194 | throw new RuntimeException("Could not find fields.csv"); 195 | } 196 | 197 | return new File[] { srgs, methods, fields }; 198 | } 199 | 200 | public long startTime() { 201 | return startTime; 202 | } 203 | 204 | public void remap(ClassNode cnode, ClassVisitor cv) { 205 | cstMappper.transform(cnode); 206 | cnode.accept(new RemappingClassAdapter(cv, obfMapper)); 207 | } 208 | 209 | public static List getParents(ClassNode cnode) { 210 | List parents = new LinkedList(); 211 | if (cnode.superName != null) { 212 | parents.add(cnode.superName); 213 | } 214 | 215 | for (String s_interface : cnode.interfaces) { 216 | parents.add(s_interface); 217 | } 218 | 219 | return parents; 220 | } 221 | 222 | public void finish(boolean errored) { 223 | long millis = System.currentTimeMillis() - startTime; 224 | out().println((errored ? "Errored after" : "Done in ") + new DecimalFormat("0.00").format(millis / 1000D) + "s"); 225 | finished = true; 226 | } 227 | 228 | public boolean finished() { 229 | return finished; 230 | } 231 | 232 | public void parseMappings() { 233 | obf.parseMappings(mappings); 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/inventory/ContainerExtended.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.inventory; 2 | 3 | import codechicken.lib.packet.PacketCustom; 4 | import net.minecraft.entity.player.EntityPlayer; 5 | import net.minecraft.entity.player.EntityPlayerMP; 6 | import net.minecraft.entity.player.InventoryPlayer; 7 | import net.minecraft.inventory.*; 8 | import net.minecraft.item.ItemStack; 9 | 10 | import java.util.Arrays; 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | 14 | public abstract class ContainerExtended extends Container implements IContainerListener { 15 | public LinkedList playerCrafters = new LinkedList(); 16 | 17 | public ContainerExtended() { 18 | listeners.add(this); 19 | } 20 | 21 | @Override 22 | public void addListener(IContainerListener icrafting) { 23 | if (icrafting instanceof EntityPlayerMP) { 24 | playerCrafters.add((EntityPlayerMP) icrafting); 25 | sendContainerAndContentsToPlayer(this, getInventory(), Arrays.asList((EntityPlayerMP) icrafting)); 26 | detectAndSendChanges(); 27 | } else { 28 | super.addListener(icrafting); 29 | } 30 | } 31 | 32 | @Override 33 | public void removeListener(IContainerListener icrafting) { 34 | if (icrafting instanceof EntityPlayerMP) { 35 | playerCrafters.remove(icrafting); 36 | } else { 37 | super.removeListener(icrafting); 38 | } 39 | } 40 | 41 | @Override 42 | public void updateCraftingInventory(Container container, List list) { 43 | sendContainerAndContentsToPlayer(container, list, playerCrafters); 44 | } 45 | 46 | @Override 47 | public void sendAllWindowProperties(Container p_175173_1_, IInventory p_175173_2_) { 48 | } 49 | 50 | public void sendContainerAndContentsToPlayer(Container container, List list, List playerCrafters) { 51 | LinkedList largeStacks = new LinkedList(); 52 | for (int i = 0; i < list.size(); i++) { 53 | ItemStack stack = list.get(i); 54 | if (stack != null && stack.stackSize > Byte.MAX_VALUE) { 55 | list.set(i, null); 56 | largeStacks.add(stack); 57 | } else { 58 | largeStacks.add(null); 59 | } 60 | } 61 | 62 | for (EntityPlayerMP player : playerCrafters) { 63 | player.updateCraftingInventory(container, list); 64 | } 65 | 66 | for (int i = 0; i < largeStacks.size(); i++) { 67 | ItemStack stack = largeStacks.get(i); 68 | if (stack != null) { 69 | sendLargeStack(stack, i, playerCrafters); 70 | } 71 | } 72 | } 73 | 74 | public void sendLargeStack(ItemStack stack, int slot, List players) { 75 | } 76 | 77 | @Override 78 | public void sendProgressBarUpdate(Container container, int i, int j) { 79 | for (EntityPlayerMP player : playerCrafters) { 80 | player.sendProgressBarUpdate(container, i, j); 81 | } 82 | } 83 | 84 | @Override 85 | public void sendSlotContents(Container container, int slot, ItemStack stack) { 86 | if (stack != null && stack.stackSize > Byte.MAX_VALUE) { 87 | sendLargeStack(stack, slot, playerCrafters); 88 | } else { 89 | for (EntityPlayerMP player : playerCrafters) { 90 | player.sendSlotContents(container, slot, stack); 91 | } 92 | } 93 | } 94 | 95 | @Override 96 | public ItemStack slotClick(int slot, int dragType, ClickType clickType, EntityPlayer player) { 97 | if (slot >= 0 && slot < inventorySlots.size()) { 98 | Slot actualSlot = getSlot(slot); 99 | if (actualSlot instanceof SlotHandleClicks) { 100 | return ((SlotHandleClicks) actualSlot).slotClick(this, player, dragType, clickType); 101 | } 102 | } 103 | return super.slotClick(slot, dragType, clickType, player); 104 | } 105 | 106 | @Override 107 | public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int slotIndex) { 108 | ItemStack transferredStack = null; 109 | Slot slot = inventorySlots.get(slotIndex); 110 | 111 | if (slot != null && slot.getHasStack()) { 112 | ItemStack stack = slot.getStack(); 113 | transferredStack = stack.copy(); 114 | 115 | if (!doMergeStackAreas(slotIndex, stack)) { 116 | return null; 117 | } 118 | 119 | if (stack.stackSize == 0) { 120 | slot.putStack(null); 121 | } else { 122 | slot.onSlotChanged(); 123 | } 124 | } 125 | 126 | return transferredStack; 127 | } 128 | 129 | @Override 130 | public boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean reverse) { 131 | boolean merged = false; 132 | int slotIndex = reverse ? endIndex - 1 : startIndex; 133 | 134 | if (stack == null) { 135 | return false; 136 | } 137 | 138 | if (stack.isStackable())//search for stacks to increase 139 | { 140 | while (stack.stackSize > 0 && (reverse ? slotIndex >= startIndex : slotIndex < endIndex)) { 141 | Slot slot = inventorySlots.get(slotIndex); 142 | ItemStack slotStack = slot.getStack(); 143 | 144 | if (slotStack != null && slotStack.getItem() == stack.getItem() && 145 | (!stack.getHasSubtypes() || stack.getItemDamage() == slotStack.getItemDamage()) && 146 | ItemStack.areItemStackTagsEqual(stack, slotStack)) { 147 | int totalStackSize = slotStack.stackSize + stack.stackSize; 148 | int maxStackSize = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit()); 149 | if (totalStackSize <= maxStackSize) { 150 | stack.stackSize = 0; 151 | slotStack.stackSize = totalStackSize; 152 | slot.onSlotChanged(); 153 | merged = true; 154 | } else if (slotStack.stackSize < maxStackSize) { 155 | stack.stackSize -= maxStackSize - slotStack.stackSize; 156 | slotStack.stackSize = maxStackSize; 157 | slot.onSlotChanged(); 158 | merged = true; 159 | } 160 | } 161 | 162 | slotIndex += reverse ? -1 : 1; 163 | } 164 | } 165 | 166 | if (stack.stackSize > 0)//normal transfer :) 167 | { 168 | slotIndex = reverse ? endIndex - 1 : startIndex; 169 | 170 | while (stack.stackSize > 0 && (reverse ? slotIndex >= startIndex : slotIndex < endIndex)) { 171 | Slot slot = this.inventorySlots.get(slotIndex); 172 | 173 | if (!slot.getHasStack() && slot.isItemValid(stack)) { 174 | int maxStackSize = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit()); 175 | if (stack.stackSize <= maxStackSize) { 176 | slot.putStack(stack.copy()); 177 | slot.onSlotChanged(); 178 | stack.stackSize = 0; 179 | merged = true; 180 | } else { 181 | slot.putStack(stack.splitStack(maxStackSize)); 182 | slot.onSlotChanged(); 183 | merged = true; 184 | } 185 | } 186 | 187 | slotIndex += reverse ? -1 : 1; 188 | } 189 | } 190 | 191 | return merged; 192 | } 193 | 194 | public boolean doMergeStackAreas(int slotIndex, ItemStack stack) { 195 | return false; 196 | } 197 | 198 | protected void bindPlayerInventory(InventoryPlayer inventoryPlayer) { 199 | bindPlayerInventory(inventoryPlayer, 8, 84); 200 | } 201 | 202 | protected void bindPlayerInventory(InventoryPlayer inventoryPlayer, int x, int y) { 203 | for (int row = 0; row < 3; row++) { 204 | for (int col = 0; col < 9; col++) { 205 | addSlotToContainer(new Slot(inventoryPlayer, col + row * 9 + 9, x + col * 18, y + row * 18)); 206 | } 207 | } 208 | for (int slot = 0; slot < 9; slot++) { 209 | addSlotToContainer(new Slot(inventoryPlayer, slot, x + slot * 18, y + 58)); 210 | } 211 | } 212 | 213 | @Override 214 | public boolean canInteractWith(EntityPlayer var1) { 215 | return true; 216 | } 217 | 218 | public void sendContainerPacket(PacketCustom packet) { 219 | for (EntityPlayerMP player : playerCrafters) { 220 | packet.sendToPlayer(player); 221 | } 222 | } 223 | 224 | /** 225 | * May be called from a client packet handler to handle additional info 226 | */ 227 | public void handleOutputPacket(PacketCustom packet) { 228 | } 229 | 230 | /** 231 | * May be called from a server packet handler to handle additional info 232 | */ 233 | public void handleInputPacket(PacketCustom packet) { 234 | } 235 | 236 | /** 237 | * May be called from a server packet handler to handle client input 238 | */ 239 | public void handleGuiChange(int ID, int value) { 240 | } 241 | 242 | public void sendProgressBarUpdate(int barID, int value) { 243 | for (IContainerListener crafting : listeners) { 244 | crafting.sendProgressBarUpdate(this, barID, value); 245 | } 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/main/java/codechicken/obfuscator/ObfuscationMap.java: -------------------------------------------------------------------------------- 1 | package codechicken.obfuscator; 2 | 3 | import codechicken.lib.asm.ObfMapping; 4 | import com.google.common.base.Function; 5 | import com.google.common.collect.ArrayListMultimap; 6 | 7 | import java.io.File; 8 | import java.util.HashMap; 9 | import java.util.HashSet; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Map.Entry; 13 | 14 | public class ObfuscationMap { 15 | public class ObfuscationEntry { 16 | public final ObfMapping obf; 17 | public final ObfMapping srg; 18 | public final ObfMapping mcp; 19 | 20 | public ObfuscationEntry(ObfMapping obf, ObfMapping srg, ObfMapping mcp) { 21 | this.obf = obf; 22 | this.srg = srg; 23 | this.mcp = mcp; 24 | } 25 | } 26 | 27 | private class ClassEntry extends ObfuscationEntry { 28 | public Map mcpMap = new HashMap(); 29 | public Map srgMap = new HashMap(); 30 | public Map obfMap = new HashMap(); 31 | 32 | public ClassEntry(String obf, String srg) { 33 | super(new ObfMapping(obf, "", ""), new ObfMapping(srg, "", ""), new ObfMapping(srg, "", "")); 34 | } 35 | 36 | public ObfuscationEntry addEntry(ObfMapping obf_desc, ObfMapping srg_desc) { 37 | ObfuscationEntry entry = new ObfuscationEntry(obf_desc, srg_desc, srg_desc.copy()); 38 | obfMap.put(obf_desc.s_name.concat(obf_desc.s_desc), entry); 39 | srgMap.put(srg_desc.s_name, entry); 40 | 41 | if (srg_desc.s_name.startsWith("field_") || srg_desc.s_name.startsWith("func_")) { 42 | srgMemberMap.put(srg_desc.s_name, entry); 43 | } 44 | 45 | return entry; 46 | } 47 | 48 | public void inheritFrom(ClassEntry p) { 49 | inherit(obfMap, p.obfMap); 50 | inherit(srgMap, p.srgMap); 51 | inherit(mcpMap, p.mcpMap); 52 | } 53 | 54 | private void inherit(Map child, Map parent) { 55 | for (Entry e : parent.entrySet()) { 56 | if (!child.containsKey(e.getKey())) { 57 | child.put(e.getKey(), e.getValue()); 58 | } 59 | } 60 | } 61 | } 62 | 63 | private Map srgMap = new HashMap(); 64 | private Map obfMap = new HashMap(); 65 | private ArrayListMultimap srgMemberMap = ArrayListMultimap.create(); 66 | 67 | private IHeirachyEvaluator heirachyEvaluator; 68 | private HashSet mappedClasses = new HashSet(); 69 | public ILogStreams log = SystemLogStreams.inst; 70 | 71 | public ObfuscationMap setHeirachyEvaluator(IHeirachyEvaluator eval) { 72 | heirachyEvaluator = eval; 73 | return this; 74 | } 75 | 76 | public ObfuscationMap setLog(ILogStreams log) { 77 | this.log = log; 78 | return this; 79 | } 80 | 81 | public ObfuscationEntry addClass(String obf, String srg) { 82 | return addEntry(new ObfMapping(obf, "", ""), new ObfMapping(srg, "", "")); 83 | } 84 | 85 | public ObfuscationEntry addField(String obf_owner, String obf_name, String srg_owner, String srg_name) { 86 | return addEntry(new ObfMapping(obf_owner, obf_name, ""), new ObfMapping(srg_owner, srg_name, "")); 87 | } 88 | 89 | public ObfuscationEntry addMethod(String obf_owner, String obf_name, String obf_desc, String srg_owner, String srg_name, String srg_desc) { 90 | return addEntry(new ObfMapping(obf_owner, obf_name, obf_desc), new ObfMapping(srg_owner, srg_name, srg_desc)); 91 | } 92 | 93 | public ObfuscationEntry addEntry(ObfMapping obf_desc, ObfMapping srg_desc) { 94 | ClassEntry e = srgMap.get(srg_desc.s_owner); 95 | if (e == null) { 96 | e = new ClassEntry(obf_desc.s_owner, srg_desc.s_owner); 97 | obfMap.put(obf_desc.s_owner, e); 98 | srgMap.put(srg_desc.s_owner, e); 99 | } 100 | if (obf_desc.s_name.length() > 0) { 101 | return e.addEntry(obf_desc, srg_desc); 102 | } 103 | 104 | return e; 105 | } 106 | 107 | public void addMcpName(String srg_name, String mcp_name) { 108 | List entries = srgMemberMap.get(srg_name); 109 | if (entries.isEmpty()) { 110 | log.err().println("Tried to add mcp name (" + mcp_name + ") for unknown srg key (" + srg_name + ")"); 111 | return; 112 | } 113 | for (ObfuscationEntry entry : entries) { 114 | entry.mcp.s_name = mcp_name; 115 | srgMap.get(entry.srg.s_owner).mcpMap.put(entry.mcp.s_name.concat(entry.mcp.s_desc), entry); 116 | } 117 | } 118 | 119 | public ObfuscationEntry lookupSrg(String srg_key) { 120 | List list = srgMemberMap.get(srg_key); 121 | return list.isEmpty() ? null : list.get(0); 122 | } 123 | 124 | public ObfuscationEntry lookupMcpClass(String name) { 125 | return srgMap.get(name); 126 | } 127 | 128 | public ObfuscationEntry lookupObfClass(String name) { 129 | return obfMap.get(name); 130 | } 131 | 132 | public ObfuscationEntry lookupMcpField(String owner, String name) { 133 | return lookupMcpMethod(owner, name, ""); 134 | } 135 | 136 | public ObfuscationEntry lookupSrgField(String owner, String name) { 137 | if (name.startsWith("field_")) { 138 | ObfuscationEntry e = lookupSrg(name); 139 | if (e != null) { 140 | return e; 141 | } 142 | } 143 | 144 | evaluateHeirachy(owner); 145 | ClassEntry e = srgMap.get(owner); 146 | return e == null ? null : e.srgMap.get(name); 147 | } 148 | 149 | public ObfuscationEntry lookupObfField(String owner, String name) { 150 | return lookupObfMethod(owner, name, ""); 151 | } 152 | 153 | public ObfuscationEntry lookupMcpMethod(String owner, String name, String desc) { 154 | evaluateHeirachy(owner); 155 | ClassEntry e = srgMap.get(owner); 156 | return e == null ? null : e.mcpMap.get(name.concat(desc)); 157 | } 158 | 159 | public ObfuscationEntry lookupObfMethod(String owner, String name, String desc) { 160 | evaluateHeirachy(owner); 161 | ClassEntry e = obfMap.get(owner); 162 | return e == null ? null : e.obfMap.get(name.concat(desc)); 163 | } 164 | 165 | private boolean isMapped(ObfuscationEntry desc) { 166 | return mappedClasses.contains(desc.srg.s_owner); 167 | } 168 | 169 | private ObfuscationEntry getOrCreateClassEntry(String name) { 170 | ObfuscationEntry e = lookupObfClass(name); 171 | if (e == null) { 172 | e = lookupMcpClass(name); 173 | } 174 | if (e == null) { 175 | e = addClass(name, name);//if the class isn't in obf or srg maps, it must be a custom mod class with no name change. 176 | } 177 | return e; 178 | } 179 | 180 | public ObfuscationEntry evaluateHeirachy(String name) { 181 | ObfuscationEntry desc = getOrCreateClassEntry(name); 182 | if (isMapped(desc)) { 183 | return desc; 184 | } 185 | 186 | mappedClasses.add(desc.srg.s_owner); 187 | if (heirachyEvaluator == null) { 188 | throw new IllegalArgumentException("Cannot call method/field mappings if a heirachy evaluator is not set."); 189 | } 190 | 191 | if (!heirachyEvaluator.isLibClass(desc)) { 192 | List parents = heirachyEvaluator.getParents(desc); 193 | if (parents == null) { 194 | log.err().println("Could not find class: " + desc.srg.s_owner); 195 | } else { 196 | for (String parent : parents) { 197 | inherit(desc, evaluateHeirachy(parent)); 198 | } 199 | } 200 | } 201 | 202 | return desc; 203 | } 204 | 205 | public void inherit(ObfuscationEntry desc, ObfuscationEntry p_desc) { 206 | inherit(desc.srg.s_owner, p_desc.srg.s_owner); 207 | } 208 | 209 | public void inherit(String name, String parent) { 210 | ClassEntry e = srgMap.get(name); 211 | if (e == null) { 212 | throw new IllegalStateException("Tried to inerit to an undefined class: " + name + " extends " + parent); 213 | } 214 | ClassEntry p = srgMap.get(parent); 215 | if (p == null) { 216 | throw new IllegalStateException("Tried to inerit from undefired parent: " + name + " extends " + parent); 217 | } 218 | e.inheritFrom(p); 219 | } 220 | 221 | public void parseMappings(File[] mappings) { 222 | parseSRGS(mappings[0]); 223 | parseCSV(mappings[1]); 224 | parseCSV(mappings[2]); 225 | } 226 | 227 | public static String[] splitLast(String s, char c) { 228 | int i = s.lastIndexOf(c); 229 | return new String[] { s.substring(0, i), s.substring(i + 1) }; 230 | } 231 | 232 | public static String[] split4(String s, char c) { 233 | String[] split = new String[4]; 234 | int i2 = s.indexOf(c); 235 | split[0] = s.substring(0, i2); 236 | int i = i2 + 1; 237 | i2 = s.indexOf(c, i); 238 | split[1] = s.substring(i, i2); 239 | i = i2 + 1; 240 | i2 = s.indexOf(c, i); 241 | split[2] = s.substring(i, i2); 242 | i = i2 + 1; 243 | i2 = s.indexOf(c, i); 244 | split[3] = s.substring(i); 245 | return split; 246 | } 247 | 248 | private void parseSRGS(File srgs) { 249 | log.out().println("Parsing " + srgs.getName()); 250 | 251 | Function function = new Function() { 252 | @Override 253 | public Void apply(String line) { 254 | int hpos = line.indexOf('#'); 255 | if (hpos > 0) { 256 | line = line.substring(0, hpos).trim(); 257 | } 258 | if (line.startsWith("CL: ")) { 259 | String[] params = splitLast(line.substring(4), ' '); 260 | addClass(params[0], params[1]); 261 | } else if (line.startsWith("FD: ")) { 262 | String[] params = splitLast(line.substring(4), ' '); 263 | String[] p1 = splitLast(params[0], '/'); 264 | String[] p2 = splitLast(params[1], '/'); 265 | addField(p1[0], p1[1], p2[0], p2[1]); 266 | return null; 267 | } else if (line.startsWith("MD: ")) { 268 | String[] params = split4(line.substring(4), ' '); 269 | String[] p1 = splitLast(params[0], '/'); 270 | String[] p2 = splitLast(params[2], '/'); 271 | addMethod(p1[0], p1[1], params[1], p2[0], p2[1], params[3]); 272 | return null; 273 | } 274 | return null; 275 | } 276 | }; 277 | 278 | ObfuscationRun.processLines(srgs, function); 279 | } 280 | 281 | private void parseCSV(File csv) { 282 | log.out().println("Parsing " + csv.getName()); 283 | 284 | Function function = new Function() { 285 | @Override 286 | public Void apply(String line) { 287 | if (line.startsWith("func_") || line.startsWith("field_")) { 288 | int i = line.indexOf(','); 289 | String srg = line.substring(0, i); 290 | int i2 = i + 1; 291 | i = line.indexOf(',', i2); 292 | String mcp = line.substring(i2, i); 293 | 294 | addMcpName(srg, mcp); 295 | } 296 | return null; 297 | } 298 | }; 299 | 300 | ObfuscationRun.processLines(csv, function); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/main/java/codechicken/core/launch/DepLoader.java: -------------------------------------------------------------------------------- 1 | package codechicken.core.launch; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParser; 6 | import net.minecraft.launchwrapper.LaunchClassLoader; 7 | import net.minecraftforge.fml.common.FMLLog; 8 | import net.minecraftforge.fml.common.asm.transformers.ModAccessTransformer; 9 | import net.minecraftforge.fml.common.versioning.ComparableVersion; 10 | import net.minecraftforge.fml.relauncher.*; 11 | import org.apache.logging.log4j.Level; 12 | import org.apache.logging.log4j.LogManager; 13 | import org.apache.logging.log4j.Logger; 14 | import sun.misc.URLClassPath; 15 | import sun.net.util.URLUtil; 16 | 17 | import javax.swing.*; 18 | import javax.swing.event.HyperlinkEvent; 19 | import javax.swing.event.HyperlinkListener; 20 | import java.awt.*; 21 | import java.awt.Dialog.ModalityType; 22 | import java.awt.event.WindowAdapter; 23 | import java.awt.event.WindowEvent; 24 | import java.beans.PropertyChangeEvent; 25 | import java.beans.PropertyChangeListener; 26 | import java.io.*; 27 | import java.lang.reflect.Field; 28 | import java.lang.reflect.Method; 29 | import java.net.MalformedURLException; 30 | import java.net.URL; 31 | import java.net.URLClassLoader; 32 | import java.net.URLConnection; 33 | import java.nio.ByteBuffer; 34 | import java.util.*; 35 | import java.util.List; 36 | import java.util.Map.Entry; 37 | import java.util.jar.Attributes; 38 | import java.util.jar.JarFile; 39 | import java.util.regex.Matcher; 40 | import java.util.regex.Pattern; 41 | import java.util.regex.PatternSyntaxException; 42 | import java.util.zip.ZipEntry; 43 | import java.util.zip.ZipFile; 44 | 45 | /** 46 | * For autodownloading stuff. 47 | * This is really unoriginal, mostly ripped off FML, credits to cpw. 48 | */ 49 | @Deprecated 50 | public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { 51 | private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); 52 | private static final String owner = "DepLoader"; 53 | private static DepLoadInst inst; 54 | private static final Logger logger = LogManager.getLogger(owner); 55 | 56 | public interface IYellAtPeople { 57 | void addYellingData(String data); 58 | 59 | void displayYellingData(); 60 | } 61 | 62 | public static class YellGui extends JOptionPane implements IYellAtPeople { 63 | private ArrayList yellingData = new ArrayList(); 64 | 65 | @Override 66 | public void addYellingData(String data) { 67 | yellingData.add(data); 68 | } 69 | 70 | @Override 71 | public void displayYellingData() { 72 | StringBuilder builder = new StringBuilder(); 73 | builder.append(""); 74 | for (String data : yellingData) { 75 | builder.append("
"); 76 | builder.append(data); 77 | } 78 | builder.append(""); 79 | JEditorPane ep = new JEditorPane("text/html", builder.toString()); 80 | ep.setAutoscrolls(true); 81 | ep.setEditable(false); 82 | ep.setOpaque(false); 83 | ep.addHyperlinkListener(new HyperlinkListener() { 84 | @Override 85 | public void hyperlinkUpdate(HyperlinkEvent event) { 86 | try { 87 | if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { 88 | Desktop.getDesktop().browse(event.getURL().toURI()); 89 | } 90 | } catch (Exception ignored) { 91 | } 92 | } 93 | }); 94 | JOptionPane.showMessageDialog(null, ep, "DepLoader is Deprecated!", -1); 95 | } 96 | } 97 | 98 | public static class YellServer implements IYellAtPeople { 99 | private ArrayList yellingData = new ArrayList(); 100 | 101 | @Override 102 | public void addYellingData(String data) { 103 | yellingData.add(data); 104 | } 105 | 106 | @Override 107 | public void displayYellingData() { 108 | for (String string : yellingData) { 109 | FMLLog.severe(string); 110 | } 111 | try { 112 | Thread.sleep(10000); 113 | } catch (InterruptedException ignored) { 114 | } 115 | } 116 | } 117 | 118 | public interface IDownloadDisplay { 119 | void resetProgress(int sizeGuess); 120 | 121 | void setPokeThread(Thread currentThread); 122 | 123 | void updateProgress(int fullLength); 124 | 125 | boolean shouldStopIt(); 126 | 127 | void updateProgressString(String string, Object... data); 128 | 129 | Object makeDialog(); 130 | 131 | void showErrorDialog(String name, String url); 132 | } 133 | 134 | @SuppressWarnings("serial") 135 | public static class Downloader extends JOptionPane implements IDownloadDisplay { 136 | private JDialog container; 137 | private JLabel currentActivity; 138 | private JProgressBar progress; 139 | boolean stopIt; 140 | Thread pokeThread; 141 | 142 | private Box makeProgressPanel() { 143 | Box box = Box.createVerticalBox(); 144 | box.add(Box.createRigidArea(new Dimension(0, 10))); 145 | JLabel welcomeLabel = new JLabel("" + owner + " is setting up your minecraft environment"); 146 | box.add(welcomeLabel); 147 | welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); 148 | welcomeLabel = new JLabel("Please wait, " + owner + " has some tasks to do before you can play"); 149 | welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); 150 | box.add(welcomeLabel); 151 | box.add(Box.createRigidArea(new Dimension(0, 10))); 152 | currentActivity = new JLabel("Currently doing ..."); 153 | box.add(currentActivity); 154 | box.add(Box.createRigidArea(new Dimension(0, 10))); 155 | progress = new JProgressBar(0, 100); 156 | progress.setStringPainted(true); 157 | box.add(progress); 158 | box.add(Box.createRigidArea(new Dimension(0, 30))); 159 | return box; 160 | } 161 | 162 | @Override 163 | public JDialog makeDialog() { 164 | if (container != null) { 165 | return container; 166 | } 167 | 168 | setMessageType(JOptionPane.INFORMATION_MESSAGE); 169 | setMessage(makeProgressPanel()); 170 | setOptions(new Object[] { "Stop" }); 171 | addPropertyChangeListener(new PropertyChangeListener() { 172 | @Override 173 | public void propertyChange(PropertyChangeEvent evt) { 174 | if (evt.getSource() == Downloader.this && evt.getPropertyName() == VALUE_PROPERTY) { 175 | requestClose("This will stop minecraft from launching\nAre you sure you want to do this?"); 176 | } 177 | } 178 | }); 179 | container = new JDialog(null, "Hello", ModalityType.MODELESS); 180 | container.setResizable(false); 181 | container.setLocationRelativeTo(null); 182 | container.add(this); 183 | this.updateUI(); 184 | container.pack(); 185 | container.setMinimumSize(container.getPreferredSize()); 186 | container.setVisible(true); 187 | container.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 188 | container.addWindowListener(new WindowAdapter() { 189 | @Override 190 | public void windowClosing(WindowEvent e) { 191 | requestClose("Closing this window will stop minecraft from launching\nAre you sure you wish to do this?"); 192 | } 193 | }); 194 | return container; 195 | } 196 | 197 | protected void requestClose(String message) { 198 | int shouldClose = JOptionPane.showConfirmDialog(container, message, "Are you sure you want to stop?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 199 | if (shouldClose == JOptionPane.YES_OPTION) { 200 | container.dispose(); 201 | } 202 | 203 | stopIt = true; 204 | if (pokeThread != null) { 205 | pokeThread.interrupt(); 206 | } 207 | } 208 | 209 | @Override 210 | public void updateProgressString(String progressUpdate, Object... data) { 211 | //FMLLog.finest(progressUpdate, data); 212 | if (currentActivity != null) { 213 | currentActivity.setText(String.format(progressUpdate, data)); 214 | } 215 | } 216 | 217 | @Override 218 | public void resetProgress(int sizeGuess) { 219 | if (progress != null) { 220 | progress.getModel().setRangeProperties(0, 0, 0, sizeGuess, false); 221 | } 222 | } 223 | 224 | @Override 225 | public void updateProgress(int fullLength) { 226 | if (progress != null) { 227 | progress.getModel().setValue(fullLength); 228 | } 229 | } 230 | 231 | @Override 232 | public void setPokeThread(Thread currentThread) { 233 | this.pokeThread = currentThread; 234 | } 235 | 236 | @Override 237 | public boolean shouldStopIt() { 238 | return stopIt; 239 | } 240 | 241 | @Override 242 | public void showErrorDialog(String name, String url) { 243 | JEditorPane ep = new JEditorPane("text/html", "" + owner + " was unable to download required library " + name + "
Check your internet connection and try restarting or download it manually from" + "
" + url + " and put it in your mods folder" + ""); 244 | 245 | ep.setEditable(false); 246 | ep.setOpaque(false); 247 | ep.addHyperlinkListener(new HyperlinkListener() { 248 | @Override 249 | public void hyperlinkUpdate(HyperlinkEvent event) { 250 | try { 251 | if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { 252 | Desktop.getDesktop().browse(event.getURL().toURI()); 253 | } 254 | } catch (Exception e) { 255 | } 256 | } 257 | }); 258 | 259 | JOptionPane.showMessageDialog(null, ep, "A download error has occured", JOptionPane.ERROR_MESSAGE); 260 | } 261 | } 262 | 263 | public static class DummyDownloader implements IDownloadDisplay { 264 | @Override 265 | public void resetProgress(int sizeGuess) { 266 | } 267 | 268 | @Override 269 | public void setPokeThread(Thread currentThread) { 270 | } 271 | 272 | @Override 273 | public void updateProgress(int fullLength) { 274 | } 275 | 276 | @Override 277 | public boolean shouldStopIt() { 278 | return false; 279 | } 280 | 281 | @Override 282 | public void updateProgressString(String string, Object... data) { 283 | } 284 | 285 | @Override 286 | public Object makeDialog() { 287 | return null; 288 | } 289 | 290 | @Override 291 | public void showErrorDialog(String name, String url) { 292 | } 293 | } 294 | 295 | public static class VersionedFile { 296 | public final Pattern pattern; 297 | public final String filename; 298 | public final ComparableVersion version; 299 | public final String name; 300 | 301 | public VersionedFile(String filename, Pattern pattern) { 302 | this.pattern = pattern; 303 | this.filename = filename; 304 | Matcher m = pattern.matcher(filename); 305 | if (m.matches()) { 306 | name = m.group(1); 307 | version = new ComparableVersion(m.group(2)); 308 | } else { 309 | name = null; 310 | version = null; 311 | } 312 | } 313 | 314 | public boolean matches() { 315 | return name != null; 316 | } 317 | } 318 | 319 | public static class Dependency { 320 | /** 321 | * Zip file to extract packed dependencies from 322 | */ 323 | public File source; 324 | public String repo; 325 | public String packed; 326 | public VersionedFile file; 327 | public String testClass; 328 | public boolean coreLib; 329 | 330 | public String existing; 331 | 332 | /** 333 | * Flag set to add this dep to the classpath immediately because it is required for a coremod. 334 | */ 335 | 336 | public Dependency(File source, String repo, String packed, VersionedFile file, String testClass, boolean coreLib) { 337 | this.source = source; 338 | this.repo = repo; 339 | this.packed = packed; 340 | this.file = file; 341 | this.coreLib = coreLib; 342 | this.testClass = testClass; 343 | } 344 | 345 | public void set(Dependency dep) { 346 | this.source = dep.source; 347 | this.repo = dep.repo; 348 | this.packed = dep.packed; 349 | this.file = dep.file; 350 | } 351 | } 352 | 353 | public static class DepLoadInst { 354 | private File modsDir; 355 | private File v_modsDir; 356 | private IDownloadDisplay downloadMonitor; 357 | private JDialog popupWindow; 358 | 359 | private Map depMap = new HashMap(); 360 | private HashSet depSet = new HashSet(); 361 | 362 | private File scanning; 363 | private LaunchClassLoader loader = (LaunchClassLoader) DepLoader.class.getClassLoader(); 364 | 365 | public DepLoadInst() { 366 | String mcVer = (String) FMLInjectionData.data()[4]; 367 | File mcDir = (File) FMLInjectionData.data()[6]; 368 | 369 | modsDir = new File(mcDir, "mods"); 370 | v_modsDir = new File(mcDir, "mods/" + mcVer); 371 | if (!v_modsDir.exists()) { 372 | v_modsDir.mkdirs(); 373 | } 374 | } 375 | 376 | private void addClasspath(File file) { 377 | try { 378 | loader.addURL(file.toURI().toURL()); 379 | } catch (MalformedURLException e) { 380 | throw new RuntimeException(e); 381 | } 382 | } 383 | 384 | private void deleteMod(File mod) { 385 | if (mod.delete()) { 386 | return; 387 | } 388 | 389 | try { 390 | URL url = mod.toURI().toURL(); 391 | Field f_ucp = URLClassLoader.class.getDeclaredField("ucp"); 392 | Field f_loaders = URLClassPath.class.getDeclaredField("loaders"); 393 | Field f_lmap = URLClassPath.class.getDeclaredField("lmap"); 394 | f_ucp.setAccessible(true); 395 | f_loaders.setAccessible(true); 396 | f_lmap.setAccessible(true); 397 | 398 | URLClassPath ucp = (URLClassPath) f_ucp.get(loader); 399 | Closeable loader = ((Map) f_lmap.get(ucp)).remove(URLUtil.urlNoFragString(url)); 400 | if (loader != null) { 401 | loader.close(); 402 | ((List) f_loaders.get(ucp)).remove(loader); 403 | } 404 | } catch (Exception e) { 405 | e.printStackTrace(); 406 | } 407 | 408 | if (!mod.delete()) { 409 | mod.deleteOnExit(); 410 | String msg = owner + " was unable to delete file " + mod.getPath() + " the game will now try to delete it on exit. If this dialog appears again, delete it manually."; 411 | logger.error(msg); 412 | if (!GraphicsEnvironment.isHeadless()) { 413 | JOptionPane.showMessageDialog(null, msg, "An update error has occured", JOptionPane.ERROR_MESSAGE); 414 | } 415 | 416 | System.exit(1); 417 | } 418 | } 419 | 420 | private void install(Dependency dep) { 421 | popupWindow = (JDialog) downloadMonitor.makeDialog(); 422 | 423 | if (!extract(dep)) { 424 | download(dep); 425 | } 426 | 427 | dep.existing = dep.file.filename; 428 | scanDepInfo(new File(v_modsDir, dep.existing)); 429 | } 430 | 431 | private boolean extract(Dependency dep) { 432 | if (dep.packed == null) { 433 | return false; 434 | } 435 | 436 | ZipFile zip = null; 437 | try { 438 | zip = new ZipFile(dep.source); 439 | ZipEntry libEntry = zip.getEntry(dep.packed + dep.file.filename); 440 | if (libEntry == null) { 441 | return false; 442 | } 443 | 444 | downloadMonitor.updateProgressString("Extracting file %s\n", dep.source.getPath() + '!' + libEntry.toString()); 445 | logger.info("Extracting file " + dep.source.getPath() + '!' + libEntry.toString()); 446 | 447 | download(zip.getInputStream(libEntry), (int) libEntry.getSize(), dep); 448 | 449 | downloadMonitor.updateProgressString("Extraction complete"); 450 | logger.info("Extraction complete"); 451 | } catch (Exception e) { 452 | installError(e, dep, "extraction"); 453 | } finally { 454 | try { 455 | if (zip != null) { 456 | zip.close(); 457 | } 458 | } catch (IOException e) { 459 | e.printStackTrace(); 460 | } 461 | } 462 | return true; 463 | } 464 | 465 | private void download(Dependency dep) { 466 | try { 467 | URL libDownload = new URL(dep.repo + dep.file.filename); 468 | downloadMonitor.updateProgressString("Downloading file %s", libDownload.toString()); 469 | logger.info("Downloading file " + libDownload.toString()); 470 | URLConnection connection = libDownload.openConnection(); 471 | connection.setConnectTimeout(5000); 472 | connection.setReadTimeout(5000); 473 | connection.setRequestProperty("User-Agent", "" + owner + " Downloader"); 474 | download(connection.getInputStream(), connection.getContentLength(), dep); 475 | downloadMonitor.updateProgressString("Download complete"); 476 | logger.info("Download complete"); 477 | } catch (Exception e) { 478 | installError(e, dep, "download"); 479 | } 480 | } 481 | 482 | private void installError(Exception e, Dependency dep, String s) { 483 | if (downloadMonitor.shouldStopIt()) { 484 | logger.error("You have stopped the " + s + " before it could complete"); 485 | System.exit(1); 486 | } 487 | downloadMonitor.showErrorDialog(dep.file.filename, dep.repo + '/' + dep.file.filename); 488 | throw new RuntimeException(s + " error", e); 489 | } 490 | 491 | private void download(InputStream is, int sizeGuess, Dependency dep) throws Exception { 492 | File target = new File(v_modsDir, dep.file.filename); 493 | if (sizeGuess > downloadBuffer.capacity()) { 494 | throw new Exception(String.format("The file %s is too large to be downloaded by " + owner + " - the download is invalid", target.getName())); 495 | } 496 | 497 | downloadBuffer.clear(); 498 | 499 | int read, fullLength = 0; 500 | 501 | downloadMonitor.resetProgress(sizeGuess); 502 | try { 503 | downloadMonitor.setPokeThread(Thread.currentThread()); 504 | byte[] buffer = new byte[1024]; 505 | while ((read = is.read(buffer)) >= 0) { 506 | downloadBuffer.put(buffer, 0, read); 507 | fullLength += read; 508 | if (downloadMonitor.shouldStopIt()) { 509 | break; 510 | } 511 | 512 | downloadMonitor.updateProgress(fullLength); 513 | } 514 | is.close(); 515 | downloadMonitor.setPokeThread(null); 516 | downloadBuffer.limit(fullLength); 517 | downloadBuffer.position(0); 518 | } catch (InterruptedIOException e) { 519 | // We were interrupted by the stop button. We're stopping now.. clear interruption flag. 520 | Thread.interrupted(); 521 | throw new Exception("Stop"); 522 | } 523 | 524 | if (!target.exists()) { 525 | target.createNewFile(); 526 | } 527 | 528 | downloadBuffer.position(0); 529 | FileOutputStream fos = new FileOutputStream(target); 530 | fos.getChannel().write(downloadBuffer); 531 | fos.close(); 532 | } 533 | 534 | private String checkExisting(Dependency dep) { 535 | for (File f : modsDir.listFiles()) { 536 | VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); 537 | if (!vfile.matches() || !vfile.name.equals(dep.file.name)) { 538 | continue; 539 | } 540 | 541 | if (f.renameTo(new File(v_modsDir, f.getName()))) { 542 | continue; 543 | } 544 | 545 | deleteMod(f); 546 | } 547 | 548 | for (File f : v_modsDir.listFiles()) { 549 | VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); 550 | if (!vfile.matches() || !vfile.name.equals(dep.file.name)) { 551 | continue; 552 | } 553 | 554 | int cmp = vfile.version.compareTo(dep.file.version); 555 | if (cmp < 0) { 556 | logger.info("Deleted old version " + f.getName()); 557 | deleteMod(f); 558 | return null; 559 | } 560 | if (cmp > 0) { 561 | logger.info("Warning: version of " + dep.file.name + ", " + vfile.version + " is newer than request " + dep.file.version); 562 | return f.getName(); 563 | } 564 | return f.getName();//found dependency 565 | } 566 | return null; 567 | } 568 | 569 | public void load() { 570 | scanDepInfos(); 571 | if (depMap.isEmpty()) { 572 | return; 573 | } 574 | boolean dontYell = Boolean.parseBoolean(System.getProperty("deploader.dontYellAtPeople", "false")); 575 | if (!dontYell) { 576 | yellAtPeople(); 577 | } 578 | forceRemoveCCL(); 579 | 580 | loadDeps(); 581 | activateDeps(); 582 | } 583 | 584 | private void activateDeps() { 585 | for (Dependency dep : depMap.values()) { 586 | File file = new File(v_modsDir, dep.existing); 587 | if (!searchCoreMod(file) && dep.coreLib) { 588 | addClasspath(file); 589 | } 590 | } 591 | } 592 | 593 | /** 594 | * Looks for FMLCorePlugin attributes and adds to CoreModManager 595 | */ 596 | private boolean searchCoreMod(File coreMod) { 597 | JarFile jar = null; 598 | Attributes mfAttributes; 599 | try { 600 | jar = new JarFile(coreMod); 601 | if (jar.getManifest() == null) { 602 | return false; 603 | } 604 | 605 | ModAccessTransformer.addJar(jar); 606 | mfAttributes = jar.getManifest().getMainAttributes(); 607 | } catch (IOException ioe) { 608 | FMLRelaunchLog.log(Level.ERROR, ioe, "Unable to read the jar file %s - ignoring", coreMod.getName()); 609 | return false; 610 | } finally { 611 | try { 612 | if (jar != null) { 613 | jar.close(); 614 | } 615 | } catch (IOException ignored) { 616 | } 617 | } 618 | 619 | String fmlCorePlugin = mfAttributes.getValue("FMLCorePlugin"); 620 | if (fmlCorePlugin == null) { 621 | return false; 622 | } 623 | 624 | addClasspath(coreMod); 625 | 626 | try { 627 | if (!mfAttributes.containsKey(new Attributes.Name("FMLCorePluginContainsFMLMod"))) { 628 | FMLRelaunchLog.finer("Adding %s to the list of known coremods, it will not be examined again", coreMod.getName()); 629 | CoreModManager.getIgnoredMods().add(coreMod.getName()); 630 | } else { 631 | FMLRelaunchLog.finer("Found FMLCorePluginContainsFMLMod marker in %s, it will be examined later for regular @Mod instances", coreMod.getName()); 632 | CoreModManager.getReparseableCoremods().add(coreMod.getName()); 633 | } 634 | Method m_loadCoreMod = CoreModManager.class.getDeclaredMethod("loadCoreMod", LaunchClassLoader.class, String.class, File.class); 635 | m_loadCoreMod.setAccessible(true); 636 | m_loadCoreMod.invoke(null, loader, fmlCorePlugin, coreMod); 637 | } catch (Exception e) { 638 | throw new RuntimeException(e); 639 | } 640 | 641 | return true; 642 | } 643 | 644 | private void loadDeps() { 645 | downloadMonitor = FMLLaunchHandler.side().isClient() ? new Downloader() : new DummyDownloader(); 646 | try { 647 | while (!depSet.isEmpty()) { 648 | Iterator it = depSet.iterator(); 649 | Dependency dep = depMap.get(it.next()); 650 | it.remove(); 651 | load(dep); 652 | } 653 | } finally { 654 | if (popupWindow != null) { 655 | popupWindow.setVisible(false); 656 | popupWindow.dispose(); 657 | } 658 | } 659 | } 660 | 661 | private void load(Dependency dep) { 662 | dep.existing = checkExisting(dep); 663 | if (dep.existing == null && DepLoader.class.getResource("/" + dep.testClass.replace('.', '/') + ".class") == null) { 664 | install(dep); 665 | } 666 | } 667 | 668 | private List modFiles() { 669 | List list = new LinkedList(); 670 | list.addAll(Arrays.asList(modsDir.listFiles())); 671 | list.addAll(Arrays.asList(v_modsDir.listFiles())); 672 | return list; 673 | } 674 | 675 | private void scanDepInfos() { 676 | for (File file : modFiles()) { 677 | if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) { 678 | continue; 679 | } 680 | 681 | scanDepInfo(file); 682 | } 683 | } 684 | 685 | private void scanDepInfo(File file) { 686 | try { 687 | scanning = file; 688 | ZipFile zip = new ZipFile(file); 689 | ZipEntry e = zip.getEntry("dependencies.info"); 690 | if (e != null) { 691 | loadJSon(zip.getInputStream(e)); 692 | } 693 | 694 | zip.close(); 695 | } catch (Exception e) { 696 | logger.error("Failed to load dependencies.info from " + file.getName() + " as JSON", e); 697 | } 698 | } 699 | 700 | private void loadJSon(InputStream input) throws IOException { 701 | InputStreamReader reader = new InputStreamReader(input); 702 | JsonElement root = new JsonParser().parse(reader); 703 | if (root.isJsonArray()) { 704 | loadJSonArr(root); 705 | } else { 706 | loadJson(root.getAsJsonObject()); 707 | } 708 | reader.close(); 709 | } 710 | 711 | private void loadJSonArr(JsonElement root) throws IOException { 712 | for (JsonElement node : root.getAsJsonArray()) { 713 | loadJson(node.getAsJsonObject()); 714 | } 715 | } 716 | 717 | private void loadJson(JsonObject node) throws IOException { 718 | boolean obfuscated = ((LaunchClassLoader) DepLoader.class.getClassLoader()).getClassBytes("net.minecraft.world.World") == null; 719 | 720 | String repo = node.has("repo") ? node.get("repo").getAsString() : null; 721 | String packed = node.has("packed") ? node.get("packed").getAsString() : null; 722 | String testClass = node.get("class").getAsString(); 723 | 724 | String filename = node.get("file").getAsString(); 725 | if (!obfuscated && node.has("dev")) { 726 | filename = node.get("dev").getAsString(); 727 | } 728 | 729 | boolean coreLib = node.has("coreLib") && node.get("coreLib").getAsBoolean(); 730 | 731 | Pattern pattern = null; 732 | try { 733 | if (node.has("pattern")) { 734 | pattern = Pattern.compile(node.get("pattern").getAsString()); 735 | } 736 | } catch (PatternSyntaxException e) { 737 | logger.error("Invalid filename pattern: " + node.get("pattern"), e); 738 | } 739 | if (pattern == null) { 740 | pattern = Pattern.compile("(\\w+).*?([\\d\\.]+)[-\\w]*\\.[^\\d]+"); 741 | } 742 | 743 | VersionedFile file = new VersionedFile(filename, pattern); 744 | if (!file.matches()) { 745 | throw new RuntimeException("Invalid filename format for dependency: " + filename); 746 | } 747 | 748 | addDep(new Dependency(scanning, repo, packed, file, testClass, coreLib)); 749 | } 750 | 751 | private void addDep(Dependency newDep) { 752 | Dependency oldDep = depMap.get(newDep.file.name); 753 | if (oldDep == null) { 754 | depMap.put(newDep.file.name, newDep); 755 | depSet.add(newDep.file.name); 756 | return; 757 | } 758 | 759 | //combine newer info from newDep into oldDep 760 | oldDep.coreLib |= newDep.coreLib; 761 | int cmp = newDep.file.version.compareTo(oldDep.file.version); 762 | if (cmp == 1) { 763 | oldDep.set(newDep); 764 | } else if (cmp == 0) { 765 | if (oldDep.repo == null) { 766 | oldDep.repo = newDep.repo; 767 | } 768 | if (oldDep.packed == null) { 769 | oldDep.source = newDep.source; 770 | oldDep.packed = newDep.packed; 771 | } 772 | } 773 | } 774 | 775 | public void yellAtPeople() { 776 | IYellAtPeople yellAtPeople = FMLLaunchHandler.side().isClient() ? new YellGui() : new YellServer(); 777 | yellAtPeople.addYellingData("The CodeChicken Dependency Downloader is being phased out and has detected mods using it."); 778 | yellAtPeople.addYellingData("The downloader will function as normal but this message serves as a log of what mods are using it."); 779 | yellAtPeople.addYellingData("If you are a mod dev, Please phase out all use of the dependency downloader."); 780 | yellAtPeople.addYellingData("If you are a normal user, you can follow the instructions at the bottom of the window if you would like."); 781 | yellAtPeople.addYellingData("The following mods are being requested to download..."); 782 | yellAtPeople.addYellingData(""); 783 | for (Entry entry : depMap.entrySet()) { 784 | yellAtPeople.addYellingData("\"" + entry.getValue().source.getName() + "\"" + " Wants: " + entry.getKey() + "-" + entry.getValue().file.version); 785 | } 786 | yellAtPeople.addYellingData(""); 787 | yellAtPeople.addYellingData(""); 788 | yellAtPeople.addYellingData("Don't be alarmed by this window, it is simply so i can log what mods are using the Dependency Downloader."); 789 | yellAtPeople.addYellingData("If you would like to report this please follow instructions listed here."); 790 | yellAtPeople.addYellingData("Click the OK button to continue."); 791 | 792 | yellAtPeople.displayYellingData(); 793 | } 794 | 795 | private void forceRemoveCCL() { 796 | if (depSet.contains("CodeChickenLib")) { 797 | depSet.remove("CodeChickenLib"); 798 | depMap.remove("CodeChickenLib"); 799 | } 800 | try { 801 | File[] files = v_modsDir.listFiles(); 802 | if (files != null) { 803 | for (File file : files) { 804 | if (file.getName().contains("CodeChickenLib") && file.getName().endsWith(".jar")) { 805 | FMLLog.info("Found old CCL [%s] attempting delete..", file.getName()); 806 | deleteMod(file); 807 | } 808 | } 809 | } 810 | } catch (Exception e) { 811 | throw new RuntimeException(e); 812 | } 813 | } 814 | } 815 | 816 | public static void load() { 817 | if (inst == null) { 818 | inst = new DepLoadInst(); 819 | inst.load(); 820 | } 821 | } 822 | 823 | @Override 824 | public String[] getASMTransformerClass() { 825 | return null; 826 | } 827 | 828 | @Override 829 | public String getModContainerClass() { 830 | return null; 831 | } 832 | 833 | @Override 834 | public String getSetupClass() { 835 | return getClass().getName(); 836 | } 837 | 838 | @Override 839 | public void injectData(Map data) { 840 | } 841 | 842 | @Override 843 | public Void call() { 844 | load(); 845 | 846 | return null; 847 | } 848 | 849 | @Override 850 | public String getAccessTransformerClass() { 851 | return null; 852 | } 853 | } 854 | --------------------------------------------------------------------------------