2
0
Fork 0

Merge remote-tracking branch 'origin/main'

main
KeyLime17 6 months ago
commit cf0196d142

@ -1,138 +0,0 @@
package com.zivilon.cinder_loe;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lotr.common.LOTRAchievement;
import lotr.common.fac.LOTRFaction;
import lotr.common.world.LOTRWorldProvider;
import lotr.common.world.LOTRWorldProviderMiddleEarth;
import lotr.common.world.LOTRWorldProviderUtumno;
import lotr.common.world.biome.LOTRBiome;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import net.minecraft.world.WorldProvider;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.config.Configuration;
import java.util.*;
public enum CinderDimension {
ISLAND("Island", 101, LOTRWorldProviderMiddleEarth.class, false, 500, EnumSet.of(DimensionRegion.REG));
public String dimensionName;
private int defaultID;
public int dimensionID;
private Class providerClass;
private boolean loadSpawn;
public LOTRBiome[] biomeList = new LOTRBiome[256];
public Map<Integer, Integer> colorsToBiomeIDs = new HashMap<Integer, Integer>();
public List<LOTRBiome> majorBiomes = new ArrayList<LOTRBiome>();
public List<LOTRAchievement.Category> achievementCategories = new ArrayList<LOTRAchievement.Category>();
public List<LOTRAchievement> allAchievements = new ArrayList<LOTRAchievement>();
public List<LOTRFaction> factionList = new ArrayList<LOTRFaction>();
public List<CinderDimension.DimensionRegion> dimensionRegions = new ArrayList<CinderDimension.DimensionRegion>();
public int spawnCap;
private CinderDimension(String s, int i, Class c, boolean flag, int spawns, EnumSet<DimensionRegion> regions) {
this.dimensionName = s;
this.defaultID = i;
this.providerClass = c;
this.loadSpawn = flag;
this.spawnCap = spawns;
this.dimensionRegions.addAll(regions);
for (DimensionRegion r : this.dimensionRegions) {
r.setDimension(this);
}
}
public String getUntranslatedDimensionName() {
return "lotr.dimension." + this.dimensionName;
}
public String getDimensionName() {
return StatCollector.translateToLocal((String)this.getUntranslatedDimensionName());
}
public static void configureDimensions(Configuration config, String category) {
for (CinderDimension dim : CinderDimension.values()) {
dim.dimensionID = config.get(category, "Dimension ID: " + dim.dimensionName, dim.defaultID).getInt();
}
}
public static void registerDimensions() {
for (CinderDimension dim : CinderDimension.values()) {
DimensionManager.registerProviderType((int)dim.dimensionID, (Class)dim.providerClass, (boolean)dim.loadSpawn);
DimensionManager.registerDimension((int)dim.dimensionID, (int)dim.dimensionID);
}
}
public static CinderDimension getCurrentDimension(World world) {
WorldProvider provider;
if (world != null && (provider = world.provider) instanceof LOTRWorldProvider) {
return ((LOTRWorldProvider)provider).getLOTRDimension();
}
return null;
}
public static CinderDimension getCurrentDimensionWithFallback(World world) {
CinderDimension dim = CinderDimension.getCurrentDimension(world);
if (dim == null) {
return ISLAND;
}
return dim;
}
public static CinderDimension forName(String s) {
for (CinderDimension dim : CinderDimension.values()) {
if (!dim.dimensionName.equals(s)) continue;
return dim;
}
return null;
}
public static enum DimensionRegion {
REG("island");
private String regionName;
private CinderDimension dimension;
public List<LOTRFaction> factionList = new ArrayList<LOTRFaction>();
private DimensionRegion(String s) {
this.regionName = s;
}
public void setDimension(CinderDimension dim) {
this.dimension = dim;
}
public CinderDimension getDimension() {
return this.dimension;
}
public String codeName() {
return this.regionName;
}
public String getRegionName() {
return StatCollector.translateToLocal((String)("lotr.dimension." + this.dimension.dimensionName + "." + this.codeName()));
}
public static DimensionRegion forName(String regionName) {
for (DimensionRegion r : DimensionRegion.values()) {
if (!r.codeName().equals(regionName)) continue;
return r;
}
return null;
}
public static DimensionRegion forID(int ID) {
for (DimensionRegion r : DimensionRegion.values()) {
if (r.ordinal() != ID) continue;
return r;
}
return null;
}
}
}

