mirror of
https://github.com/GTNewHorizons/Hardcore-Ender-Expansion.git
synced 2026-10-25 20:22:31 +00:00
Replace reflective registry replacement with minor mixined method (#24)
This commit is contained in:
1 parent
63eb75461c
commit
73ff6ff8a5
16 files changed
+178
-133
No files matched your search
@@ -68,7 +68,7 @@ The project is under the All Rights Reserved license, which means that redistrib
|
||||
|
||||
This rule only applies to the source code, assets are copyrighted and belong to their respective owners (music to qwertygiy, all other assets to me), and cannot be used in other projects without the owner's permission!
|
||||
|
||||
If you find a handy method or even an entire class (such as BlockReplaceHelper), I don't mind if you use it in your project (don't copy everything you see though, that's not how you learn to mod). Giving credit is only required if your project has publicly visible source, in that case use javadoc and link back to the original source.
|
||||
If you find a handy method or even an entire class (such as ~~BlockReplaceHelper~~ NH deleted this class because it was an awful hack), I don't mind if you use it in your project (don't copy everything you see though, that's not how you learn to mod). Giving credit is only required if your project has publicly visible source, in that case use javadoc and link back to the original source.
|
||||
|
||||
### I want to modify something in HEE
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
//version: 1707058017
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhconvention'
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
implementation('com.github.GTNewHorizons:GTNHLib:0.6.15:dev')
|
||||
implementation('com.github.GTNewHorizons:NotEnoughItems:2.7.30-GTNH:dev')
|
||||
implementation('com.github.GTNewHorizons:GTNHLib:0.6.21:dev')
|
||||
implementation('com.github.GTNewHorizons:NotEnoughItems:2.7.40-GTNH:dev')
|
||||
|
||||
compileOnly('thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev')
|
||||
compileOnly('com.github.GTNewHorizons:Mobs-Info:0.5.2-GTNH:dev')
|
||||
|
||||
+6
-6
@@ -14,7 +14,7 @@ modId = HardcoreEnderExpansion
|
||||
modGroup = chylex.hee
|
||||
|
||||
# Whether to use modGroup as the maven publishing group.
|
||||
# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods.
|
||||
# When false, com.github.GTNewHorizons is used.
|
||||
useModGroupForPublishing = false
|
||||
|
||||
# Updates your build.gradle and settings.gradle automatically whenever an update is available.
|
||||
@@ -41,11 +41,11 @@ developmentEnvironmentUserName = "Developer"
|
||||
|
||||
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
|
||||
# See https://github.com/bsideup/jabel for details on how this works.
|
||||
enableModernJavaSyntax = false
|
||||
enableModernJavaSyntax = true
|
||||
|
||||
# Enables injecting missing generics into the decompiled source code for a better coding experience.
|
||||
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
|
||||
enableGenericInjection = false
|
||||
enableGenericInjection = true
|
||||
|
||||
# Generate a class with a String field for the mod version named as defined below.
|
||||
# If generateGradleTokenClass is empty or not missing, no such class will be generated.
|
||||
@@ -83,7 +83,7 @@ apiPackage =
|
||||
accessTransformersFile =
|
||||
|
||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||
usesMixins = false
|
||||
usesMixins = true
|
||||
|
||||
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
|
||||
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
|
||||
@@ -97,12 +97,12 @@ usesMixinDebug = false
|
||||
mixinPlugin =
|
||||
|
||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
||||
mixinsPackage =
|
||||
mixinsPackage = mixins
|
||||
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
# This parameter is for legacy compatibility only
|
||||
# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin
|
||||
coreModClass =
|
||||
coreModClass = HEECore
|
||||
|
||||
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
|
||||
# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.37'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.38'
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package chylex.hee;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.mixin.IMixins;
|
||||
import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader;
|
||||
|
||||
import chylex.hee.mixins.Mixins;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
public class HEECore implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
|
||||
@Override
|
||||
public String getMixinConfig() {
|
||||
return "mixins.HardcoreEnderExpansion.early.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins(Set<String> loadedCoreMods) {
|
||||
return IMixins.getEarlyMixins(Mixins.class, loadedCoreMods);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package chylex.hee.block;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.util.ObjectIntIdentityMap;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.reflect.Fields;
|
||||
|
||||
import chylex.hee.system.logging.Log;
|
||||
import chylex.hee.system.logging.Stopwatch;
|
||||
import chylex.hee.system.util.ReflectionUtils;
|
||||
import cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry;
|
||||
import cpw.mods.fml.common.registry.GameData;
|
||||
|
||||
public class BlockReplaceHelper {
|
||||
|
||||
public static void replaceBlock(Block toReplace, Block replacement) {
|
||||
Stopwatch.time("BlockReplace");
|
||||
|
||||
Class<?>[] classTest = new Class<?>[4];
|
||||
Exception exception = null;
|
||||
|
||||
try {
|
||||
final Fields.ClassFields blocksFields = Fields.ofClass(Blocks.class);
|
||||
for (Field blockField : Blocks.class.getFields()) {
|
||||
if (Block.class.isAssignableFrom(blockField.getType())) {
|
||||
Block block = (Block) blockField.get(null);
|
||||
|
||||
if (block == toReplace) {
|
||||
final Fields.ClassFields.Field fieldAccessor = blocksFields
|
||||
.getUntypedField(Fields.LookupType.PUBLIC, blockField.getName());
|
||||
String registryName = Block.blockRegistry.getNameForObject(block);
|
||||
int id = Block.getIdFromBlock(block);
|
||||
|
||||
Log.debug("Replacing block - $0/$1", id, registryName);
|
||||
|
||||
ReflectionUtils.setFieldValue(
|
||||
((ItemBlock) Item.getItemFromBlock(block)),
|
||||
"field_150939_a",
|
||||
replacement);
|
||||
|
||||
FMLControlledNamespacedRegistry<Block> registryBlocks = GameData.getBlockRegistry();
|
||||
Log.debug("Got BlockRegistry.");
|
||||
|
||||
Map registryObjects = ReflectionUtils.getFieldValue(registryBlocks, "registryObjects");
|
||||
Log.debug("Got registryObjects.");
|
||||
ObjectIntIdentityMap underlyingIntegerMap = ReflectionUtils
|
||||
.getFieldValue(registryBlocks, "underlyingIntegerMap");
|
||||
Log.debug("Got underlyingIntegerMap.");
|
||||
registryObjects.put(registryName, replacement);
|
||||
Log.debug(
|
||||
"Put " + replacement.getUnlocalizedName()
|
||||
+ " in registryObjects with key: "
|
||||
+ registryName);
|
||||
underlyingIntegerMap.func_148746_a(replacement, id); // OBFUSCATED put object
|
||||
Log.debug("OBFUSCATED put object - underlyingIntegerMap");
|
||||
ReflectionUtils.setFieldValue(registryBlocks, "registryObjects", registryObjects);
|
||||
Log.debug("Set new value for registryObjects: registryObjects. For object registryBlocks.");
|
||||
ReflectionUtils.setFieldValue(registryBlocks, "underlyingIntegerMap", underlyingIntegerMap);
|
||||
Log.debug(
|
||||
"Set new value for underlyingIntegerMap: underlyingIntegerMap. For object registryBlocks.");
|
||||
|
||||
Log.debug("Made " + blockField.getName() + " accessible.");
|
||||
fieldAccessor.setValue(null, replacement);
|
||||
Log.debug("Set " + blockField.getName() + " to " + replacement.getUnlocalizedName() + ".");
|
||||
|
||||
Method delegateNameMethod = replacement.delegate.getClass()
|
||||
.getDeclaredMethod("setName", String.class);
|
||||
delegateNameMethod.setAccessible(true);
|
||||
Log.debug("Made " + delegateNameMethod.getName() + " accessible.");
|
||||
delegateNameMethod.invoke(replacement.delegate, toReplace.delegate.name());
|
||||
Log.debug("Invoked " + delegateNameMethod.getName() + ".");
|
||||
|
||||
classTest[0] = blockField.get(null).getClass();
|
||||
classTest[1] = Block.blockRegistry.getObjectById(id).getClass();
|
||||
classTest[2] = ((ItemBlock) Item.getItemFromBlock(replacement)).field_150939_a.getClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
Stopwatch.finish("BlockReplace");
|
||||
|
||||
Log.debug("Check field: $0", classTest[0]);
|
||||
Log.debug("Check block registry: $0", classTest[1]);
|
||||
Log.debug("Check item: $0", classTest[2]);
|
||||
|
||||
if (classTest[0] != classTest[1] || classTest[0] != classTest[2] || classTest[0] == null) {
|
||||
throw new RuntimeException(
|
||||
"HardcoreEnderExpansion was unable to replace block " + toReplace.getUnlocalizedName()
|
||||
+ "! Debug info to report: "
|
||||
+ classTest[0]
|
||||
+ ","
|
||||
+ classTest[1]
|
||||
+ ","
|
||||
+ classTest[2],
|
||||
exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.item.EntityFallingBlock;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.world.World;
|
||||
@@ -104,9 +105,9 @@ public class EntityBlockTempleDragonEgg extends EntityFallingBlock {
|
||||
}
|
||||
|
||||
if (deltaY > 6D) {
|
||||
for (EntityPlayerMP player : new ArrayList<EntityPlayerMP>(worldObj.playerEntities)) {
|
||||
for (EntityPlayer player : new ArrayList<>(worldObj.playerEntities)) {
|
||||
if (player.ridingEntity != null) player.mountEntity(null);
|
||||
DragonUtil.teleportToOverworld(player);
|
||||
DragonUtil.teleportToOverworld((EntityPlayerMP) player);
|
||||
}
|
||||
|
||||
TempleEvents.destroyWorld();
|
||||
|
||||
@@ -16,7 +16,6 @@ import net.minecraft.entity.item.EntityTNTPrimed;
|
||||
import net.minecraft.entity.monster.EntityEnderman;
|
||||
import net.minecraft.entity.monster.EntityMob;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
@@ -755,9 +754,9 @@ public class EntityMobHomelandEnderman extends EntityMob implements IEndermanRen
|
||||
protected Entity findPlayerToAttack() {
|
||||
if (worldObj.isRemote) return null;
|
||||
|
||||
List<EntityPlayerMP> players = worldObj.playerEntities;
|
||||
List<EntityPlayer> players = worldObj.playerEntities;
|
||||
|
||||
for (EntityPlayerMP player : players) {
|
||||
for (EntityPlayer player : players) {
|
||||
if (!player.capabilities.disableDamage && getDistanceSqToEntity(player) <= 4096D) {
|
||||
if (isPlayerStaringIntoEyes(player)) {
|
||||
if (!shouldActHostile(player) && teleportRandomly(10D)) return null;
|
||||
|
||||
@@ -26,7 +26,6 @@ import chylex.hee.block.BlockCustomSpawner;
|
||||
import chylex.hee.block.BlockDeathFlower;
|
||||
import chylex.hee.block.BlockDeathFlowerPot;
|
||||
import chylex.hee.block.BlockDecompositionTable;
|
||||
import chylex.hee.block.BlockDragonEggCustom;
|
||||
import chylex.hee.block.BlockDungeonPuzzle;
|
||||
import chylex.hee.block.BlockEndPowderOre;
|
||||
import chylex.hee.block.BlockEnderGoo;
|
||||
@@ -48,7 +47,6 @@ import chylex.hee.block.BlockObsidianSpecial;
|
||||
import chylex.hee.block.BlockPersegrit;
|
||||
import chylex.hee.block.BlockRavagedBrick;
|
||||
import chylex.hee.block.BlockRavagedBrickSmooth;
|
||||
import chylex.hee.block.BlockReplaceHelper;
|
||||
import chylex.hee.block.BlockSpecialEffects;
|
||||
import chylex.hee.block.BlockSphalerite;
|
||||
import chylex.hee.block.BlockSpookyLeaves;
|
||||
@@ -426,8 +424,6 @@ public final class BlockList {
|
||||
}
|
||||
|
||||
public static void registerBlocks() {
|
||||
BlockReplaceHelper.replaceBlock(Blocks.dragon_egg, new BlockDragonEggCustom());
|
||||
|
||||
for (Entry<String, Block> entry : BlockList.blocks.entrySet()) {
|
||||
GameRegistryUtil.registerBlock(entry.getValue(), entry.getKey(), itemBlocks.get(entry.getKey()));
|
||||
}
|
||||
|
||||
@@ -116,11 +116,11 @@ public final class TempleEvents {
|
||||
if (world == null) setStage(DestroyStage.DELETE);
|
||||
else if (world.playerEntities.isEmpty()) setStage(DestroyStage.UNLOAD);
|
||||
else {
|
||||
List<EntityPlayerMP> players = new ArrayList<>(world.playerEntities);
|
||||
List<EntityPlayer> players = new ArrayList<>(world.playerEntities);
|
||||
|
||||
for (EntityPlayerMP player : players) {
|
||||
for (EntityPlayer player : players) {
|
||||
if (player.ridingEntity != null) player.mountEntity(null);
|
||||
DragonUtil.teleportToOverworld(player);
|
||||
DragonUtil.teleportToOverworld((EntityPlayerMP) player);
|
||||
}
|
||||
}
|
||||
} else if (stage == DestroyStage.UNLOAD) {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package chylex.hee.mixins;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.mixin.TargetedMod.VANILLA;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.mixin.IMixins;
|
||||
import com.gtnewhorizon.gtnhlib.mixin.ITargetedMod;
|
||||
import com.gtnewhorizon.gtnhlib.mixin.MixinBuilder;
|
||||
import com.gtnewhorizon.gtnhlib.mixin.Phase;
|
||||
import com.gtnewhorizon.gtnhlib.mixin.Side;
|
||||
|
||||
public enum Mixins implements IMixins {
|
||||
|
||||
REPLACE_DRAGON_EGG(new MixinBuilder("Replaces the dragon egg").setApplyIf(() -> true)
|
||||
.addMixinClasses("minecraft.MixinBlock").addTargetedMod(VANILLA).setSide(Side.BOTH).setPhase(Phase.EARLY));
|
||||
|
||||
private final List<String> mixinClasses;
|
||||
private final List<ITargetedMod> targetedMods;
|
||||
private final List<ITargetedMod> excludedMods;
|
||||
private final Supplier<Boolean> applyIf;
|
||||
private final Phase phase;
|
||||
private final Side side;
|
||||
|
||||
Mixins(MixinBuilder builder) {
|
||||
mixinClasses = builder.mixinClasses;
|
||||
targetedMods = builder.targetedMods;
|
||||
excludedMods = builder.excludedMods;
|
||||
applyIf = builder.applyIf;
|
||||
phase = builder.phase;
|
||||
side = builder.side;
|
||||
|
||||
if (mixinClasses.isEmpty()) throw new RuntimeException("No mixin class specified for Mixin : " + name());
|
||||
if (targetedMods.isEmpty()) throw new RuntimeException("No targeted mods specified for Mixin : " + name());
|
||||
if (applyIf == null) throw new RuntimeException("No ApplyIf function specified for Mixin : " + name());
|
||||
if (phase == null) throw new RuntimeException("No Phase specified for Mixin : " + name());
|
||||
if (side == null) throw new RuntimeException("No Side function specified for Mixin : " + name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixinClasses() {
|
||||
return mixinClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier<Boolean> getApplyIf() {
|
||||
return applyIf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Phase getPhase() {
|
||||
return phase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Side getSide() {
|
||||
return side;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ITargetedMod> getTargetedMods() {
|
||||
return targetedMods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ITargetedMod> getExcludedMods() {
|
||||
return excludedMods;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package chylex.hee.mixins.early.minecraft;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.Slice;
|
||||
|
||||
import chylex.hee.block.BlockDragonEggCustom;
|
||||
|
||||
@Mixin(Block.class)
|
||||
public class MixinBlock {
|
||||
|
||||
@ModifyArg(
|
||||
method = "registerBlocks",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/util/RegistryNamespaced;addObject(ILjava/lang/String;Ljava/lang/Object;)V"),
|
||||
slice = @Slice(
|
||||
from = @At(value = "CONSTANT", args = "intValue=122"),
|
||||
to = @At(value = "CONSTANT", args = "intValue=123")))
|
||||
private static Object hee$replaceDragonEgg(Object block) {
|
||||
return new BlockDragonEggCustom();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.management.ServerConfigurationManager;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
@@ -53,7 +54,7 @@ public class NotificationCommonProxy {
|
||||
if (manager == null) return;
|
||||
|
||||
boolean delivered = false;
|
||||
List<EntityPlayer> players = manager.playerEntityList;
|
||||
List<EntityPlayerMP> players = manager.playerEntityList;
|
||||
|
||||
for (EntityPlayer player : players) {
|
||||
if (manager.func_152596_g(player.getGameProfile())) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8.3-GTNH",
|
||||
"package": "chylex.hee.mixins.early",
|
||||
"refmap": "mixins.HardcoreEnderExpansion.refmap.json",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8.3-GTNH",
|
||||
"refmap": "mixins.HardcoreEnderExpansion.refmap.json",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8"
|
||||
}
|
||||
Reference in new issue
Block a user