Entity related mixin.
This commit is contained in:
parent
a1bd86e8af
commit
2e6ad0cfb0
|
@ -1,15 +1,19 @@
|
|||
package io.izzel.arclight.common;
|
||||
|
||||
import com.google.gson.internal.bind.TypeAdapters;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.izzel.arclight.api.EnumHelper;
|
||||
import io.izzel.arclight.api.Unsafe;
|
||||
import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger;
|
||||
import io.izzel.arclight.common.mod.util.log.ArclightLazyLogManager;
|
||||
import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper;
|
||||
import io.izzel.arclight.common.util.EnumTypeFactory;
|
||||
import io.izzel.arclight.i18n.ArclightConfig;
|
||||
import io.izzel.arclight.i18n.ArclightLocale;
|
||||
import net.minecraftforge.server.ServerMain;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
@ -37,6 +41,7 @@ public abstract class ArclightMain {
|
|||
ArclightI18nLogger.getLogger("Arclight").info("loading-mapping");
|
||||
Objects.requireNonNull(ArclightRemapper.INSTANCE);
|
||||
this.beforeStart();
|
||||
this.dirtyHacks();
|
||||
ServerMain.main(args);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@ -44,6 +49,14 @@ public abstract class ArclightMain {
|
|||
}
|
||||
}
|
||||
|
||||
private void dirtyHacks() throws Exception {
|
||||
TypeAdapters.ENUM_FACTORY.create(null, TypeToken.get(ArclightMain.class));
|
||||
Field field = TypeAdapters.class.getDeclaredField("ENUM_FACTORY");
|
||||
Object base = Unsafe.staticFieldBase(field);
|
||||
long offset = Unsafe.staticFieldOffset(field);
|
||||
Unsafe.putObjectVolatile(base, offset, new EnumTypeFactory());
|
||||
}
|
||||
|
||||
private void printLogo() throws Exception {
|
||||
try (InputStream stream = getClass().getResourceAsStream("/META-INF/MANIFEST.MF")) {
|
||||
Manifest manifest = new Manifest(stream);
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package io.izzel.arclight.common.bridge.bukkit;
|
||||
|
||||
import io.izzel.arclight.i18n.conf.EntityPropertySpec;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface EntityTypeBridge {
|
||||
|
||||
void bridge$setup(ResourceLocation location, EntityType<?> entityType, EntityPropertySpec spec);
|
||||
|
||||
EntityType<?> bridge$getHandle();
|
||||
|
||||
EntityPropertySpec bridge$getSpec();
|
||||
|
||||
Function<Location, ? extends Entity> bridge$entityFactory();
|
||||
|
||||
void bridge$setEntityFactory(Function<Location, ? extends Entity> function);
|
||||
}
|
|
@ -4,8 +4,13 @@ import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
|
|||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.craftbukkit.v.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaItem;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface MaterialBridge {
|
||||
|
||||
|
@ -17,4 +22,12 @@ public interface MaterialBridge {
|
|||
MaterialPropertySpec bridge$getSpec();
|
||||
|
||||
MaterialPropertySpec.MaterialType bridge$getType();
|
||||
|
||||
Function<CraftMetaItem, ItemMeta> bridge$itemMetaFactory();
|
||||
|
||||
void bridge$setItemMetaFactory(Function<CraftMetaItem, ItemMeta> func);
|
||||
|
||||
Function<CraftBlock, BlockState> bridge$blockStateFactory();
|
||||
|
||||
void bridge$setBlockStateFactory(Function<CraftBlock, BlockState> func);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package io.izzel.arclight.common.mixin.bukkit;
|
||||
|
||||
import io.izzel.arclight.common.bridge.bukkit.MaterialBridge;
|
||||
import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.craftbukkit.v.block.CraftBlock;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(value = CraftBlock.class, remap = false)
|
||||
public abstract class CraftBlockMixin {
|
||||
|
||||
// @formatter:off
|
||||
@Shadow public abstract Material getType();
|
||||
// @formatter:on
|
||||
|
||||
@Inject(method = "getState", cancellable = true, at = @At("HEAD"))
|
||||
private void arclight$getState(CallbackInfoReturnable<BlockState> cir) {
|
||||
MaterialBridge bridge = (MaterialBridge) (Object) getType();
|
||||
if (bridge.bridge$getType() != MaterialPropertySpec.MaterialType.VANILLA) {
|
||||
cir.setReturnValue(bridge.bridge$blockStateFactory().apply((CraftBlock) (Object) this));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package io.izzel.arclight.common.mixin.bukkit;
|
||||
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModChestedHorse;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModEntity;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModHorse;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModLivingEntity;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModMinecart;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModMinecartContainer;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModMob;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModProjectile;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModRaider;
|
||||
import io.izzel.arclight.common.mod.server.entity.ArclightModVillager;
|
||||
import net.minecraft.entity.AgeableEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.FlyingEntity;
|
||||
import net.minecraft.entity.IProjectile;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.MobEntity;
|
||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||
import net.minecraft.entity.item.minecart.ContainerMinecartEntity;
|
||||
import net.minecraft.entity.merchant.villager.AbstractVillagerEntity;
|
||||
import net.minecraft.entity.monster.AbstractRaiderEntity;
|
||||
import net.minecraft.entity.passive.GolemEntity;
|
||||
import net.minecraft.entity.passive.TameableEntity;
|
||||
import net.minecraft.entity.passive.horse.AbstractChestedHorseEntity;
|
||||
import net.minecraft.entity.passive.horse.AbstractHorseEntity;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftAgeable;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftFlying;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftGolem;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftTameableAnimal;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(value = CraftEntity.class, remap = false)
|
||||
public class CraftEntityMixin {
|
||||
|
||||
@Inject(method = "getEntity", cancellable = true, at = @At(value = "NEW", target = "java/lang/AssertionError"))
|
||||
private static void arclight$modEntity(CraftServer server, Entity entity, CallbackInfoReturnable<CraftEntity> cir) {
|
||||
if (entity instanceof LivingEntity) {
|
||||
if (entity instanceof MobEntity) {
|
||||
if (entity instanceof AgeableEntity) {
|
||||
if (entity instanceof AbstractHorseEntity) {
|
||||
if (entity instanceof AbstractChestedHorseEntity) {
|
||||
cir.setReturnValue(new ArclightModChestedHorse(server, (AbstractChestedHorseEntity) entity));
|
||||
return;
|
||||
}
|
||||
cir.setReturnValue(new ArclightModHorse(server, (AbstractHorseEntity) entity));
|
||||
return;
|
||||
}
|
||||
if (entity instanceof AbstractVillagerEntity) {
|
||||
cir.setReturnValue(new ArclightModVillager(server, (AbstractVillagerEntity) entity));
|
||||
return;
|
||||
}
|
||||
if (entity instanceof TameableEntity) {
|
||||
cir.setReturnValue(new CraftTameableAnimal(server, (TameableEntity) entity));
|
||||
return;
|
||||
}
|
||||
cir.setReturnValue(new CraftAgeable(server, (AgeableEntity) entity));
|
||||
return;
|
||||
}
|
||||
if (entity instanceof FlyingEntity) {
|
||||
cir.setReturnValue(new CraftFlying(server, (FlyingEntity) entity));
|
||||
return;
|
||||
}
|
||||
if (entity instanceof AbstractRaiderEntity) {
|
||||
cir.setReturnValue(new ArclightModRaider(server, (AbstractRaiderEntity) entity));
|
||||
return;
|
||||
}
|
||||
if (entity instanceof GolemEntity) {
|
||||
cir.setReturnValue(new CraftGolem(server, (GolemEntity) entity));
|
||||
return;
|
||||
}
|
||||
cir.setReturnValue(new ArclightModMob(server, (MobEntity) entity));
|
||||
return;
|
||||
}
|
||||
cir.setReturnValue(new ArclightModLivingEntity(server, (LivingEntity) entity));
|
||||
return;
|
||||
}
|
||||
if (entity instanceof AbstractMinecartEntity) {
|
||||
if (entity instanceof ContainerMinecartEntity) {
|
||||
cir.setReturnValue(new ArclightModMinecartContainer(server, (ContainerMinecartEntity) entity));
|
||||
return;
|
||||
}
|
||||
cir.setReturnValue(new ArclightModMinecart(server, (AbstractMinecartEntity) entity));
|
||||
return;
|
||||
}
|
||||
if (entity instanceof IProjectile) {
|
||||
cir.setReturnValue(new ArclightModProjectile(server, entity));
|
||||
return;
|
||||
}
|
||||
cir.setReturnValue(new ArclightModEntity(server, entity));
|
||||
}
|
||||
}
|
|
@ -1,29 +1,10 @@
|
|||
package io.izzel.arclight.common.mixin.bukkit;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.izzel.arclight.common.bridge.bukkit.MaterialBridge;
|
||||
import io.izzel.arclight.common.mod.ArclightMod;
|
||||
import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftItemFactory;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaArmorStand;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBanner;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBlockState;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBook;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBookSigned;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaCharge;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaCrossbow;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaEnchantedBook;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaFirework;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaItem;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaKnowledgeBook;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaLeatherArmor;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaMap;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaPotion;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaSkull;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaSpawnEgg;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaSuspiciousStew;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaTropicalFishBucket;
|
||||
import org.bukkit.craftbukkit.v.util.CraftLegacy;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
@ -31,83 +12,15 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@Mixin(value = CraftItemFactory.class, remap = false)
|
||||
public class CraftItemFactoryMixin {
|
||||
|
||||
private static final Map<String, BiFunction<Material, CraftMetaItem, ItemMeta>> TYPES = ImmutableMap
|
||||
.<String, BiFunction<Material, CraftMetaItem, ItemMeta>>builder()
|
||||
.put("ARMOR_STAND", (a, b) -> new CraftMetaArmorStand(b))
|
||||
.put("BANNER", (a, b) -> new CraftMetaBanner(b))
|
||||
.put("TILE_ENTITY", (a, b) -> new CraftMetaBlockState(b, a))
|
||||
.put("BOOK", (a, b) -> new CraftMetaBook(b))
|
||||
.put("BOOK_SIGNED", (a, b) -> new CraftMetaBookSigned(b))
|
||||
.put("SKULL", (a, b) -> new CraftMetaSkull(b))
|
||||
.put("LEATHER_ARMOR", (a, b) -> new CraftMetaLeatherArmor(b))
|
||||
.put("MAP", (a, b) -> new CraftMetaMap(b))
|
||||
.put("POTION", (a, b) -> new CraftMetaPotion(b))
|
||||
.put("SPAWN_EGG", (a, b) -> new CraftMetaSpawnEgg(b))
|
||||
.put("ENCHANTED", (a, b) -> new CraftMetaEnchantedBook(b))
|
||||
.put("FIREWORK", (a, b) -> new CraftMetaFirework(b))
|
||||
.put("FIREWORK_EFFECT", (a, b) -> new CraftMetaCharge(b))
|
||||
.put("KNOWLEDGE_BOOK", (a, b) -> new CraftMetaKnowledgeBook(b))
|
||||
.put("TROPICAL_FISH_BUCKET", (a, b) -> new CraftMetaTropicalFishBucket(b))
|
||||
.put("CROSSBOW", (a, b) -> new CraftMetaCrossbow(b))
|
||||
.put("SUSPICIOUS_STEW", (a, b) -> new CraftMetaSuspiciousStew(b))
|
||||
.put("UNSPECIFIC", (a, b) -> new CraftMetaItem(b))
|
||||
.build();
|
||||
|
||||
@SuppressWarnings("AmbiguousMixinReference")
|
||||
@Inject(method = "getItemMeta*", require = 0, expect = 0, cancellable = true, at = @At("HEAD"))
|
||||
private void arclight$getItemMeta(Material material, CraftMetaItem meta, CallbackInfoReturnable<ItemMeta> cir) {
|
||||
MaterialBridge bridge = (MaterialBridge) (Object) CraftLegacy.fromLegacy(material);
|
||||
if (bridge.bridge$getType() != MaterialPropertySpec.MaterialType.VANILLA) {
|
||||
MaterialPropertySpec spec = bridge.bridge$getSpec();
|
||||
BiFunction<Material, CraftMetaItem, ItemMeta> func;
|
||||
if (spec == null || spec.itemMetaType == null) {
|
||||
func = (a, b) -> new CraftMetaItem(b);
|
||||
} else {
|
||||
func = TYPES.get(spec.itemMetaType);
|
||||
if (func == null) {
|
||||
func = (a, b) -> dynamicCreate(spec.itemMetaType, a, b);
|
||||
}
|
||||
}
|
||||
cir.setReturnValue(func.apply(material, meta));
|
||||
cir.setReturnValue(bridge.bridge$itemMetaFactory().apply(meta));
|
||||
}
|
||||
}
|
||||
|
||||
private ItemMeta dynamicCreate(String type, Material material, CraftMetaItem meta) {
|
||||
try {
|
||||
Class<?> cl = Class.forName(type);
|
||||
if (!CraftMetaItem.class.isAssignableFrom(cl)) {
|
||||
throw new IllegalArgumentException("" + cl + " is not assignable from " + CraftMetaItem.class);
|
||||
}
|
||||
for (Constructor<?> constructor : cl.getDeclaredConstructors()) {
|
||||
Class<?>[] parameterTypes = constructor.getParameterTypes();
|
||||
if (parameterTypes.length == 1) {
|
||||
if (parameterTypes[0] == Material.class) {
|
||||
constructor.setAccessible(true);
|
||||
return (ItemMeta) constructor.newInstance(material);
|
||||
} else if (CraftMetaItem.class.isAssignableFrom(parameterTypes[0])) {
|
||||
constructor.setAccessible(true);
|
||||
return (ItemMeta) constructor.newInstance(meta);
|
||||
}
|
||||
} else if (parameterTypes.length == 2) {
|
||||
if (parameterTypes[0] == Material.class && CraftMetaItem.class.isAssignableFrom(parameterTypes[1])) {
|
||||
constructor.setAccessible(true);
|
||||
return (ItemMeta) constructor.newInstance(material, meta);
|
||||
} else if (parameterTypes[1] == Material.class && CraftMetaItem.class.isAssignableFrom(parameterTypes[0])) {
|
||||
constructor.setAccessible(true);
|
||||
return (ItemMeta) constructor.newInstance(meta, material);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ArclightMod.LOGGER.warn("Bad itemMetaType {} for {}: {}", type, material, e);
|
||||
}
|
||||
return new CraftMetaItem(meta);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package io.izzel.arclight.common.mixin.bukkit;
|
||||
|
||||
import io.izzel.arclight.common.bridge.bukkit.EntityTypeBridge;
|
||||
import io.izzel.arclight.common.bridge.entity.EntityBridge;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v.CraftWorld;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@Mixin(value = CraftWorld.class, remap = false)
|
||||
public class CraftWorldMixin {
|
||||
|
||||
@Inject(method = "spawnEntity", cancellable = true, at = @At("HEAD"))
|
||||
private void arclight$useFactory(Location loc, EntityType entityType, CallbackInfoReturnable<Entity> cir) {
|
||||
Function<Location, ? extends net.minecraft.entity.Entity> factory = ((EntityTypeBridge) (Object) entityType).bridge$entityFactory();
|
||||
if (factory != null) {
|
||||
cir.setReturnValue(((EntityBridge) factory.apply(loc)).bridge$getBukkitEntity());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package io.izzel.arclight.common.mixin.bukkit;
|
||||
|
||||
import io.izzel.arclight.common.bridge.bukkit.EntityTypeBridge;
|
||||
import io.izzel.arclight.common.mod.ArclightMod;
|
||||
import io.izzel.arclight.i18n.LocalizedException;
|
||||
import io.izzel.arclight.i18n.conf.EntityPropertySpec;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.v.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@Mixin(value = EntityType.class, remap = false)
|
||||
public class EntityTypeMixin implements EntityTypeBridge {
|
||||
|
||||
@Shadow @Final @Mutable private NamespacedKey key;
|
||||
@Shadow @Final @Mutable private Class<? extends Entity> clazz;
|
||||
|
||||
private net.minecraft.entity.EntityType<?> handleType;
|
||||
private EntityPropertySpec spec;
|
||||
private Function<Location, ? extends net.minecraft.entity.Entity> factory;
|
||||
|
||||
@Override
|
||||
public void bridge$setup(ResourceLocation location, net.minecraft.entity.EntityType<?> entityType, EntityPropertySpec spec) {
|
||||
this.key = CraftNamespacedKey.fromMinecraft(location);
|
||||
this.handleType = entityType;
|
||||
this.spec = spec.clone();
|
||||
this.setup();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void setup() {
|
||||
if (this.spec.entityClass != null) {
|
||||
try {
|
||||
Class<?> cl = Class.forName(this.spec.entityClass);
|
||||
if (!Entity.class.isAssignableFrom(cl)) {
|
||||
throw LocalizedException.checked("registry.entity.not-subclass", cl, Entity.class);
|
||||
}
|
||||
this.clazz = (Class<? extends Entity>) cl;
|
||||
} catch (Exception e) {
|
||||
if (e instanceof LocalizedException) {
|
||||
ArclightMod.LOGGER.warn(((LocalizedException) e).node(), ((LocalizedException) e).args());
|
||||
} else {
|
||||
ArclightMod.LOGGER.warn("registry.entity.error", this, this.spec.entityClass, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.factory = loc -> {
|
||||
if (loc != null && loc.getWorld() != null) {
|
||||
ServerWorld world = ((CraftWorld) loc.getWorld()).getHandle();
|
||||
net.minecraft.entity.Entity entity = handleType.create(world);
|
||||
if (entity != null) {
|
||||
entity.setPositionAndRotation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
|
||||
}
|
||||
return entity;
|
||||
} else return null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.entity.EntityType<?> bridge$getHandle() {
|
||||
return this.handleType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPropertySpec bridge$getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Location, ? extends net.minecraft.entity.Entity> bridge$entityFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridge$setEntityFactory(Function<Location, ? extends net.minecraft.entity.Entity> function) {
|
||||
this.factory = function;
|
||||
}
|
||||
}
|
|
@ -1,18 +1,44 @@
|
|||
package io.izzel.arclight.common.mixin.bukkit;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.izzel.arclight.common.bridge.block.FireBlockBridge;
|
||||
import io.izzel.arclight.common.bridge.bukkit.MaterialBridge;
|
||||
import io.izzel.arclight.common.mod.ArclightMod;
|
||||
import io.izzel.arclight.i18n.LocalizedException;
|
||||
import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.FallingBlock;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.craftbukkit.v.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.v.block.CraftBlockEntityState;
|
||||
import org.bukkit.craftbukkit.v.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaArmorStand;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBanner;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBlockState;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBook;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaBookSigned;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaCharge;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaCrossbow;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaEnchantedBook;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaFirework;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaItem;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaKnowledgeBook;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaLeatherArmor;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaMap;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaPotion;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaSkull;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaSpawnEgg;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaSuspiciousStew;
|
||||
import org.bukkit.craftbukkit.v.inventory.CraftMetaTropicalFishBucket;
|
||||
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
@ -23,6 +49,9 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Mixin(value = Material.class, remap = false)
|
||||
public abstract class MaterialMixin implements MaterialBridge {
|
||||
|
@ -34,6 +63,29 @@ public abstract class MaterialMixin implements MaterialBridge {
|
|||
@Shadow public abstract boolean isBlock();
|
||||
// @formatter:on
|
||||
|
||||
private static final Map<String, BiFunction<Material, CraftMetaItem, ItemMeta>> TYPES = ImmutableMap
|
||||
.<String, BiFunction<Material, CraftMetaItem, ItemMeta>>builder()
|
||||
.put("ARMOR_STAND", (a, b) -> b instanceof CraftMetaArmorStand ? b : new CraftMetaArmorStand(b))
|
||||
.put("BANNER", (a, b) -> b instanceof CraftMetaBanner ? b : new CraftMetaBanner(b))
|
||||
.put("TILE_ENTITY", (a, b) -> new CraftMetaBlockState(b, a))
|
||||
.put("BOOK", (a, b) -> b != null && b.getClass().equals(CraftMetaBook.class) ? b : new CraftMetaBook(b))
|
||||
.put("BOOK_SIGNED", (a, b) -> b instanceof CraftMetaBookSigned ? b : new CraftMetaBookSigned(b))
|
||||
.put("SKULL", (a, b) -> b instanceof CraftMetaSkull ? b : new CraftMetaSkull(b))
|
||||
.put("LEATHER_ARMOR", (a, b) -> b instanceof CraftMetaLeatherArmor ? b : new CraftMetaLeatherArmor(b))
|
||||
.put("MAP", (a, b) -> b instanceof CraftMetaMap ? b : new CraftMetaMap(b))
|
||||
.put("POTION", (a, b) -> b instanceof CraftMetaPotion ? b : new CraftMetaPotion(b))
|
||||
.put("SPAWN_EGG", (a, b) -> b instanceof CraftMetaSpawnEgg ? b : new CraftMetaSpawnEgg(b))
|
||||
.put("ENCHANTED", (a, b) -> b instanceof CraftMetaEnchantedBook ? b : new CraftMetaEnchantedBook(b))
|
||||
.put("FIREWORK", (a, b) -> b instanceof CraftMetaFirework ? b : new CraftMetaFirework(b))
|
||||
.put("FIREWORK_EFFECT", (a, b) -> b instanceof CraftMetaCharge ? b : new CraftMetaCharge(b))
|
||||
.put("KNOWLEDGE_BOOK", (a, b) -> b instanceof CraftMetaKnowledgeBook ? b : new CraftMetaKnowledgeBook(b))
|
||||
.put("TROPICAL_FISH_BUCKET", (a, b) -> b instanceof CraftMetaTropicalFishBucket ? b : new CraftMetaTropicalFishBucket(b))
|
||||
.put("CROSSBOW", (a, b) -> b instanceof CraftMetaCrossbow ? b : new CraftMetaCrossbow(b))
|
||||
.put("SUSPICIOUS_STEW", (a, b) -> b instanceof CraftMetaSuspiciousStew ? b : new CraftMetaSuspiciousStew(b))
|
||||
.put("UNSPECIFIC", (a, b) -> new CraftMetaItem(b))
|
||||
.put("NULL", (a, b) -> null)
|
||||
.build();
|
||||
|
||||
private MaterialPropertySpec.MaterialType arclight$type = MaterialPropertySpec.MaterialType.VANILLA;
|
||||
private MaterialPropertySpec arclight$spec;
|
||||
|
||||
|
@ -159,6 +211,30 @@ public abstract class MaterialMixin implements MaterialBridge {
|
|||
return arclight$type;
|
||||
}
|
||||
|
||||
private Function<CraftMetaItem, ItemMeta> arclight$metaFunc;
|
||||
|
||||
@Override
|
||||
public Function<CraftMetaItem, ItemMeta> bridge$itemMetaFactory() {
|
||||
return arclight$metaFunc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridge$setItemMetaFactory(Function<CraftMetaItem, ItemMeta> func) {
|
||||
this.arclight$metaFunc = func;
|
||||
}
|
||||
|
||||
private Function<CraftBlock, BlockState> arclight$stateFunc;
|
||||
|
||||
@Override
|
||||
public Function<CraftBlock, BlockState> bridge$blockStateFactory() {
|
||||
return arclight$stateFunc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridge$setBlockStateFactory(Function<CraftBlock, BlockState> func) {
|
||||
this.arclight$stateFunc = func;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridge$setupBlock(ResourceLocation key, Block block, MaterialPropertySpec spec) {
|
||||
this.arclight$spec = spec.clone();
|
||||
|
@ -233,6 +309,124 @@ public abstract class MaterialMixin implements MaterialBridge {
|
|||
if (arclight$spec.blastResistance == null) {
|
||||
arclight$spec.blastResistance = block != null ? block.getExplosionResistance() : 0;
|
||||
}
|
||||
if (arclight$spec.itemMetaType == null) {
|
||||
arclight$spec.itemMetaType = "UNSPECIFIC";
|
||||
}
|
||||
BiFunction<Material, CraftMetaItem, ItemMeta> function = TYPES.get(arclight$spec.itemMetaType);
|
||||
if (function != null) {
|
||||
this.arclight$metaFunc = meta -> function.apply((Material) (Object) this, meta);
|
||||
} else {
|
||||
this.arclight$metaFunc = dynamicMetaCreator(arclight$spec.itemMetaType);
|
||||
}
|
||||
this.setupBlockStateFunc();
|
||||
}
|
||||
|
||||
private void setupBlockStateFunc() {
|
||||
if (arclight$spec.blockStateClass != null) {
|
||||
try {
|
||||
Class<?> cl = Class.forName(arclight$spec.blockStateClass);
|
||||
if (!CraftBlockState.class.isAssignableFrom(cl)) {
|
||||
throw LocalizedException.checked("registry.block-state.not-subclass", cl, CraftBlockState.class);
|
||||
}
|
||||
for (Constructor<?> constructor : cl.getDeclaredConstructors()) {
|
||||
if (constructor.getParameterTypes().length == 1
|
||||
&& org.bukkit.block.Block.class.isAssignableFrom(constructor.getParameterTypes()[0])) {
|
||||
constructor.setAccessible(true);
|
||||
this.arclight$stateFunc = b -> {
|
||||
try {
|
||||
return (BlockState) constructor.newInstance(b);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof LocalizedException) {
|
||||
ArclightMod.LOGGER.warn(((LocalizedException) e).node(), ((LocalizedException) e).args());
|
||||
} else {
|
||||
ArclightMod.LOGGER.warn("registry.block-state.error", this, arclight$spec.blockStateClass, e);
|
||||
}
|
||||
}
|
||||
if (this.arclight$stateFunc == null) {
|
||||
ArclightMod.LOGGER.warn("registry.block-state.no-candidate", this, arclight$spec.blockStateClass);
|
||||
}
|
||||
}
|
||||
if (this.arclight$stateFunc == null) {
|
||||
this.arclight$stateFunc = b -> {
|
||||
TileEntity tileEntity = b.getCraftWorld().getHandle().getTileEntity(b.getPosition());
|
||||
return tileEntity == null ? new CraftBlockState(b) : new CraftBlockEntityState<>(b, tileEntity.getClass());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private Function<CraftMetaItem, ItemMeta> dynamicMetaCreator(String type) {
|
||||
Function<CraftMetaItem, ItemMeta> candidate = null;
|
||||
try {
|
||||
Class<?> cl = Class.forName(type);
|
||||
if (!CraftMetaItem.class.isAssignableFrom(cl)) {
|
||||
throw LocalizedException.checked("registry.meta-type.not-subclass", cl, CraftMetaItem.class);
|
||||
}
|
||||
for (Constructor<?> constructor : cl.getDeclaredConstructors()) {
|
||||
Class<?>[] parameterTypes = constructor.getParameterTypes();
|
||||
if (parameterTypes.length == 1) {
|
||||
if (parameterTypes[0] == Material.class) {
|
||||
constructor.setAccessible(true);
|
||||
candidate = meta -> {
|
||||
try {
|
||||
return (ItemMeta) constructor.newInstance(this);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
break;
|
||||
} else if (CraftMetaItem.class.isAssignableFrom(parameterTypes[0])) {
|
||||
constructor.setAccessible(true);
|
||||
candidate = meta -> {
|
||||
try {
|
||||
return (ItemMeta) constructor.newInstance(meta);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
} else if (parameterTypes.length == 2) {
|
||||
if (parameterTypes[0] == Material.class && CraftMetaItem.class.isAssignableFrom(parameterTypes[1])) {
|
||||
constructor.setAccessible(true);
|
||||
candidate = meta -> {
|
||||
try {
|
||||
return (ItemMeta) constructor.newInstance(this, meta);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
break;
|
||||
} else if (parameterTypes[1] == Material.class && CraftMetaItem.class.isAssignableFrom(parameterTypes[0])) {
|
||||
constructor.setAccessible(true);
|
||||
candidate = meta -> {
|
||||
try {
|
||||
return (ItemMeta) constructor.newInstance(meta, this);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof LocalizedException) {
|
||||
ArclightMod.LOGGER.warn(((LocalizedException) e).node(), ((LocalizedException) e).args());
|
||||
} else {
|
||||
ArclightMod.LOGGER.warn("registry.meta-type.error", this, type, e);
|
||||
}
|
||||
}
|
||||
if (candidate == null) {
|
||||
ArclightMod.LOGGER.warn("registry.meta-type.no-candidate", this, type);
|
||||
candidate = CraftMetaItem::new;
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
private static int tryGetMaxStackSize(Item item) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import net.minecraft.util.math.EntityRayTraceResult;
|
|||
import net.minecraft.util.math.RayTraceResult;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftEntity;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.Egg;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
@ -50,7 +51,7 @@ public abstract class EggEntityMixin extends ThrowableEntityMixin {
|
|||
}
|
||||
if (hatching) {
|
||||
for (int i = 0; i < b0; ++i) {
|
||||
final Entity entity = ((WorldBridge) this.world).bridge$getWorld().createEntity(new Location(((WorldBridge) this.world).bridge$getWorld(), this.posX, this.posY, this.posZ, this.rotationYaw, 0.0f), hatchingType.getEntityClass());
|
||||
Entity entity = ((CraftEntity) ((WorldBridge) this.world).bridge$getWorld().spawnEntity(new Location(((WorldBridge) this.world).bridge$getWorld(), this.posX, this.posY, this.posZ, this.rotationYaw, 0.0f), hatchingType)).getHandle();
|
||||
if (((EntityBridge) entity).bridge$getBukkitEntity() instanceof Ageable) {
|
||||
((Ageable) ((EntityBridge) entity).bridge$getBukkitEntity()).setBaby();
|
||||
}
|
||||
|
|
|
@ -4,10 +4,13 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import io.izzel.arclight.api.EnumHelper;
|
||||
import io.izzel.arclight.api.Unsafe;
|
||||
import io.izzel.arclight.common.bridge.bukkit.EntityTypeBridge;
|
||||
import io.izzel.arclight.common.bridge.bukkit.MaterialBridge;
|
||||
import io.izzel.arclight.common.mod.ArclightMod;
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import io.izzel.arclight.common.mod.util.potion.ArclightPotionEffect;
|
||||
import io.izzel.arclight.i18n.ArclightConfig;
|
||||
import io.izzel.arclight.i18n.conf.EntityPropertySpec;
|
||||
import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
|
@ -17,12 +20,16 @@ import net.minecraftforge.registries.ForgeRegistries;
|
|||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.v.enchantments.CraftEnchantment;
|
||||
import org.bukkit.craftbukkit.v.util.CraftMagicNumbers;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -32,16 +39,46 @@ import java.util.Set;
|
|||
public class BukkitRegistry {
|
||||
|
||||
private static final List<Class<?>> MAT_CTOR = ImmutableList.of(int.class);
|
||||
private static final List<Class<?>> ENTITY_CTOR = ImmutableList.of(String.class, Class.class, int.class);
|
||||
private static final Map<String, Material> BY_NAME = getStatic(Material.class, "BY_NAME");
|
||||
private static final Map<Block, Material> BLOCK_MATERIAL = getStatic(CraftMagicNumbers.class, "BLOCK_MATERIAL");
|
||||
private static final Map<Item, Material> ITEM_MATERIAL = getStatic(CraftMagicNumbers.class, "ITEM_MATERIAL");
|
||||
private static final Map<Material, Item> MATERIAL_ITEM = getStatic(CraftMagicNumbers.class, "MATERIAL_ITEM");
|
||||
private static final Map<Material, Block> MATERIAL_BLOCK = getStatic(CraftMagicNumbers.class, "MATERIAL_BLOCK");
|
||||
private static final Map<String, EntityType> ENTITY_NAME_MAP = getStatic(EntityType.class, "NAME_MAP");
|
||||
|
||||
public static void registerAll() {
|
||||
loadMaterials();
|
||||
loadPotions();
|
||||
loadEnchantments();
|
||||
loadEntities();
|
||||
}
|
||||
|
||||
private static void loadEntities() {
|
||||
int origin = EntityType.values().length;
|
||||
int i = origin;
|
||||
List<EntityType> newTypes = new ArrayList<>(ForgeRegistries.ENTITIES.getEntries().size() - origin);
|
||||
for (Map.Entry<ResourceLocation, net.minecraft.entity.EntityType<?>> entry : ForgeRegistries.ENTITIES.getEntries()) {
|
||||
ResourceLocation location = entry.getKey();
|
||||
net.minecraft.entity.EntityType<?> type = entry.getValue();
|
||||
EntityType entityType = null;
|
||||
boolean found = false;
|
||||
if (location.getNamespace().equals(NamespacedKey.MINECRAFT)) {
|
||||
entityType = EntityType.fromName(location.getPath());
|
||||
if (entityType != null) found = true;
|
||||
else ArclightMod.LOGGER.warn("Not found {} in {}", location, EntityType.class);
|
||||
}
|
||||
if (!found) {
|
||||
String name = ResourceLocationUtil.standardize(location);
|
||||
entityType = EnumHelper.makeEnum(EntityType.class, name, i++, ENTITY_CTOR, ImmutableList.of(ResourceLocationUtil.standardize(location).toLowerCase(Locale.ROOT), Entity.class, -1));
|
||||
((EntityTypeBridge) (Object) entityType).bridge$setup(location, type, entitySpec(location));
|
||||
newTypes.add(entityType);
|
||||
ArclightMod.LOGGER.debug("Registered {} as entity {}", location, entityType);
|
||||
}
|
||||
ENTITY_NAME_MAP.put(location.toString(), entityType);
|
||||
}
|
||||
EnumHelper.addEnums(EntityType.class, newTypes);
|
||||
ArclightMod.LOGGER.info("registry.entity-type", newTypes.size());
|
||||
}
|
||||
|
||||
private static void loadEnchantments() {
|
||||
|
@ -62,7 +99,7 @@ public class BukkitRegistry {
|
|||
putStatic(PotionEffectType.class, "byId", types);
|
||||
putBool(PotionEffectType.class, "acceptingNew", true);
|
||||
for (Map.Entry<ResourceLocation, Effect> entry : ForgeRegistries.POTIONS.getEntries()) {
|
||||
String name = toName(entry.getKey());
|
||||
String name = ResourceLocationUtil.standardize(entry.getKey());
|
||||
ArclightPotionEffect effect = new ArclightPotionEffect(entry.getValue(), name);
|
||||
PotionEffectType.registerPotionEffectType(effect);
|
||||
ArclightMod.LOGGER.debug("Registered {}: {} as potion", entry.getKey(), effect);
|
||||
|
@ -75,18 +112,20 @@ public class BukkitRegistry {
|
|||
int blocks = 0, items = 0;
|
||||
int i = Material.values().length;
|
||||
int origin = i;
|
||||
List<Material> list = new ArrayList<>();
|
||||
for (Map.Entry<ResourceLocation, Block> entry : ForgeRegistries.BLOCKS.getEntries()) {
|
||||
ResourceLocation location = entry.getKey();
|
||||
Block block = entry.getValue();
|
||||
Material material = Material.matchMaterial(location.toString());
|
||||
if (material == null) {
|
||||
String name = toName(location);
|
||||
String name = ResourceLocationUtil.standardize(location);
|
||||
material = EnumHelper.makeEnum(Material.class, name, i, MAT_CTOR, ImmutableList.of(i));
|
||||
((MaterialBridge) (Object) material).bridge$setupBlock(location, block, spec(location));
|
||||
((MaterialBridge) (Object) material).bridge$setupBlock(location, block, matSpec(location));
|
||||
BY_NAME.put(name, material);
|
||||
i++;
|
||||
blocks++;
|
||||
ArclightMod.LOGGER.debug("Registered {} as block {}", location, material);
|
||||
list.add(material);
|
||||
}
|
||||
BLOCK_MATERIAL.put(block, material);
|
||||
MATERIAL_BLOCK.put(material, block);
|
||||
|
@ -96,30 +135,28 @@ public class BukkitRegistry {
|
|||
Item item = entry.getValue();
|
||||
Material material = Material.matchMaterial(location.toString());
|
||||
if (material == null) {
|
||||
String name = toName(location);
|
||||
String name = ResourceLocationUtil.standardize(location);
|
||||
material = EnumHelper.makeEnum(Material.class, name, i, MAT_CTOR, ImmutableList.of(i));
|
||||
((MaterialBridge) (Object) material).bridge$setupItem(location, item, spec(location));
|
||||
((MaterialBridge) (Object) material).bridge$setupItem(location, item, matSpec(location));
|
||||
BY_NAME.put(name, material);
|
||||
i++;
|
||||
items++;
|
||||
ArclightMod.LOGGER.debug("Registered {} as item {}", location, material);
|
||||
list.add(material);
|
||||
}
|
||||
ITEM_MATERIAL.put(item, material);
|
||||
MATERIAL_ITEM.put(material, item);
|
||||
}
|
||||
EnumHelper.addEnums(Material.class, list);
|
||||
ArclightMod.LOGGER.info("registry.material", i - origin, blocks, items);
|
||||
}
|
||||
|
||||
private static String toName(ResourceLocation location) {
|
||||
return location.toString()
|
||||
.replace(':', '_')
|
||||
.replaceAll("\\s+", "_")
|
||||
.replaceAll("\\W", "")
|
||||
.toUpperCase(Locale.ENGLISH);
|
||||
private static MaterialPropertySpec matSpec(ResourceLocation location) {
|
||||
return ArclightConfig.spec().getCompat().getMaterial(location.toString()).orElse(MaterialPropertySpec.EMPTY);
|
||||
}
|
||||
|
||||
private static MaterialPropertySpec spec(ResourceLocation location) {
|
||||
return ArclightConfig.spec().getCompat().getOverride(location.toString()).orElse(MaterialPropertySpec.EMPTY);
|
||||
private static EntityPropertySpec entitySpec(ResourceLocation location) {
|
||||
return ArclightConfig.spec().getCompat().getEntity(location.toString()).orElse(EntityPropertySpec.EMPTY);
|
||||
}
|
||||
|
||||
private static <T> T getStatic(Class<?> cl, String name) {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.passive.horse.AbstractChestedHorseEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftChestedHorse;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Horse;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModChestedHorse extends CraftChestedHorse {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModChestedHorse(CraftServer server, AbstractChestedHorseEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return this.entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Horse.@NotNull Variant getVariant() {
|
||||
return Horse.Variant.HORSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModChestedHorse{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftEntity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModEntity extends CraftEntity {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModEntity(CraftServer server, Entity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModEntity{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.passive.horse.AbstractHorseEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftAbstractHorse;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Horse;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModHorse extends CraftAbstractHorse {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModHorse(CraftServer server, AbstractHorseEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EntityType getType() {
|
||||
return this.entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Horse.@NotNull Variant getVariant() {
|
||||
return Horse.Variant.HORSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModHorse{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftLivingEntity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModLivingEntity extends CraftLivingEntity {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModLivingEntity(CraftServer server, LivingEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModLivingEntity{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftMinecart;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModMinecart extends CraftMinecart {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModMinecart(CraftServer server, AbstractMinecartEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModMinecart{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.item.minecart.ContainerMinecartEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftMinecartContainer;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModMinecartContainer extends CraftMinecartContainer {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModMinecartContainer(CraftServer server, ContainerMinecartEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModMinecartContainer{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.MobEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftMob;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModMob extends CraftMob {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModMob(CraftServer server, MobEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModMob{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftProjectile;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModProjectile extends CraftProjectile {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModProjectile(CraftServer server, Entity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModProjectile{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.monster.AbstractRaiderEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftRaider;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModRaider extends CraftRaider {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModRaider(CraftServer server, AbstractRaiderEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModRaider{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.izzel.arclight.common.mod.server.entity;
|
||||
|
||||
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
|
||||
import net.minecraft.entity.merchant.villager.AbstractVillagerEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.entity.CraftAbstractVillager;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArclightModVillager extends CraftAbstractVillager {
|
||||
|
||||
private final EntityType entityType;
|
||||
|
||||
public ArclightModVillager(CraftServer server, AbstractVillagerEntity entity) {
|
||||
super(server, entity);
|
||||
this.entityType = EntityType.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.ENTITIES.getKey(entity.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
return this.entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArclightModVillager{" + entityType + '}';
|
||||
}
|
||||
}
|
|
@ -1,19 +1,15 @@
|
|||
package io.izzel.arclight.common.mod.util;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraftforge.common.util.BlockSnapshot;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v.block.*;
|
||||
import org.bukkit.craftbukkit.v.block.CraftBlock;
|
||||
|
||||
public class ArclightBlockSnapshot extends CraftBlock {
|
||||
|
||||
private final BlockSnapshot blockSnapshot;
|
||||
private final BlockState blockState;
|
||||
|
||||
public ArclightBlockSnapshot(BlockSnapshot blockSnapshot, boolean current) {
|
||||
super(blockSnapshot.getWorld(), blockSnapshot.getPos());
|
||||
this.blockSnapshot = blockSnapshot;
|
||||
this.blockState = current ? blockSnapshot.getCurrentBlock() : blockSnapshot.getReplacedBlock();
|
||||
}
|
||||
|
||||
|
@ -22,169 +18,6 @@ public class ArclightBlockSnapshot extends CraftBlock {
|
|||
return blockState;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public org.bukkit.block.BlockState getState() {
|
||||
Material material = getType();
|
||||
|
||||
switch (material) {
|
||||
case ACACIA_SIGN:
|
||||
case ACACIA_WALL_SIGN:
|
||||
case BIRCH_SIGN:
|
||||
case BIRCH_WALL_SIGN:
|
||||
case DARK_OAK_SIGN:
|
||||
case DARK_OAK_WALL_SIGN:
|
||||
case JUNGLE_SIGN:
|
||||
case JUNGLE_WALL_SIGN:
|
||||
case OAK_SIGN:
|
||||
case OAK_WALL_SIGN:
|
||||
case SPRUCE_SIGN:
|
||||
case SPRUCE_WALL_SIGN:
|
||||
return new CraftSign(this);
|
||||
case CHEST:
|
||||
case TRAPPED_CHEST:
|
||||
return new CraftChest(this);
|
||||
case FURNACE:
|
||||
return new CraftFurnaceFurnace(this);
|
||||
case DISPENSER:
|
||||
return new CraftDispenser(this);
|
||||
case DROPPER:
|
||||
return new CraftDropper(this);
|
||||
case END_GATEWAY:
|
||||
return new CraftEndGateway(this);
|
||||
case HOPPER:
|
||||
return new CraftHopper(this);
|
||||
case SPAWNER:
|
||||
return new CraftCreatureSpawner(this);
|
||||
case JUKEBOX:
|
||||
return new CraftJukebox(this);
|
||||
case BREWING_STAND:
|
||||
return new CraftBrewingStand(this);
|
||||
case CREEPER_HEAD:
|
||||
case CREEPER_WALL_HEAD:
|
||||
case DRAGON_HEAD:
|
||||
case DRAGON_WALL_HEAD:
|
||||
case PLAYER_HEAD:
|
||||
case PLAYER_WALL_HEAD:
|
||||
case SKELETON_SKULL:
|
||||
case SKELETON_WALL_SKULL:
|
||||
case WITHER_SKELETON_SKULL:
|
||||
case WITHER_SKELETON_WALL_SKULL:
|
||||
case ZOMBIE_HEAD:
|
||||
case ZOMBIE_WALL_HEAD:
|
||||
return new CraftSkull(this);
|
||||
case COMMAND_BLOCK:
|
||||
case CHAIN_COMMAND_BLOCK:
|
||||
case REPEATING_COMMAND_BLOCK:
|
||||
return new CraftCommandBlock(this);
|
||||
case BEACON:
|
||||
return new CraftBeacon(this);
|
||||
case BLACK_BANNER:
|
||||
case BLACK_WALL_BANNER:
|
||||
case BLUE_BANNER:
|
||||
case BLUE_WALL_BANNER:
|
||||
case BROWN_BANNER:
|
||||
case BROWN_WALL_BANNER:
|
||||
case CYAN_BANNER:
|
||||
case CYAN_WALL_BANNER:
|
||||
case GRAY_BANNER:
|
||||
case GRAY_WALL_BANNER:
|
||||
case GREEN_BANNER:
|
||||
case GREEN_WALL_BANNER:
|
||||
case LIGHT_BLUE_BANNER:
|
||||
case LIGHT_BLUE_WALL_BANNER:
|
||||
case LIGHT_GRAY_BANNER:
|
||||
case LIGHT_GRAY_WALL_BANNER:
|
||||
case LIME_BANNER:
|
||||
case LIME_WALL_BANNER:
|
||||
case MAGENTA_BANNER:
|
||||
case MAGENTA_WALL_BANNER:
|
||||
case ORANGE_BANNER:
|
||||
case ORANGE_WALL_BANNER:
|
||||
case PINK_BANNER:
|
||||
case PINK_WALL_BANNER:
|
||||
case PURPLE_BANNER:
|
||||
case PURPLE_WALL_BANNER:
|
||||
case RED_BANNER:
|
||||
case RED_WALL_BANNER:
|
||||
case WHITE_BANNER:
|
||||
case WHITE_WALL_BANNER:
|
||||
case YELLOW_BANNER:
|
||||
case YELLOW_WALL_BANNER:
|
||||
return new CraftBanner(this);
|
||||
case STRUCTURE_BLOCK:
|
||||
return new CraftStructureBlock(this);
|
||||
case SHULKER_BOX:
|
||||
case WHITE_SHULKER_BOX:
|
||||
case ORANGE_SHULKER_BOX:
|
||||
case MAGENTA_SHULKER_BOX:
|
||||
case LIGHT_BLUE_SHULKER_BOX:
|
||||
case YELLOW_SHULKER_BOX:
|
||||
case LIME_SHULKER_BOX:
|
||||
case PINK_SHULKER_BOX:
|
||||
case GRAY_SHULKER_BOX:
|
||||
case LIGHT_GRAY_SHULKER_BOX:
|
||||
case CYAN_SHULKER_BOX:
|
||||
case PURPLE_SHULKER_BOX:
|
||||
case BLUE_SHULKER_BOX:
|
||||
case BROWN_SHULKER_BOX:
|
||||
case GREEN_SHULKER_BOX:
|
||||
case RED_SHULKER_BOX:
|
||||
case BLACK_SHULKER_BOX:
|
||||
return new CraftShulkerBox(this);
|
||||
case ENCHANTING_TABLE:
|
||||
return new CraftEnchantingTable(this);
|
||||
case ENDER_CHEST:
|
||||
return new CraftEnderChest(this);
|
||||
case DAYLIGHT_DETECTOR:
|
||||
return new CraftDaylightDetector(this);
|
||||
case COMPARATOR:
|
||||
return new CraftComparator(this);
|
||||
case BLACK_BED:
|
||||
case BLUE_BED:
|
||||
case BROWN_BED:
|
||||
case CYAN_BED:
|
||||
case GRAY_BED:
|
||||
case GREEN_BED:
|
||||
case LIGHT_BLUE_BED:
|
||||
case LIGHT_GRAY_BED:
|
||||
case LIME_BED:
|
||||
case MAGENTA_BED:
|
||||
case ORANGE_BED:
|
||||
case PINK_BED:
|
||||
case PURPLE_BED:
|
||||
case RED_BED:
|
||||
case WHITE_BED:
|
||||
case YELLOW_BED:
|
||||
return new CraftBed(this);
|
||||
case CONDUIT:
|
||||
return new CraftConduit(this);
|
||||
case BARREL:
|
||||
return new CraftBarrel(this);
|
||||
case BELL:
|
||||
return new CraftBell(this);
|
||||
case BLAST_FURNACE:
|
||||
return new CraftBlastFurnace(this);
|
||||
case CAMPFIRE:
|
||||
return new CraftCampfire(this);
|
||||
case JIGSAW:
|
||||
return new CraftJigsaw(this);
|
||||
case LECTERN:
|
||||
return new CraftLectern(this);
|
||||
case SMOKER:
|
||||
return new CraftSmoker(this);
|
||||
default:
|
||||
TileEntity tileEntity = blockSnapshot.getTileEntity();
|
||||
if (tileEntity != null) {
|
||||
// block with unhandled TileEntity:
|
||||
return new CraftBlockEntityState<>(this, (Class<TileEntity>) tileEntity.getClass());
|
||||
} else {
|
||||
// Block without TileEntity:
|
||||
return new CraftBlockState(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ArclightBlockSnapshot fromBlockSnapshot(BlockSnapshot blockSnapshot, boolean current) {
|
||||
return new ArclightBlockSnapshot(blockSnapshot, current);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package io.izzel.arclight.common.mod.util;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class ResourceLocationUtil {
|
||||
|
||||
@Contract("null -> fail")
|
||||
public static String standardize(ResourceLocation location) {
|
||||
Preconditions.checkNotNull(location, "location");
|
||||
return location.toString()
|
||||
.replace(':', '_')
|
||||
.replaceAll("\\s+", "_")
|
||||
.replaceAll("\\W", "")
|
||||
.toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
public static String standardizeLower(ResourceLocation location) {
|
||||
return location.toString()
|
||||
.replace(':', '_')
|
||||
.replaceAll("\\s+", "_")
|
||||
.replaceAll("\\W", "")
|
||||
.toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
package io.izzel.arclight.common.mod.util.remapper;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.IntInsnNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
// 你好
|
||||
// 不要抄(笑)
|
||||
@SuppressWarnings("unused")
|
||||
public class ArclightEnumExtender {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("EnumExtender");
|
||||
|
||||
public static void process(ClassNode node, List<String> names) {
|
||||
String desc = Type.getObjectType(node.name).getDescriptor();
|
||||
FieldNode values = tryGetEnumArray(node);
|
||||
values.access &= ~Opcodes.ACC_FINAL;
|
||||
Set<String> set = countEnum(node);
|
||||
tryCreateCtor(node);
|
||||
int count = set.size();
|
||||
for (MethodNode method : node.methods) {
|
||||
if (method.name.equals("<clinit>")) {
|
||||
InsnList list = new InsnList();
|
||||
InsnList postList = new InsnList();
|
||||
for (String name : names) {
|
||||
boolean found = false;
|
||||
if (name.startsWith(NamespacedKey.MINECRAFT + ":")) {
|
||||
if (!set.contains(standardize(name.substring(NamespacedKey.MINECRAFT.length() + 1)))) {
|
||||
LOGGER.warn("Expect {} found in {}, but not", name, node.name);
|
||||
} else found = true;
|
||||
}
|
||||
if (!found) {
|
||||
name = standardize(name);
|
||||
FieldNode fieldNode = new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_ENUM, name, desc, null, null);
|
||||
node.fields.add(fieldNode);
|
||||
list.add(new TypeInsnNode(Opcodes.NEW, node.name));
|
||||
list.add(new InsnNode(Opcodes.DUP));
|
||||
list.add(new LdcInsnNode(name));
|
||||
list.add(loadInt(count));
|
||||
list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, node.name, "<init>", "(Ljava/lang/String;I)V", false));
|
||||
list.add(new FieldInsnNode(Opcodes.PUTSTATIC, node.name, name, desc));
|
||||
postList.add(new InsnNode(Opcodes.DUP));
|
||||
postList.add(loadInt(count));
|
||||
postList.add(new FieldInsnNode(Opcodes.GETSTATIC, node.name, name, desc));
|
||||
postList.add(new InsnNode(Opcodes.AASTORE));
|
||||
LOGGER.info("Added {} to {}", name, node.name);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
list.add(new FieldInsnNode(Opcodes.GETSTATIC, node.name, values.name, values.desc));
|
||||
list.add(loadInt(0));
|
||||
list.add(loadInt(count));
|
||||
list.add(new TypeInsnNode(Opcodes.ANEWARRAY, node.name));
|
||||
list.add(new InsnNode(Opcodes.DUP));
|
||||
list.add(new FieldInsnNode(Opcodes.PUTSTATIC, node.name, values.name, values.desc));
|
||||
list.add(loadInt(0));
|
||||
list.add(loadInt(set.size()));
|
||||
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V"));
|
||||
list.add(new FieldInsnNode(Opcodes.GETSTATIC, node.name, values.name, values.desc));
|
||||
postList.add(new InsnNode(Opcodes.POP));
|
||||
for (AbstractInsnNode insnNode : method.instructions) {
|
||||
if (insnNode.getOpcode() == Opcodes.RETURN) {
|
||||
method.instructions.insertBefore(insnNode, list);
|
||||
method.instructions.insertBefore(insnNode, postList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AbstractInsnNode loadInt(int i) {
|
||||
if (i >= -1 && i < 6) {
|
||||
return new InsnNode(Opcodes.ICONST_0 + i);
|
||||
} else if (i >= -128 && i < 128) {
|
||||
return new IntInsnNode(Opcodes.BIPUSH, i);
|
||||
} else if (i >= -32768 && i < 32768) {
|
||||
return new IntInsnNode(Opcodes.SIPUSH, i);
|
||||
} else {
|
||||
return new LdcInsnNode(i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void tryCreateCtor(ClassNode node) {
|
||||
boolean found = false;
|
||||
for (MethodNode method : node.methods) {
|
||||
if (method.name.equals("<init>") && method.desc.equals("(Ljava/lang/String;I)V")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
MethodNode methodNode = new MethodNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC, "<init>", "(Ljava/lang/String;I)V", null, null);
|
||||
InsnList list = new InsnList();
|
||||
list.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
list.add(new VarInsnNode(Opcodes.ALOAD, 1));
|
||||
list.add(new VarInsnNode(Opcodes.ILOAD, 2));
|
||||
list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/Enum", "<init>", "(Ljava/lang/String;I)V", false));
|
||||
list.add(new InsnNode(Opcodes.RETURN));
|
||||
methodNode.instructions = list;
|
||||
node.methods.add(methodNode);
|
||||
}
|
||||
}
|
||||
|
||||
private static String standardize(String str) {
|
||||
return str
|
||||
.replace(':', '_')
|
||||
.replaceAll("\\s+", "_")
|
||||
.replaceAll("\\W", "")
|
||||
.toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
private static Set<String> countEnum(ClassNode node) {
|
||||
Set<String> ret = new HashSet<>();
|
||||
for (FieldNode field : node.fields) {
|
||||
if ((field.access & Opcodes.ACC_ENUM) != 0) {
|
||||
ret.add(field.name);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static FieldNode tryGetEnumArray(ClassNode node) {
|
||||
String desc = '[' + Type.getObjectType(node.name).getDescriptor();
|
||||
List<FieldNode> candidates = new ArrayList<>();
|
||||
for (FieldNode field : node.fields) {
|
||||
if (Modifier.isStatic(field.access) && field.desc.equals(desc)) {
|
||||
candidates.add(field);
|
||||
}
|
||||
}
|
||||
if (candidates.size() != 1) {
|
||||
throw new RuntimeException("No $VALUES candidate found in enum class " + node.name);
|
||||
}
|
||||
return candidates.get(0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package io.izzel.arclight.common.util;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
// code from gson, Apache license
|
||||
// mute the assetiong error throwing because we dynamically add elements to enums
|
||||
public class EnumTypeFactory implements TypeAdapterFactory {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
Class<? super T> rawType = type.getRawType();
|
||||
if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {
|
||||
return null;
|
||||
}
|
||||
if (!rawType.isEnum()) {
|
||||
rawType = rawType.getSuperclass(); // handle anonymous subclasses
|
||||
}
|
||||
return (TypeAdapter<T>) new EnumTypeAdapter(rawType);
|
||||
}
|
||||
|
||||
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
|
||||
|
||||
private final Map<String, T> nameToConstant = new HashMap<String, T>();
|
||||
private final Map<T, String> constantToName = new HashMap<T, String>();
|
||||
|
||||
public EnumTypeAdapter(Class<T> classOfT) {
|
||||
for (T constant : classOfT.getEnumConstants()) {
|
||||
String name = constant.name();
|
||||
SerializedName annotation;
|
||||
try {
|
||||
annotation = classOfT.getField(name).getAnnotation(SerializedName.class);
|
||||
} catch (NoSuchFieldException e) {
|
||||
annotation = null;
|
||||
}
|
||||
if (annotation != null) {
|
||||
name = annotation.value();
|
||||
for (String alternate : annotation.alternate()) {
|
||||
nameToConstant.put(alternate, constant);
|
||||
}
|
||||
}
|
||||
nameToConstant.put(name, constant);
|
||||
constantToName.put(constant, name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T read(JsonReader in) throws IOException {
|
||||
if (in.peek() == JsonToken.NULL) {
|
||||
in.nextNull();
|
||||
return null;
|
||||
}
|
||||
return nameToConstant.get(in.nextString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, T value) throws IOException {
|
||||
out.value(value == null ? null : constantToName.get(value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,16 +5,21 @@
|
|||
"target": "@env(DEFAULT)",
|
||||
"refmap": "mixins.arclight.refmap.json",
|
||||
"setSourceFile": true,
|
||||
"plugin": "io.izzel.arclight.common.mod.ArclightMixinPlugin",
|
||||
"mixins": [
|
||||
"BukkitCommandWrapperMixin",
|
||||
"ColouredConsoleSenderMixin",
|
||||
"CraftBlockMixin",
|
||||
"CraftBlockStateMixin",
|
||||
"CraftChunkMixin",
|
||||
"CraftConsoleCommandSenderMixin",
|
||||
"CraftEntityMixin",
|
||||
"CraftEventFactoryMixin",
|
||||
"CraftItemFactoryMixin",
|
||||
"CraftMagicNumbersMixin",
|
||||
"CraftServerMixin",
|
||||
"CraftWorldMixin",
|
||||
"EntityTypeMixin",
|
||||
"JavaPluginLoaderMixin",
|
||||
"JavaPluginMixin",
|
||||
"MaterialMixin",
|
||||
|
|
|
@ -9,14 +9,25 @@ import java.util.Optional;
|
|||
@ConfigSerializable
|
||||
public class CompatSpec {
|
||||
|
||||
@Setting("property-override")
|
||||
private Map<String, MaterialPropertySpec> overrides;
|
||||
@Setting("material-property-overrides")
|
||||
private Map<String, MaterialPropertySpec> materials;
|
||||
|
||||
public Map<String, MaterialPropertySpec> getOverrides() {
|
||||
return overrides;
|
||||
@Setting("entity-property-overrides")
|
||||
private Map<String, EntityPropertySpec> entities;
|
||||
|
||||
public Map<String, MaterialPropertySpec> getMaterials() {
|
||||
return materials;
|
||||
}
|
||||
|
||||
public Optional<MaterialPropertySpec> getOverride(String key) {
|
||||
return Optional.ofNullable(overrides.get(key));
|
||||
public Optional<MaterialPropertySpec> getMaterial(String key) {
|
||||
return Optional.ofNullable(materials.get(key));
|
||||
}
|
||||
|
||||
public Map<String, EntityPropertySpec> getEntities() {
|
||||
return entities;
|
||||
}
|
||||
|
||||
public Optional<EntityPropertySpec> getEntity(String key) {
|
||||
return Optional.ofNullable(entities.get(key));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package io.izzel.arclight.i18n.conf;
|
||||
|
||||
import ninja.leaping.configurate.objectmapping.Setting;
|
||||
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class EntityPropertySpec implements Cloneable {
|
||||
|
||||
public static final EntityPropertySpec EMPTY = new EntityPropertySpec();
|
||||
|
||||
@Setting("entityClass")
|
||||
public String entityClass;
|
||||
|
||||
@Setting("entityImplClass")
|
||||
public String entityImplClass;
|
||||
|
||||
@Override
|
||||
public EntityPropertySpec clone() {
|
||||
try {
|
||||
return (EntityPropertySpec) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,6 +62,9 @@ public class MaterialPropertySpec implements Cloneable {
|
|||
@Setting("itemMetaType")
|
||||
public String itemMetaType;
|
||||
|
||||
@Setting("blockStateClass")
|
||||
public String blockStateClass;
|
||||
|
||||
@Override
|
||||
public MaterialPropertySpec clone() {
|
||||
try {
|
||||
|
|
|
@ -7,7 +7,8 @@ optimization {
|
|||
remove-stream = true
|
||||
}
|
||||
compatibility {
|
||||
property-override {
|
||||
|
||||
material-property-overrides {
|
||||
}
|
||||
entity-property-overrides {
|
||||
}
|
||||
}
|
|
@ -47,6 +47,21 @@ registry {
|
|||
enchantment = "注册了 {} 个新的附魔"
|
||||
potion = "注册了 {} 个新的药水效果"
|
||||
material = "注册了 {} 个材料,其中 {} 个方块 {} 个物品"
|
||||
entity-type = "注册了 {} 个新的生物类型"
|
||||
meta-type {
|
||||
not-subclass = "{} 不是 {} 的子类"
|
||||
error = "{} 提供的 itemMetaType {} 无效: {}"
|
||||
no-candidate = "{} 未在提供的 itemMetaType {} 找到合适的构造方法"
|
||||
}
|
||||
block-state {
|
||||
not-subclass = "{} 不是 {} 的子类"
|
||||
error = "{} 提供的 itemMetaType {} 无效: {}"
|
||||
no-candidate = "{} 未在提供的 blockStateClass {} 找到合适的构造方法"
|
||||
}
|
||||
entity {
|
||||
not-subclass = "{} 不是 {} 的子类"
|
||||
error = "{} 提供的 entityClass {} 无效: {}"
|
||||
}
|
||||
}
|
||||
|
||||
comments {
|
||||
|
|
Loading…
Reference in New Issue
Block a user