@ -14,7 +14,7 @@ import java.util.Map;
public class CoreMod implements IFMLLoadingPlugin {
@Override
public String[] getASMTransformerClass() {
return new String[] {"com.zivilon.cinder_loe.coremod.LOTRMaterialTransformer","com.zivilon.cinder_loe.coremod.LOTRWeaponLinker", "com.zivilon.cinder_loe.coremod.LOTRBannerAdder", "com.zivilon.cinder_loe.coremod.LOTRSpawnListLinker", "com.zivilon.cinder_loe.coremod.OptiFinePatcher"};
return new String[] {"com.zivilon.cinder_loe.coremod.LOTRMaterialTransformer","com.zivilon.cinder_loe.coremod.LOTRWeaponLinker", "com.zivilon.cinder_loe.coremod.LOTRBannerAdder", "com.zivilon.cinder_loe.coremod.LOTRDimensionAdder", "com.zivilon.cinder_loe.coremod.LOTRSpawnListLinker", "com.zivilon.cinder_loe.coremod.OptiFinePatcher"};
}
@Override

@ -0,0 +1,206 @@
package com.zivilon.cinder_loe.coremod;
import com.zivilon.cinder_loe.world.CinderWorldProviderIsland;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import java.util.List;
import java.util.ArrayList;
public class LOTRDimensionAdder implements IClassTransformer {
public static List<DimensionInfo> custom_dimensions = new ArrayList<>();
// This is where you add new dimensions
public void registerDimensions() {
System.out.println("Registering dimensions");
custom_dimensions = new ArrayList<>();
// register("ISLAND", "Island", 102, CinderWorldProviderIsland.class, 100);
}
// The ASM code you shouldn't touch
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if ("lotr.common.LOTRDimension".equals(transformedName)) {
registerDimensions();
if (custom_dimensions.isEmpty()) return basicClass;
// Get class
ClassReader classReader = new ClassReader(basicClass);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, 0);
// Add the new enum constant
for (DimensionInfo dimension : custom_dimensions) {
FieldNode newEnumConstant = new FieldNode(
Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL + Opcodes.ACC_ENUM,
dimension.enum_name,
"Llotr/common/LOTRDimension;",
null,
null
);
classNode.fields.add(newEnumConstant);
}
// Locate <clinit>
MethodNode clinit = null;
for (MethodNode method : classNode.methods) {
if ("<clinit>".equals(method.name)) {
clinit = method;
break;
}
}
InsnList insns = clinit.instructions;
AbstractInsnNode constructor_injection_point = null;
for (AbstractInsnNode insn : clinit.instructions.toArray()) {
if (insn.getOpcode() == Opcodes.ICONST_2) {
constructor_injection_point = insn;
int list_size = 2 + custom_dimensions.size();
IntInsnNode push_size = new IntInsnNode(Opcodes.BIPUSH, 2 + custom_dimensions.size());
clinit.instructions.insert(insn, push_size);
clinit.instructions.remove(insn);
constructor_injection_point = push_size;
System.out.println("LOTRDimension list size: " + list_size);
break;
}
}
// Create the constructor instructions to add new dimension
InsnList constructor_injection = new InsnList();
int i = 2;
for (DimensionInfo dimension : custom_dimensions) {
System.out.println("Registering with enum " + dimension.enum_name);
System.out.println("Registering with ordinal " + i);
System.out.println("Registering with name " + dimension.dimension_name);
System.out.println("Registering with ID " + dimension.dimension_id);
constructor_injection.add(new TypeInsnNode(Opcodes.NEW, "lotr/common/LOTRDimension"));
constructor_injection.add(new InsnNode(Opcodes.DUP));
constructor_injection.add(new LdcInsnNode(dimension.enum_name));
constructor_injection.add(new IntInsnNode(Opcodes.BIPUSH, i));
constructor_injection.add(new LdcInsnNode(dimension.dimension_name));
constructor_injection.add(new IntInsnNode(Opcodes.BIPUSH, dimension.dimension_id));
constructor_injection.add(new LdcInsnNode(Type.getType(dimension.world_provider))); // World provider class
constructor_injection.add(new InsnNode(Opcodes.ICONST_0)); // Do not load spawn persistently
constructor_injection.add(new IntInsnNode(Opcodes.BIPUSH, dimension.spawn_limit)); // Set spawn cap for dimension
// Add no DimensionRegions
constructor_injection.add(new LdcInsnNode(Type.getType("Llotr/common/LOTRDimension$DimensionRegion;")));
constructor_injection.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/EnumSet", "noneOf", "(Ljava/lang/Class;)Ljava/util/EnumSet;", false));
// Add PUTSTATIC
constructor_injection.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "lotr/common/LOTRDimension", "<init>", "(Ljava/lang/String;ILjava/lang/String;ILjava/lang/Class;ZILjava/util/EnumSet;)V", false));
constructor_injection.add(new FieldInsnNode(Opcodes.PUTSTATIC, "lotr/common/LOTRDimension", dimension.enum_name, "Llotr/common/LOTRDimension;"));
i++;
}
// Insert the new instructions
if (constructor_injection_point != null) {
insns.insertBefore(constructor_injection_point, constructor_injection);
}
// Modifying the $VALUES array
// Create new instruction list to be injected later
InsnList values_array_injection = new InsnList();
// Add instructions to the instruction list
i = 2;
for (DimensionInfo dimension : custom_dimensions) {
values_array_injection.add(new InsnNode(Opcodes.DUP));
values_array_injection.add(new IntInsnNode(Opcodes.BIPUSH, i));
values_array_injection.add(new FieldInsnNode(Opcodes.GETSTATIC, "lotr/common/LOTRDimension", dimension.enum_name, "Llotr/common/LOTRDimension;"));
values_array_injection.add(new InsnNode(Opcodes.AASTORE));
i++;
}
// Find the putstatic instruction for $VALUES
// This is where the fields are injected into a list, we want to inject our instructions before this
AbstractInsnNode values_injection_point = null;
AbstractInsnNode cursor = constructor_injection_point;
while (cursor != null) {
if (cursor.getOpcode() == Opcodes.PUTSTATIC) {
values_injection_point = cursor;
break;
}
cursor = cursor.getNext();
}
if (values_injection_point == null) {
throw new RuntimeException("[CinderLoE] Could not locate $VALUES PUTSTATIC injection point for LOTRDimension!");
}
// Insert the new instructions before the putstatic instruction
if (values_injection_point != null) {
insns.insertBefore(values_injection_point, values_array_injection);
}
// Write the modified class back to a byte array
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classNode.accept(classWriter);
return classWriter.toByteArray(); // Return the modified class
}
return basicClass; // Return the unmodified class for all other classes
}
public void register(String enum_name, String dimension_name, int dimension_id, Class<?> world_provider, int spawn_limit) {
System.out.println("Registering dimension " + enum_name + " " + dimension_name + " with ID " + dimension_id);
custom_dimensions.add(new DimensionInfo(enum_name, dimension_name, dimension_id, world_provider, spawn_limit));
}
public class DimensionInfo {
String enum_name;
String dimension_name;
int dimension_id;
Class<?> world_provider;
int spawn_limit;
public DimensionInfo(String enum_name, String dimension_name, int dimension_id, Class<?> world_provider, int spawn_limit) {
this.enum_name = enum_name;
this.dimension_name = dimension_name;
this.dimension_id = dimension_id;
this.world_provider = world_provider;
this.spawn_limit = spawn_limit;
}
}
}
/* Reference
L0: new lotr/common/LOTRDimension
L3: dup
L4: ldc 'MIDDLE_EARTH'
L6: iconst_0
L7: ldc 'MiddleEarth'
L9: bipush 100
L11: ldc Class lotr/common/world/LOTRWorldProviderMiddleEarth
L13: iconst_1
L14: bipush 100
L16: getstatic Field lotr/common/LOTRDimension$DimensionRegion WEST Llotr/common/LOTRDimension$DimensionRegion;
L19: getstatic Field lotr/common/LOTRDimension$DimensionRegion EAST Llotr/common/LOTRDimension$DimensionRegion;
L22: getstatic Field lotr/common/LOTRDimension$DimensionRegion SOUTH Llotr/common/LOTRDimension$DimensionRegion;
L25: invokestatic Method java/util/EnumSet of (Ljava/lang/Enum;Ljava/lang/Enum;Ljava/lang/Enum;)Ljava/util/EnumSet;
L28: invokespecial Method lotr/common/LOTRDimension <init> (Ljava/lang/String;ILjava/lang/String;ILjava/lang/Class;ZILjava/util/EnumSet;)V
L31: putstatic Field lotr/common/LOTRDimension MIDDLE_EARTH Llotr/common/LOTRDimension;
L34: new lotr/common/LOTRDimension
*/

@ -1,6 +1,5 @@
package com.zivilon.cinder_loe.world;
import com.zivilon.cinder_loe.CinderDimension;
import lotr.common.LOTRDimension;
import lotr.common.LOTRLevelData;
import lotr.common.world.LOTRChunkProvider;
@ -9,8 +8,13 @@ import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.chunk.IChunkProvider;
public class CinderWorldProviderIsland extends LOTRWorldProvider {
public static LOTRDimension cached_enum;
static {
for (LOTRDimension dimension : LOTRDimension.values()) {
if (dimension.name().equals("ISLAND")) cached_enum = dimension;
}
}
public IChunkProvider createChunkGenerator() {
return new LOTRChunkProvider(this.worldObj, this.worldObj.getSeed());
@ -34,6 +38,6 @@ public class CinderWorldProviderIsland extends LOTRWorldProvider {
@Override
public LOTRDimension getLOTRDimension() {
return CinderDimension.ISLAND;
return cached_enum;
}
}
Loading…
Cancel
Save