From 6d436a2c6a5d9b51070b8399c4fdb196603a8e82 Mon Sep 17 00:00:00 2001 From: Jakub <53441451+kuba6000@users.noreply.github.com> Date: Sun, 14 Aug 2022 15:19:13 +0200 Subject: Add "Mob Drops" NEI page + Extreme Extermination Chamber (#1) * First commit * Mixins * Merge the same items with diffrent damage * Faster random in NEI * More accuracy ? * Update ClientProxy.java * Renaming * Update buildscript * Use reserved MTE ID's * EEC work * Rework NEI page * Fix inaccurate chances * Basic equipment spawn * Add config options * Translations * Add infernal drops * Witchery fix * Forestry fixes * More fixes * Default blacklist * NEI sorting * Comment out testing deps * Clientsided check * Blood Magic support * LoaderReference * Check if peacefull is allowed * Add some XP output * Add recipe * Send Server config to Client * Add command to reload config * Translations * Process MT additions --- .../java/kubatech/loaders/MobRecipeLoader.java | 973 +++++++++++++++++++++ src/main/java/kubatech/loaders/RecipeLoader.java | 77 ++ 2 files changed, 1050 insertions(+) create mode 100644 src/main/java/kubatech/loaders/MobRecipeLoader.java create mode 100644 src/main/java/kubatech/loaders/RecipeLoader.java (limited to 'src/main/java/kubatech/loaders') diff --git a/src/main/java/kubatech/loaders/MobRecipeLoader.java b/src/main/java/kubatech/loaders/MobRecipeLoader.java new file mode 100644 index 0000000000..033beb49fd --- /dev/null +++ b/src/main/java/kubatech/loaders/MobRecipeLoader.java @@ -0,0 +1,973 @@ +/* + * KubaTech - Gregtech Addon + * Copyright (C) 2022 kuba6000 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package kubatech.loaders; + +import static kubatech.api.utils.ModUtils.isClientSided; +import static kubatech.api.utils.ModUtils.isDeobfuscatedEnvironment; +import static kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber.MobNameToRecipeMap; + +import atomicstryker.infernalmobs.common.InfernalMobsCore; +import atomicstryker.infernalmobs.common.MobModifier; +import atomicstryker.infernalmobs.common.mods.api.ModifierLoader; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.util.GT_Utility; +import gregtech.common.GT_DummyWorld; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.stream.Collectors; +import kubatech.Config; +import kubatech.Tags; +import kubatech.api.LoaderReference; +import kubatech.api.utils.InfernalHelper; +import kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber; +import kubatech.nei.Mob_Handler; +import kubatech.network.LoadConfigPacket; +import minetweaker.MineTweakerAPI; +import minetweaker.api.entity.IEntityDefinition; +import minetweaker.api.item.IItemStack; +import minetweaker.mc1710.item.MCItemStack; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.monster.EntitySlime; +import net.minecraft.entity.monster.IMob; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.common.MinecraftForge; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import stanhebben.zenscript.value.IntRange; +import thaumcraft.common.items.wands.ItemWandCasting; + +public class MobRecipeLoader { + + private static final Logger LOG = LogManager.getLogger(Tags.MODID + "[Mob Handler]"); + + public static final MobRecipeLoader instance = new MobRecipeLoader(); + + @SuppressWarnings("unused") + @SubscribeEvent + public void onOpenGui(GuiOpenEvent event) { + MobRecipeLoader.generateMobRecipeMap(); + MinecraftForge.EVENT_BUS.unregister(instance); + } + + private static final String dropFewItemsName = isDeobfuscatedEnvironment ? "dropFewItems" : "func_70628_a"; + private static final String dropRareDropName = isDeobfuscatedEnvironment ? "dropRareDrop" : "func_70600_l"; + private static final String setSlimeSizeName = isDeobfuscatedEnvironment ? "setSlimeSize" : "func_70799_a"; + private static final String addRandomArmorName = isDeobfuscatedEnvironment ? "addRandomArmor" : "func_82164_bB"; + private static final String enchantEquipmentName = isDeobfuscatedEnvironment ? "enchantEquipment" : "func_82162_bC"; + private static final String randName = isDeobfuscatedEnvironment ? "rand" : "field_70146_Z"; + + private static boolean alreadyGenerated = false; + public static boolean isInGenerationProcess = false; + public static final String randomEnchantmentDetectedString = "RandomEnchantmentDetected"; + + public static class MobRecipe { + public final ArrayList mOutputs; + public final int mEUt = 2000; + public final int mDuration; + public final int mMaxDamageChance; + public final boolean infernalityAllowed; + public final boolean alwaysinfernal; + public static droplist infernaldrops; + public final boolean isPeacefulAllowed; + + @SuppressWarnings("unchecked") + public MobRecipe copy() { + return new MobRecipe( + (ArrayList) mOutputs.clone(), + mDuration, + mMaxDamageChance, + infernalityAllowed, + alwaysinfernal, + isPeacefulAllowed); + } + + private MobRecipe( + ArrayList mOutputs, + int mDuration, + int mMaxDamageChance, + boolean infernalityAllowed, + boolean alwaysinfernal, + boolean isPeacefulAllowed) { + this.mOutputs = mOutputs; + this.mDuration = mDuration; + this.mMaxDamageChance = mMaxDamageChance; + this.infernalityAllowed = infernalityAllowed; + this.alwaysinfernal = alwaysinfernal; + this.isPeacefulAllowed = isPeacefulAllowed; + } + + @SuppressWarnings("unchecked") + public MobRecipe(EntityLiving e, ArrayList outputs) { + if (infernaldrops == null && LoaderReference.InfernalMobs) { + infernaldrops = new droplist(); + LOG.info("Generating Infernal drops"); + ArrayList> modifierLoaders = (ArrayList>) + InfernalHelper.getModifierLoaders().clone(); + int i = 0; + for (ModifierLoader modifierLoader : modifierLoaders) { + MobModifier nextMod = modifierLoader.make(null); + if (nextMod.getBlackListMobClasses() != null) + for (Class cl : nextMod.getBlackListMobClasses()) + if (e.getClass().isAssignableFrom(cl)) break; + i++; + } + if (i > 0) { + double chance = + InfernalHelper.checkEntityClassForced(e) ? 1d : (1d / InfernalHelper.getEliteRarity()); + ArrayList elitelist = InfernalHelper.getDropIdListElite(); + for (ItemStack stack : elitelist) { + dropinstance instance = infernaldrops.add( + new dropinstance(stack.copy(), infernaldrops), chance / elitelist.size()); + instance.isEnchatmentRandomized = true; + instance.enchantmentLevel = stack.getItem().getItemEnchantability(); + } + ArrayList ultralist = InfernalHelper.getDropIdListUltra(); + chance *= 1d / InfernalHelper.getUltraRarity(); + for (ItemStack stack : ultralist) { + dropinstance instance = infernaldrops.add( + new dropinstance(stack.copy(), infernaldrops), chance / ultralist.size()); + instance.isEnchatmentRandomized = true; + instance.enchantmentLevel = stack.getItem().getItemEnchantability(); + } + ArrayList infernallist = InfernalHelper.getDropIdListInfernal(); + chance *= 1d / InfernalHelper.getInfernoRarity(); + for (ItemStack stack : infernallist) { + dropinstance instance = infernaldrops.add( + new dropinstance(stack.copy(), infernaldrops), chance / infernallist.size()); + instance.isEnchatmentRandomized = true; + instance.enchantmentLevel = stack.getItem().getItemEnchantability(); + } + } + } else if (infernaldrops == null) infernaldrops = new droplist(); + + infernalityAllowed = InfernalHelper.isClassAllowed(e); + alwaysinfernal = InfernalHelper.checkEntityClassForced(e); + isPeacefulAllowed = !(e instanceof IMob); + + mOutputs = outputs; + int maxdamagechance = 0; + for (MobDrop o : mOutputs) { + if (o.damages != null) for (int v : o.damages.values()) maxdamagechance += v; + } + mMaxDamageChance = maxdamagechance; + // Powered spawner with octadic capacitor spawns ~22/min ~= 0.366/sec ~= 2.72s/spawn ~= 54.54t/spawn + mDuration = 55 + 10 + (((int) e.getMaxHealth() / 5) * 10); + } + + public ItemStack[] generateOutputs(Random rnd, GT_MetaTileEntity_ExtremeExterminationChamber MTE) { + MTE.mEUt = mEUt; + MTE.mMaxProgresstime = mDuration; + ArrayList stacks = new ArrayList<>(mOutputs.size()); + for (MobDrop o : mOutputs) { + if (o.chance == 10000 || rnd.nextInt(10000) < o.chance) { + ItemStack s = o.stack.copy(); + if (o.enchantable != null) EnchantmentHelper.addRandomEnchantment(rnd, s, o.enchantable); + if (o.damages != null) { + int rChance = rnd.nextInt(mMaxDamageChance); + int cChance = 0; + for (Map.Entry damage : o.damages.entrySet()) { + cChance += damage.getValue(); + if (rChance <= cChance) { + s.setItemDamage(damage.getKey()); + break; + } + } + } + stacks.add(s); + } + } + + if (infernalityAllowed + && mEUt * 8 < MTE.getMaxInputVoltage() + && !InfernalHelper.getDimensionBlackList() + .contains(MTE.getBaseMetaTileEntity().getWorld().provider.dimensionId)) { + int p = 0; + int mods = 0; + if (alwaysinfernal || rnd.nextInt(InfernalHelper.getEliteRarity()) == 0) { + p = 1; + if (rnd.nextInt(InfernalHelper.getUltraRarity()) == 0) { + p = 2; + if (rnd.nextInt(InfernalHelper.getInfernoRarity()) == 0) p = 3; + } + } + ArrayList infernalstacks = null; + if (p > 0) + if (p == 1) { + infernalstacks = InfernalHelper.getDropIdListElite(); + mods = InfernalHelper.getMinEliteModifiers(); + } else if (p == 2) { + infernalstacks = InfernalHelper.getDropIdListUltra(); + mods = InfernalHelper.getMinUltraModifiers(); + } else if (p == 3) { + infernalstacks = InfernalHelper.getDropIdListInfernal(); + mods = InfernalHelper.getMinInfernoModifiers(); + } + if (infernalstacks != null) { + ItemStack infernalstack = infernalstacks + .get(rnd.nextInt(infernalstacks.size())) + .copy(); + EnchantmentHelper.addRandomEnchantment( + rnd, infernalstack, infernalstack.getItem().getItemEnchantability()); + stacks.add(infernalstack); + MTE.mEUt *= 8; + MTE.mMaxProgresstime *= mods * InfernalMobsCore.instance().getMobModHealthFactor(); + } + } + + return stacks.toArray(new ItemStack[0]); + } + } + + public static class MobDrop { + public enum DropType { + Normal, + Rare, + Additional, + Infernal + } + + public ItemStack stack; + public DropType type; + public int chance; + public Integer enchantable; + public HashMap damages; + + public MobDrop( + ItemStack stack, DropType type, int chance, Integer enchantable, HashMap damages) { + this.stack = stack; + this.type = type; + this.chance = chance; + this.enchantable = enchantable; + this.damages = damages; + } + } + + public static class fakeRand extends Random { + private static class nexter { + private final int type; + private final int bound; + private int next; + + public nexter(int type, int bound) { + this.next = 0; + this.bound = bound; + this.type = type; + } + + private int getType() { + return type; + } + + private boolean getBoolean() { + return next == 1; + } + + private int getInt() { + return next; + } + + private float getFloat() { + return next * 0.1f; + } + + private boolean next() { + next++; + return next >= bound; + } + } + + private final ArrayList nexts = new ArrayList<>(); + private int walkCounter = 0; + private double chance; + private boolean exceptionOnEnchantTry = false; + private int maxWalkCount = -1; + private float forceFloatValue = -1.f; + + @Override + public int nextInt(int bound) { + if (exceptionOnEnchantTry && bound == Enchantment.enchantmentsBookList.length) return -1; + if (nexts.size() <= walkCounter) { // new call + if (maxWalkCount == walkCounter) { + return 0; + } + nexts.add(new nexter(0, bound)); + walkCounter++; + chance /= bound; + return 0; + } + chance /= bound; + return nexts.get(walkCounter++).getInt(); + } + + @Override + public float nextFloat() { + if (forceFloatValue != -1f) return forceFloatValue; + if (nexts.size() <= walkCounter) { // new call + if (maxWalkCount == walkCounter) { + return 0f; + } + nexts.add(new nexter(2, 10)); + walkCounter++; + chance /= 10; + return 0f; + } + chance /= 10; + return nexts.get(walkCounter++).getFloat(); + } + + @Override + public boolean nextBoolean() { + if (nexts.size() <= walkCounter) { // new call + if (maxWalkCount == walkCounter) { + return false; + } + nexts.add(new nexter(1, 2)); + walkCounter++; + chance /= 2; + return false; + } + chance /= 2; + return nexts.get(walkCounter++).getBoolean(); + } + + public void newRound() { + walkCounter = 0; + nexts.clear(); + chance = 1d; + maxWalkCount = -1; + exceptionOnEnchantTry = false; + forceFloatValue = -1f; + } + + public boolean nextRound() { + walkCounter = 0; + chance = 1d; + while (nexts.size() > 0 && nexts.get(nexts.size() - 1).next()) nexts.remove(nexts.size() - 1); + return nexts.size() > 0; + } + } + + private static class dropinstance { + public boolean isDamageRandomized = false; + public HashMap damagesPossible = new HashMap<>(); + public boolean isEnchatmentRandomized = false; + public int enchantmentLevel = 0; + public final ItemStack stack; + public final GT_Utility.ItemId itemId; + private double dropchance = 0d; + private int dropcount = 1; + private final droplist owner; + + public dropinstance(ItemStack s, droplist owner) { + this.owner = owner; + stack = s; + itemId = GT_Utility.ItemId.createNoCopy(stack); + } + + public int getchance(int chancemodifier) { + dropchance = (double) Math.round(dropchance * 100000) / 100000d; + return (int) (dropchance * chancemodifier); + } + + @Override + public int hashCode() { + return itemId.hashCode(); + } + } + + public static class droplist { + private final ArrayList drops = new ArrayList<>(); + private final HashMap dropschecker = new HashMap<>(); + + public dropinstance add(dropinstance i, double chance) { + if (contains(i)) { + int ssize = i.stack.stackSize; + i = get(dropschecker.get(i.itemId)); + i.dropchance += chance * ssize; + i.dropcount += ssize; + return i; + } + drops.add(i); + i.dropchance += chance * i.stack.stackSize; + i.dropcount += i.stack.stackSize - 1; + i.stack.stackSize = 1; + dropschecker.put(i.itemId, drops.size() - 1); + return i; + } + + public dropinstance get(int index) { + return drops.get(index); + } + + public dropinstance get(dropinstance i) { + if (!contains(i)) return null; + return get(dropschecker.get(i.itemId)); + } + + public boolean contains(dropinstance i) { + return dropschecker.containsKey(i.itemId); + } + + public boolean contains(ItemStack stack) { + return dropschecker.containsKey(GT_Utility.ItemId.createNoCopy(stack)); + } + + public boolean isEmpty() { + return drops.isEmpty(); + } + + public int size() { + return drops.size(); + } + + public int indexOf(dropinstance i) { + if (!contains(i)) return -1; + return dropschecker.get(i.itemId); + } + } + + private static class dropCollector { + HashMap damagableChecker = new HashMap<>(); + private boolean booksAlwaysRandomlyEnchanted = false; + + public void addDrop(droplist fdrops, ArrayList listToParse, double chance) { + for (EntityItem entityItem : listToParse) { + ItemStack ostack = entityItem.getEntityItem(); + if (ostack == null) continue; + dropinstance drop; + boolean randomchomenchantdetected = + ostack.hasTagCompound() && ostack.stackTagCompound.hasKey(randomEnchantmentDetectedString); + int randomenchantmentlevel = 0; + if (randomchomenchantdetected) { + randomenchantmentlevel = ostack.stackTagCompound.getInteger(randomEnchantmentDetectedString); + ostack.stackTagCompound.removeTag("ench"); + } + if ((booksAlwaysRandomlyEnchanted || randomchomenchantdetected) + && Items.enchanted_book == ostack.getItem()) { + NBTTagCompound tagCompound = (NBTTagCompound) ostack.stackTagCompound.copy(); + tagCompound.removeTag("StoredEnchantments"); + ostack = new ItemStack(Items.book, ostack.stackSize, 0); + if (!tagCompound.hasNoTags()) ostack.stackTagCompound = tagCompound; + if (randomenchantmentlevel == 0) randomenchantmentlevel = 1; + randomchomenchantdetected = true; + } + boolean randomdamagedetected = false; + int newdamage = -1; + if (ostack.isItemStackDamageable()) { + int odamage = ostack.getItemDamage(); + ostack.setItemDamage(1); + GT_Utility.ItemId id = GT_Utility.ItemId.createNoCopy(ostack); + damagableChecker.putIfAbsent(id, odamage); + int check = damagableChecker.get(id); + if (check != odamage) { + randomdamagedetected = true; + newdamage = odamage; + ostack.setItemDamage(check); + } else ostack.setItemDamage(odamage); + } + drop = fdrops.add(new dropinstance(ostack.copy(), fdrops), chance); + if (!drop.isEnchatmentRandomized && randomchomenchantdetected) { + drop.isEnchatmentRandomized = true; + drop.enchantmentLevel = randomenchantmentlevel; + } + if (drop.isDamageRandomized && !randomdamagedetected) { + drop.damagesPossible.merge(drop.stack.getItemDamage(), 1, Integer::sum); + } + if (randomdamagedetected) { + if (!drop.isDamageRandomized) { + drop.isDamageRandomized = true; + drop.damagesPossible.merge(drop.stack.getItemDamage(), drop.dropcount - 1, Integer::sum); + } + if (newdamage == -1) newdamage = drop.stack.getItemDamage(); + drop.damagesPossible.merge(newdamage, 1, Integer::sum); + } + } + + listToParse.clear(); + } + + public void newRound() { + damagableChecker.clear(); + booksAlwaysRandomlyEnchanted = false; + } + } + + public static class GeneralMappedMob { + public final EntityLiving mob; + public final MobRecipe recipe; + public final ArrayList drops; + + public GeneralMappedMob(EntityLiving mob, MobRecipe recipe, ArrayList drops) { + this.mob = mob; + this.recipe = recipe; + this.drops = drops; + } + } + + public static final HashMap GeneralMobList = new HashMap<>(); + + @SuppressWarnings("unchecked") + public static void generateMobRecipeMap() { + + if (alreadyGenerated) return; + alreadyGenerated = true; + if (!Config.mobHandlerEnabled) return; + + World f = new GT_DummyWorld() { + @Override + public boolean blockExists(int p_72899_1_, int p_72899_2_, int p_72899_3_) { + return false; + } + + @Override + public List getEntitiesWithinAABB(Class p_72872_1_, AxisAlignedBB p_72872_2_) { + return new ArrayList(); + } + }; + f.isRemote = true; // quick hack to get around achievements + + fakeRand frand = new fakeRand(); + f.rand = frand; + + isInGenerationProcess = true; + + LOG.info("Generating Recipe Map for Mob Handler and EEC"); + + long time = System.currentTimeMillis(); + + Method setSlimeSize; + Method dropFewItems; + Method dropRareDrop; + Method addRandomArmor; + Method enchantEquipment; + Field rand; + + try { + setSlimeSize = EntitySlime.class.getDeclaredMethod(setSlimeSizeName, int.class); + setSlimeSize.setAccessible(true); + dropFewItems = EntityLivingBase.class.getDeclaredMethod(dropFewItemsName, boolean.class, int.class); + dropFewItems.setAccessible(true); + dropRareDrop = EntityLivingBase.class.getDeclaredMethod(dropRareDropName, int.class); + dropRareDrop.setAccessible(true); + addRandomArmor = EntityLiving.class.getDeclaredMethod(addRandomArmorName); + addRandomArmor.setAccessible(true); + enchantEquipment = EntityLiving.class.getDeclaredMethod(enchantEquipmentName); + enchantEquipment.setAccessible(true); + rand = Entity.class.getDeclaredField(randName); + rand.setAccessible(true); + } catch (Exception ex) { + LOG.error("Failed to obtain methods"); + isInGenerationProcess = false; + return; + } + + dropCollector collector = new dropCollector(); + + // Stupid MC code, I need to cast myself + ((Map>) EntityList.stringToClassMapping).forEach((k, v) -> { + if (v == null) return; + + LOG.info("Generating entry for mob: " + k); + + if (Modifier.isAbstract(v.getModifiers())) { + LOG.info("Entity " + k + " is abstract, skipping"); + return; + } + + EntityLiving e; + try { + e = (EntityLiving) v.getConstructor(new Class[] {World.class}).newInstance(new Object[] {f}); + } catch (ClassCastException ex) { + // not a EntityLiving + LOG.info("Entity " + k + " is not a LivingEntity, skipping"); + return; + } catch (NoSuchMethodException ex) { + // No constructor ? + LOG.info("Entity " + k + " doesn't have constructor, skipping"); + return; + } catch (Exception ex) { + ex.printStackTrace(); + return; + } + + if (StatCollector.translateToLocal("entity." + k + ".name").equals("entity." + k + ".name")) { + LOG.info("Entity " + k + " does't have localized name, skipping"); + return; + } + + e.captureDrops = true; + + // POWERFULL GENERATION + + if (e instanceof EntitySlime) + try { + setSlimeSize.invoke(e, 1); + } catch (Exception ex) { + ex.printStackTrace(); + return; + } + + try { + rand.set(e, frand); + } catch (Exception ex) { + ex.printStackTrace(); + return; + } + + droplist drops = new droplist(); + droplist raredrops = new droplist(); + droplist additionaldrops = new droplist(); + + LOG.info("Generating normal drops"); + + frand.newRound(); + collector.newRound(); + + if (v.getName().startsWith("com.emoniph.witchery")) { + try { + dropFewItems.invoke(e, true, 0); + } catch (Exception ex) { + ex.printStackTrace(); + return; + } + frand.newRound(); + frand.exceptionOnEnchantTry = true; + boolean enchantmentDetected = false; + try { + dropFewItems.invoke(e, true, 0); + } catch (Exception ex) { + enchantmentDetected = true; + } + int w = frand.walkCounter; + frand.newRound(); + if (enchantmentDetected) { + frand.maxWalkCount = w; + collector.booksAlwaysRandomlyEnchanted = true; + } + e.capturedDrops.clear(); + } + + do { + try { + dropFewItems.invoke(e, true, 0); + } catch (Exception ex) { + ex.printStackTrace(); + return; + } + collector.addDrop(drops, e.capturedDrops, frand.chance); + + if (frand.chance < 0.0000001d) { + LOG.info("Skipping " + k + " normal dropmap because it's too randomized"); + break; + } + + } while (frand.nextRound()); + + LOG.info("Generating rare drops"); + + frand.newRound(); + collector.newRound(); + + do { + try { + dropRareDrop.invoke(e, 0); + } catch (Exception ex) { + ex.printStackTrace(); + return; + } + collector.addDrop(raredrops, e.capturedDrops, frand.chance); + + if (frand.chance < 0.0000001d) { + LOG.info("Skipping " + k + " rare dropmap because it's too randomized"); + break; + } + } while (frand.nextRound()); + + LOG.info("Generating additional drops"); + + frand.newRound(); + collector.newRound(); + + try { + Class cl = e.getClass(); + boolean detectedException = false; + do { + detectedException = false; + try { + cl.getDeclaredMethod(addRandomArmorName); + } catch (Exception ex) { + detectedException = true; + cl = cl.getSuperclass(); + } + } while (detectedException && !cl.equals(Entity.class)); + if (cl.equals(EntityLiving.class) || cl.equals(Entity.class)) throw new Exception(); + cl = e.getClass(); + do { + detectedException = false; + try { + cl.getDeclaredMethod(enchantEquipmentName); + } catch (Exception ex) { + detectedException = true; + cl = cl.getSuperclass(); + } + } while (detectedException && !cl.equals(EntityLiving.class)); + boolean usingVanillaEnchantingMethod = cl.equals(EntityLiving.class); + double chanceModifierLocal = 1f; + if (v.getName().startsWith("twilightforest.entity")) { + frand.forceFloatValue = 0f; + chanceModifierLocal = 0.25f; + } + do { + addRandomArmor.invoke(e); + if (!usingVanillaEnchantingMethod) enchantEquipment.invoke(e); + ItemStack[] lastActiveItems = e.getLastActiveItems(); + for (int j = 0, lastActiveItemsLength = lastActiveItems.length; j < lastActiveItemsLength; j++) { + ItemStack stack = lastActiveItems[j]; + if (stack != null) { + if (LoaderReference.Thaumcraft) + if (stack.getItem() instanceof ItemWandCasting) + continue; // crashes the game when rendering in GUI + + int randomenchant = -1; + if (stack.hasTagCompound() + && stack.stackTagCompound.hasKey(randomEnchantmentDetectedString)) { + randomenchant = stack.stackTagCompound.getInteger(randomEnchantmentDetectedString); + stack.stackTagCompound.removeTag("ench"); + } + dropinstance i = additionaldrops.add( + new dropinstance(stack.copy(), additionaldrops), + frand.chance + * chanceModifierLocal + * (usingVanillaEnchantingMethod ? (j == 0 ? 0.75d : 0.5d) : 1d)); + if (!i.isDamageRandomized && i.stack.isItemStackDamageable()) { + i.isDamageRandomized = true; + int maxdamage = i.stack.getMaxDamage(); + int max = Math.max(maxdamage - 25, 1); + for (int d = Math.min(max, 25); d <= max; d++) i.damagesPossible.put(d, 1); + } + if (!i.isEnchatmentRandomized && randomenchant != -1) { + i.isEnchatmentRandomized = true; + i.enchantmentLevel = randomenchant; + } + if (usingVanillaEnchantingMethod) { + if (!stack.hasTagCompound()) stack.stackTagCompound = new NBTTagCompound(); + stack.stackTagCompound.setInteger(randomEnchantmentDetectedString, 14); + dropinstance newdrop = additionaldrops.add( + new dropinstance(stack.copy(), additionaldrops), + frand.chance * chanceModifierLocal * (j == 0 ? 0.25d : 0.5d)); + newdrop.isEnchatmentRandomized = true; + newdrop.enchantmentLevel = 14; + newdrop.isDamageRandomized = i.isDamageRandomized; + newdrop.damagesPossible = (HashMap) i.damagesPossible.clone(); + } + } + } + Arrays.fill(e.getLastActiveItems(), null); + + if (frand.chance < 0.0000001d) { + LOG.info("Skipping " + k + " additional dropmap because it's too randomized"); + break; + } + + } while (frand.nextRound()); + } catch (Exception ignored) { + } + + frand.newRound(); + collector.newRound(); + + if (drops.isEmpty() && raredrops.isEmpty() && additionaldrops.isEmpty()) { + GeneralMobList.put(k, new GeneralMappedMob(e, null, new ArrayList<>())); + LOG.info("Entity " + k + " doesn't drop any items, skipping EEC Recipe map"); + return; + } + + ArrayList moboutputs = new ArrayList<>(drops.size() + raredrops.size() + additionaldrops.size()); + + for (dropinstance drop : drops.drops) { + ItemStack stack = drop.stack; + if (stack.hasTagCompound()) stack.stackTagCompound.removeTag(randomEnchantmentDetectedString); + int chance = drop.getchance(10000); + while (chance > 10000) { + stack.stackSize *= 2; + chance /= 2; + } + moboutputs.add(new MobDrop( + stack, + MobDrop.DropType.Normal, + chance, + drop.isEnchatmentRandomized ? drop.enchantmentLevel : null, + drop.isDamageRandomized ? drop.damagesPossible : null)); + } + for (dropinstance drop : raredrops.drops) { + ItemStack stack = drop.stack; + if (stack.hasTagCompound()) stack.stackTagCompound.removeTag(randomEnchantmentDetectedString); + int chance = drop.getchance(250); + while (chance > 10000) { + stack.stackSize *= 2; + chance /= 2; + } + moboutputs.add(new MobDrop( + stack, + MobDrop.DropType.Rare, + chance, + drop.isEnchatmentRandomized ? drop.enchantmentLevel : null, + drop.isDamageRandomized ? drop.damagesPossible : null)); + } + for (dropinstance drop : additionaldrops.drops) { + ItemStack stack = drop.stack; + if (stack.hasTagCompound()) stack.stackTagCompound.removeTag(randomEnchantmentDetectedString); + int chance = drop.getchance(850); + while (chance > 10000) { + stack.stackSize *= 2; + chance /= 2; + } + moboutputs.add(new MobDrop( + stack, + MobDrop.DropType.Additional, + chance, + drop.isEnchatmentRandomized ? drop.enchantmentLevel : null, + drop.isDamageRandomized ? drop.damagesPossible : null)); + } + + GeneralMobList.put(k, new GeneralMappedMob(e, new MobRecipe(e, moboutputs), moboutputs)); + + LOG.info("Mapped " + k); + }); + + time -= System.currentTimeMillis(); + time = -time; + + LOG.info("Recipe map generated ! It took " + time + "ms"); + + isInGenerationProcess = false; + } + + public static void processMobRecipeMap() { + LOG.info("Loading config"); + + if (isClientSided) Mob_Handler.clearRecipes(); + MobNameToRecipeMap.clear(); + LoadConfigPacket.instance.mobsToLoad.clear(); + GeneralMobList.forEach((k, v) -> { + if (Arrays.asList(Config.mobBlacklist).contains(k)) { + LOG.info("Entity " + k + " is blacklisted, skipping"); + return; + } + + MobRecipe recipe = v.recipe; + if (recipe != null) recipe = recipe.copy(); + ArrayList drops = (ArrayList) v.drops.clone(); + + // MT Scripts should already be loaded here + if (LoaderReference.MineTweaker) { + Optionals.parseMTAdditions(k, drops, recipe); + } + + if (drops.isEmpty()) { + LOG.info("Entity " + k + " doesn't drop any items, skipping EEC map"); + if (!Config.includeEmptyMobs) return; + LoadConfigPacket.instance.mobsToLoad.add(k); + LOG.info("Registered " + k); + return; + } + if (v.recipe != null) MobNameToRecipeMap.put(k, recipe); + LoadConfigPacket.instance.mobsToLoad.add(k); + LOG.info("Registered " + k); + }); + } + + @SideOnly(Side.CLIENT) + public static void processMobRecipeMap(HashSet mobs) { + if (isClientSided) Mob_Handler.clearRecipes(); + MobNameToRecipeMap.clear(); + mobs.forEach(k -> { + GeneralMappedMob v = GeneralMobList.get(k); + MobRecipe recipe = v.recipe; + if (recipe != null) recipe = recipe.copy(); + ArrayList drops = (ArrayList) v.drops.clone(); + + // MT Scripts should already be loaded here + if (LoaderReference.MineTweaker) { + Optionals.parseMTAdditions(k, drops, recipe); + } + + Mob_Handler.addRecipe(v.mob, drops); + if (recipe != null) MobNameToRecipeMap.put(k, recipe); + LOG.info("Registered " + k); + }); + LOG.info("Sorting NEI map"); + Mob_Handler.sortCachedRecipes(); + } + + private static class Optionals { + private static void parseMTAdditions(String k, ArrayList drops, MobRecipe recipe) { + IEntityDefinition ie = MineTweakerAPI.game.getEntity(k); + if (ie != null) { + for (Map.Entry entry : ie.getDropsToAdd().entrySet()) { + IntRange r = entry.getValue(); + // Get average chance + double chance; + if (r.getFrom() == 0 && r.getTo() == 0) chance = 1d; + else chance = (((double) r.getTo() - (double) r.getFrom()) / 2d) + (double) r.getFrom(); + ItemStack stack = ((ItemStack) entry.getKey().getInternal()).copy(); + MobDrop drop = new MobDrop(stack, MobDrop.DropType.Normal, (int) (chance * 10000), null, null); + drops.add(drop); + if (recipe != null) recipe.mOutputs.add(drop); + } + for (Map.Entry entry : + ie.getDropsToAddPlayerOnly().entrySet()) { + IntRange r = entry.getValue(); + // Get average chance + double chance; + if (r.getFrom() == 0 && r.getTo() == 0) chance = 1d; + else chance = (((double) r.getTo() - (double) r.getFrom()) / 2d) + (double) r.getFrom(); + ItemStack stack = ((ItemStack) entry.getKey().getInternal()).copy(); + MobDrop drop = new MobDrop(stack, MobDrop.DropType.Normal, (int) (chance * 10000), null, null); + drops.add(drop); + if (recipe != null) recipe.mOutputs.add(drop); + } + for (IItemStack istack : ie.getDropsToRemove()) { + List toRemove = drops.stream() + .filter(d -> istack.matches(new MCItemStack(d.stack))) + .collect(Collectors.toList()); + drops.removeAll(toRemove); + if (recipe != null) recipe.mOutputs.removeAll(toRemove); + } + } + } + } +} diff --git a/src/main/java/kubatech/loaders/RecipeLoader.java b/src/main/java/kubatech/loaders/RecipeLoader.java new file mode 100644 index 0000000000..99908a857f --- /dev/null +++ b/src/main/java/kubatech/loaders/RecipeLoader.java @@ -0,0 +1,77 @@ +/* + * KubaTech - Gregtech Addon + * Copyright (C) 2022 kuba6000 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package kubatech.loaders; + +import gregtech.api.enums.Materials; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.util.GT_ModHandler; +import kubatech.Tags; +import kubatech.api.LoaderReference; +import kubatech.api.enums.ItemList; +import kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class RecipeLoader { + + private static final Logger LOG = LogManager.getLogger(Tags.MODID + "[Recipe Loader]"); + protected static final long bitsd = GT_ModHandler.RecipeBits.NOT_REMOVABLE + | GT_ModHandler.RecipeBits.REVERSIBLE + | GT_ModHandler.RecipeBits.BUFFERED + | GT_ModHandler.RecipeBits.DISMANTLEABLE; + + private static int MTEID = 14201; + private static final int MTEIDMax = 14300; + + public static void addRecipes() { + if (LoaderReference.EnderIO) { + ItemList.ExtremeExterminationChamber.set(new GT_MetaTileEntity_ExtremeExterminationChamber( + MTEID++, "multimachine.exterminationchamber", "Extreme Extermination Chamber") + .getStackForm(1L)); + GT_ModHandler.addCraftingRecipe(ItemList.ExtremeExterminationChamber.get(1), bitsd, new Object[] { + "RCR", + "CHC", + "VVV", + 'R', + gregtech.api.enums.ItemList.Robot_Arm_EV, + 'C', + OrePrefixes.circuit.get(Materials.Data), + 'H', + gregtech.api.enums.ItemList.Hull_EV, + 'V', + GT_ModHandler.getModItem("OpenBlocks", "vacuumhopper", 1, new ItemStack(Blocks.hopper)) + }); + } + if (MTEID > MTEIDMax + 1) throw new RuntimeException("MTE ID's"); + } + + private static boolean lateRecipesInitialized = false; + + public static void addRecipesLate() { + // Runs on server start + if (lateRecipesInitialized) return; + lateRecipesInitialized = true; + + MobRecipeLoader.generateMobRecipeMap(); + MobRecipeLoader.processMobRecipeMap(); + } +} -- cgit From f53a666152aa956a097d67fdaa7fb18757839147 Mon Sep 17 00:00:00 2001 From: kuba6000 Date: Sun, 14 Aug 2022 16:23:54 +0200 Subject: Fix server crash from Blood Magic entities --- src/main/java/kubatech/loaders/MobRecipeLoader.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/main/java/kubatech/loaders') diff --git a/src/main/java/kubatech/loaders/MobRecipeLoader.java b/src/main/java/kubatech/loaders/MobRecipeLoader.java index 033beb49fd..fddfb03137 100644 --- a/src/main/java/kubatech/loaders/MobRecipeLoader.java +++ b/src/main/java/kubatech/loaders/MobRecipeLoader.java @@ -618,7 +618,11 @@ public class MobRecipeLoader { // No constructor ? LOG.info("Entity " + k + " doesn't have constructor, skipping"); return; - } catch (Exception ex) { + } catch (NoClassDefFoundError ex) { + // Its using classes from Client ? Then it's not important to include + LOG.info("Entity " + k + " is using undefined classes, skipping"); + return; + } catch (Throwable ex) { ex.printStackTrace(); return; } -- cgit From 4ad580a05e475a912ff9964cdd09d5ff666b98e8 Mon Sep 17 00:00:00 2001 From: kuba6000 Date: Sun, 14 Aug 2022 21:46:59 +0200 Subject: LGPL 3.0 --- src/main/java/kubatech/loaders/MobRecipeLoader.java | 18 +++++++++--------- src/main/java/kubatech/loaders/RecipeLoader.java | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/main/java/kubatech/loaders') diff --git a/src/main/java/kubatech/loaders/MobRecipeLoader.java b/src/main/java/kubatech/loaders/MobRecipeLoader.java index fddfb03137..3c087961d9 100644 --- a/src/main/java/kubatech/loaders/MobRecipeLoader.java +++ b/src/main/java/kubatech/loaders/MobRecipeLoader.java @@ -2,18 +2,18 @@ * KubaTech - Gregtech Addon * Copyright (C) 2022 kuba6000 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . * */ diff --git a/src/main/java/kubatech/loaders/RecipeLoader.java b/src/main/java/kubatech/loaders/RecipeLoader.java index 99908a857f..ba6cbb7a1f 100644 --- a/src/main/java/kubatech/loaders/RecipeLoader.java +++ b/src/main/java/kubatech/loaders/RecipeLoader.java @@ -2,18 +2,18 @@ * KubaTech - Gregtech Addon * Copyright (C) 2022 kuba6000 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . * */ -- cgit From 76a2834cedfa4f3916d07e2893fc54121268489e Mon Sep 17 00:00:00 2001 From: kuba6000 Date: Wed, 17 Aug 2022 05:01:16 +0200 Subject: Structure --- .../java/kubatech/loaders/MobRecipeLoader.java | 22 +++++++++++++++------- src/main/java/kubatech/loaders/RecipeLoader.java | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'src/main/java/kubatech/loaders') diff --git a/src/main/java/kubatech/loaders/MobRecipeLoader.java b/src/main/java/kubatech/loaders/MobRecipeLoader.java index 3c087961d9..21c18897f4 100644 --- a/src/main/java/kubatech/loaders/MobRecipeLoader.java +++ b/src/main/java/kubatech/loaders/MobRecipeLoader.java @@ -21,7 +21,7 @@ package kubatech.loaders; import static kubatech.api.utils.ModUtils.isClientSided; import static kubatech.api.utils.ModUtils.isDeobfuscatedEnvironment; -import static kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber.MobNameToRecipeMap; +import static kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber.MobNameToRecipeMap; import atomicstryker.infernalmobs.common.InfernalMobsCore; import atomicstryker.infernalmobs.common.MobModifier; @@ -39,10 +39,10 @@ import java.util.stream.Collectors; import kubatech.Config; import kubatech.Tags; import kubatech.api.LoaderReference; +import kubatech.api.network.LoadConfigPacket; import kubatech.api.utils.InfernalHelper; -import kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber; import kubatech.nei.Mob_Handler; -import kubatech.network.LoadConfigPacket; +import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber; import minetweaker.MineTweakerAPI; import minetweaker.api.entity.IEntityDefinition; import minetweaker.api.item.IItemStack; @@ -102,6 +102,7 @@ public class MobRecipeLoader { public final boolean alwaysinfernal; public static droplist infernaldrops; public final boolean isPeacefulAllowed; + public final EntityLiving entity; @SuppressWarnings("unchecked") public MobRecipe copy() { @@ -111,7 +112,8 @@ public class MobRecipeLoader { mMaxDamageChance, infernalityAllowed, alwaysinfernal, - isPeacefulAllowed); + isPeacefulAllowed, + entity); } private MobRecipe( @@ -120,13 +122,15 @@ public class MobRecipeLoader { int mMaxDamageChance, boolean infernalityAllowed, boolean alwaysinfernal, - boolean isPeacefulAllowed) { + boolean isPeacefulAllowed, + EntityLiving entity) { this.mOutputs = mOutputs; this.mDuration = mDuration; this.mMaxDamageChance = mMaxDamageChance; this.infernalityAllowed = infernalityAllowed; this.alwaysinfernal = alwaysinfernal; this.isPeacefulAllowed = isPeacefulAllowed; + this.entity = entity; } @SuppressWarnings("unchecked") @@ -185,6 +189,7 @@ public class MobRecipeLoader { mMaxDamageChance = maxdamagechance; // Powered spawner with octadic capacitor spawns ~22/min ~= 0.366/sec ~= 2.72s/spawn ~= 54.54t/spawn mDuration = 55 + 10 + (((int) e.getMaxHealth() / 5) * 10); + entity = e; } public ItemStack[] generateOutputs(Random rnd, GT_MetaTileEntity_ExtremeExterminationChamber MTE) { @@ -460,7 +465,7 @@ public class MobRecipeLoader { } private static class dropCollector { - HashMap damagableChecker = new HashMap<>(); + final HashMap damagableChecker = new HashMap<>(); private boolean booksAlwaysRandomlyEnchanted = false; public void addDrop(droplist fdrops, ArrayList listToParse, double chance) { @@ -552,6 +557,7 @@ public class MobRecipeLoader { return false; } + @SuppressWarnings("rawtypes") @Override public List getEntitiesWithinAABB(Class p_72872_1_, AxisAlignedBB p_72872_2_) { return new ArrayList(); @@ -727,7 +733,7 @@ public class MobRecipeLoader { try { Class cl = e.getClass(); - boolean detectedException = false; + boolean detectedException; do { detectedException = false; try { @@ -894,6 +900,7 @@ public class MobRecipeLoader { MobRecipe recipe = v.recipe; if (recipe != null) recipe = recipe.copy(); + @SuppressWarnings("unchecked") ArrayList drops = (ArrayList) v.drops.clone(); // MT Scripts should already be loaded here @@ -922,6 +929,7 @@ public class MobRecipeLoader { GeneralMappedMob v = GeneralMobList.get(k); MobRecipe recipe = v.recipe; if (recipe != null) recipe = recipe.copy(); + @SuppressWarnings("unchecked") ArrayList drops = (ArrayList) v.drops.clone(); // MT Scripts should already be loaded here diff --git a/src/main/java/kubatech/loaders/RecipeLoader.java b/src/main/java/kubatech/loaders/RecipeLoader.java index ba6cbb7a1f..84c3603225 100644 --- a/src/main/java/kubatech/loaders/RecipeLoader.java +++ b/src/main/java/kubatech/loaders/RecipeLoader.java @@ -25,7 +25,7 @@ import gregtech.api.util.GT_ModHandler; import kubatech.Tags; import kubatech.api.LoaderReference; import kubatech.api.enums.ItemList; -import kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber; +import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import org.apache.logging.log4j.LogManager; -- cgit From 01d91c0acd0e8b494578d63683088e6f1d67509f Mon Sep 17 00:00:00 2001 From: kuba6000 Date: Thu, 18 Aug 2022 00:12:14 +0200 Subject: Cache Mob Handler map --- .../java/kubatech/loaders/MobRecipeLoader.java | 84 +++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'src/main/java/kubatech/loaders') diff --git a/src/main/java/kubatech/loaders/MobRecipeLoader.java b/src/main/java/kubatech/loaders/MobRecipeLoader.java index 3c087961d9..b7c5e9781d 100644 --- a/src/main/java/kubatech/loaders/MobRecipeLoader.java +++ b/src/main/java/kubatech/loaders/MobRecipeLoader.java @@ -26,20 +26,28 @@ import static kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_E import atomicstryker.infernalmobs.common.InfernalMobsCore; import atomicstryker.infernalmobs.common.MobModifier; import atomicstryker.infernalmobs.common.mods.api.ModifierLoader; +import com.google.common.io.Files; +import com.google.gson.Gson; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.util.GT_Utility; import gregtech.common.GT_DummyWorld; +import java.io.File; +import java.io.Reader; +import java.io.Writer; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; import kubatech.Config; import kubatech.Tags; import kubatech.api.LoaderReference; +import kubatech.api.utils.GSONUtils; import kubatech.api.utils.InfernalHelper; +import kubatech.api.utils.ModUtils; import kubatech.common.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber; import kubatech.nei.Mob_Handler; import kubatech.network.LoadConfigPacket; @@ -259,7 +267,10 @@ public class MobRecipeLoader { Infernal } + @GSONUtils.SkipGSON public ItemStack stack; + + public NBTTagCompound reconstructableStack; public DropType type; public int chance; public Integer enchantable; @@ -268,11 +279,16 @@ public class MobRecipeLoader { public MobDrop( ItemStack stack, DropType type, int chance, Integer enchantable, HashMap damages) { this.stack = stack; + this.reconstructableStack = stack.writeToNBT(new NBTTagCompound()); this.type = type; this.chance = chance; this.enchantable = enchantable; this.damages = damages; } + + public void reconstructStack() { + this.stack = ItemStack.loadItemStackFromNBT(this.reconstructableStack); + } } public static class fakeRand extends Random { @@ -539,7 +555,12 @@ public class MobRecipeLoader { public static final HashMap GeneralMobList = new HashMap<>(); - @SuppressWarnings("unchecked") + private static class MobRecipeLoaderCacheStructure { + String version; + Map> moblist; + } + + @SuppressWarnings({"unchecked", "UnstableApiUsage"}) public static void generateMobRecipeMap() { if (alreadyGenerated) return; @@ -562,6 +583,46 @@ public class MobRecipeLoader { fakeRand frand = new fakeRand(); f.rand = frand; + File cache = Config.getConfigFile("MobRecipeLoader.cache"); + Gson gson = GSONUtils.GSON_BUILDER.create(); + + if (cache.exists()) { + LOG.info("Parsing Cached map"); + Reader reader = null; + try { + reader = Files.newReader(cache, StandardCharsets.UTF_8); + MobRecipeLoaderCacheStructure s = gson.fromJson(reader, MobRecipeLoaderCacheStructure.class); + if (s.version.equals(ModUtils.getModListVersion())) { + for (Map.Entry> entry : s.moblist.entrySet()) { + try { + EntityLiving e = + (EntityLiving) ((Class) EntityList.stringToClassMapping.get(entry.getKey())) + .getConstructor(new Class[] {World.class}) + .newInstance(new Object[] {f}); + ArrayList drops = entry.getValue(); + drops.forEach(MobDrop::reconstructStack); + GeneralMobList.put(entry.getKey(), new GeneralMappedMob(e, new MobRecipe(e, drops), drops)); + } catch (Exception ignored) { + } + } + LOG.info("Parsed cached map, skipping generation"); + return; + } else { + LOG.info("Cached map version mismatch, generating a new one"); + } + } catch (Exception ignored) { + LOG.info("There was an exception while parsing cached map, generating a new one"); + } finally { + if (reader != null) + try { + reader.close(); + } catch (Exception ignored) { + } + } + } else { + LOG.info("Cached map doesn't exist, generating a new one"); + } + isInGenerationProcess = true; LOG.info("Generating Recipe Map for Mob Handler and EEC"); @@ -878,6 +939,27 @@ public class MobRecipeLoader { LOG.info("Recipe map generated ! It took " + time + "ms"); isInGenerationProcess = false; + + LOG.info("Saving generated map to file"); + MobRecipeLoaderCacheStructure s = new MobRecipeLoaderCacheStructure(); + s.version = ModUtils.getModListVersion(); + s.moblist = new HashMap<>(); + GeneralMobList.forEach((k, v) -> s.moblist.put(k, v.drops)); + Writer writer = null; + try { + writer = Files.newWriter(cache, StandardCharsets.UTF_8); + gson.toJson(s, writer); + writer.flush(); + writer.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (writer != null) + try { + writer.close(); + } catch (Exception ignored) { + } + } } public static void processMobRecipeMap() { -- cgit From c775b9f97779003c3a2366eff607b1d64b6c8040 Mon Sep 17 00:00:00 2001 From: kuba6000 Date: Thu, 18 Aug 2022 00:45:04 +0200 Subject: Update MobRecipeLoader.java --- src/main/java/kubatech/loaders/MobRecipeLoader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/kubatech/loaders') diff --git a/src/main/java/kubatech/loaders/MobRecipeLoader.java b/src/main/java/kubatech/loaders/MobRecipeLoader.java index b7c5e9781d..283c75391a 100644 --- a/src/main/java/kubatech/loaders/MobRecipeLoader.java +++ b/src/main/java/kubatech/loaders/MobRecipeLoader.java @@ -601,7 +601,9 @@ public class MobRecipeLoader { .newInstance(new Object[] {f});