Wither Skeleton Summoning Remake (#99)

This commit is contained in:
koolkrafter5 authored and GitHub committed 2026-06-17 11:16:53 +02:00
1 parent 6c25bcee2a
commit c101bb2e6d
5 files changed
+169 -168

No files matched your search

@@ -118,7 +118,7 @@ public class NEINecromancyHandler extends InfusionRecipeHandler {
private void setResult(EnumMobAspect enumMobAspect) {
ItemStack result = new ItemStack(ThaumicTinkerer.registry.getFirstItemFromClass(ItemMobDisplay.class));
((ItemMobDisplay) result.getItem()).setEntityType(result, enumMobAspect.toString());
((ItemMobDisplay) result.getItem()).setEntityType(result, enumMobAspect);
this.result = new PositionedStack(result, OUTPUT_X, 39, false);
}
@@ -3,10 +3,10 @@ package thaumic.tinkerer.common.block.tile;
import java.util.ArrayList;
import java.util.Arrays;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import thaumcraft.api.aspects.Aspect;
@@ -19,121 +19,115 @@ public class TileSummon extends TileEntity {
@Override
public void updateEntity() {
if (worldObj.getTotalWorldTime() % 300 != 0
|| worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) {
return;
}
if (worldObj.getTotalWorldTime() % 300 == 0) {
if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) {
return;
}
for (int radius = 1; radius < 6; radius++) {
ArrayList<TileEntity> pedestals = new ArrayList<>();
for (int x = xCoord - radius; x <= xCoord + radius; x++) {
for (int z = zCoord - radius; z <= zCoord + radius; z++) {
TileEntity tile = worldObj.getTileEntity(x, yCoord, z);
if (tile instanceof TilePedestal && ((TilePedestal) tile).getStackInSlot(0) != null
&& ((TilePedestal) tile).getStackInSlot(0).getItem() instanceof ItemMobAspect) {
pedestals.add(tile);
}
for (int radius = 1; radius < 6; radius++) {
ArrayList<TilePedestal> pedestals = new ArrayList<>();
for (int x = xCoord - radius; x <= xCoord + radius; x++) {
for (int z = zCoord - radius; z <= zCoord + radius; z++) {
TileEntity tile = worldObj.getTileEntity(x, yCoord, z);
if (tile instanceof TilePedestal pedestal && pedestal.getStackInSlot(0) != null
&& pedestal.getStackInSlot(0).getItem() instanceof ItemMobAspect) {
pedestals.add(pedestal);
}
}
}
for (int i = 0; i < pedestals.size(); i++) {
for (int j = 0; j < pedestals.size(); j++) {
for (TileEntity pedestal : pedestals) {
TilePedestal ped1 = (TilePedestal) pedestals.get(i);
TilePedestal ped2 = (TilePedestal) pedestals.get(j);
TilePedestal ped3 = (TilePedestal) pedestal;
for (int i = 0; i < pedestals.size(); i++) {
for (int j = 0; j < pedestals.size(); j++) {
for (TilePedestal ped3 : pedestals) {
TilePedestal ped1 = pedestals.get(i);
TilePedestal ped2 = pedestals.get(j);
if ((ped1 != ped2) && (ped2 != ped3) && (ped1 != ped3)) {
ArrayList<Aspect> aspects = new ArrayList<>();
aspects.add(ItemMobAspect.getAspect(ped1.getStackInSlot(0)));
if ((ped1 == ped2) || (ped2 == ped3) || (ped1 == ped3)) continue;
ArrayList<Aspect> aspects = new ArrayList<>();
aspects.add(ItemMobAspect.getAspect(ped1.getStackInSlot(0)));
aspects.add(ItemMobAspect.getAspect(ped2.getStackInSlot(0)));
aspects.add(ItemMobAspect.getAspect(ped2.getStackInSlot(0)));
aspects.add(ItemMobAspect.getAspect(ped3.getStackInSlot(0)));
aspects.add(ItemMobAspect.getAspect(ped3.getStackInSlot(0)));
for (EnumMobAspect recipe : EnumMobAspect.values()) {
if (Arrays.asList(recipe.aspects).containsAll(aspects)
&& aspects.containsAll(Arrays.asList(recipe.aspects))) {
for (EnumMobAspect recipe : EnumMobAspect.values()) {
if (!Arrays.asList(recipe.aspects).containsAll(aspects)
|| !aspects.containsAll(Arrays.asList(recipe.aspects))) {
continue;
}
boolean isInfused = ItemMobAspect.isInfused(ped1.getStackInSlot(0))
&& ItemMobAspect.isInfused(ped2.getStackInSlot(0))
&& ItemMobAspect.isInfused(ped3.getStackInSlot(0));
boolean isInfused = ItemMobAspect.isInfused(ped1.getStackInSlot(0))
&& ItemMobAspect.isInfused(ped2.getStackInSlot(0))
&& ItemMobAspect.isInfused(ped3.getStackInSlot(0));
if (isInfused && worldObj.getTotalWorldTime() % 1200 != 0) {
return;
}
if (isInfused && worldObj.getTotalWorldTime() % 1200 != 0) return;
if (!isInfused) {
ped1.setInventorySlotContents(0, null);
ped2.setInventorySlotContents(0, null);
ped3.setInventorySlotContents(0, null);
}
if (!isInfused) {
ped1.setInventorySlotContents(0, null);
ped2.setInventorySlotContents(0, null);
ped3.setInventorySlotContents(0, null);
}
if (!isInfused || ItemMobAspect
.lastUsedTabletMatches(ped1.getStackInSlot(0), this)
&& ItemMobAspect.lastUsedTabletMatches(ped2.getStackInSlot(0), this)
&& ItemMobAspect.lastUsedTabletMatches(ped3.getStackInSlot(0), this)) {
if (!isInfused || ItemMobAspect.lastUsedTabletMatches(ped1.getStackInSlot(0), this)
&& ItemMobAspect.lastUsedTabletMatches(ped2.getStackInSlot(0), this)
&& ItemMobAspect.lastUsedTabletMatches(ped3.getStackInSlot(0), this)) {
if (!worldObj.isRemote) {
Entity spawn = EntityList
.createEntityByName(recipe.toString(), worldObj);
spawn.setLocationAndAngles(xCoord + .5, yCoord + 1, zCoord + .5, 0, 0);
if (spawn instanceof EntitySkeleton && worldObj.provider.isHellWorld) {
((EntitySkeleton) spawn).setSkeletonType(1);
}
worldObj.spawnEntityInWorld(spawn);
((EntityLiving) spawn).onSpawnWithEgg(null);
((EntityLiving) spawn).playLivingSound();
}
if (worldObj.isRemote) {
ThaumicTinkerer.tcProxy.essentiaTrailFx(
worldObj,
ped1.xCoord,
ped1.yCoord,
ped1.zCoord,
xCoord,
yCoord,
zCoord,
20,
aspects.get(0).getColor(),
20);
ThaumicTinkerer.tcProxy.essentiaTrailFx(
worldObj,
ped2.xCoord,
ped2.yCoord,
ped2.zCoord,
xCoord,
yCoord,
zCoord,
20,
aspects.get(1).getColor(),
20);
ThaumicTinkerer.tcProxy.essentiaTrailFx(
worldObj,
ped3.xCoord,
ped3.yCoord,
ped3.zCoord,
xCoord,
yCoord,
zCoord,
20,
aspects.get(2).getColor(),
20);
}
}
if (isInfused) {
ItemMobAspect.markLastUsedTablet(ped1.getStackInSlot(0), this);
ItemMobAspect.markLastUsedTablet(ped2.getStackInSlot(0), this);
ItemMobAspect.markLastUsedTablet(ped3.getStackInSlot(0), this);
}
return;
if (!worldObj.isRemote) {
EntityLiving spawn = recipe.createEntity(worldObj);
spawn.setLocationAndAngles(xCoord + .5, yCoord + 1, zCoord + .5, 0, 0);
worldObj.spawnEntityInWorld(spawn);
spawn.onSpawnWithEgg(null);
if (spawn instanceof EntitySkeleton skeleton && skeleton.getSkeletonType() == 1) {
// Needs to be done here instead of EnumMobAspect::setWither because
// EntitySkeleton::onSpawnWithEgg sets the held item to a bow
skeleton.setCurrentItemOrArmor(0, new ItemStack(Items.stone_sword));
}
spawn.playLivingSound();
}
if (worldObj.isRemote) {
ThaumicTinkerer.tcProxy.essentiaTrailFx(
worldObj,
ped1.xCoord,
ped1.yCoord,
ped1.zCoord,
xCoord,
yCoord,
zCoord,
20,
aspects.get(0).getColor(),
20);
ThaumicTinkerer.tcProxy.essentiaTrailFx(
worldObj,
ped2.xCoord,
ped2.yCoord,
ped2.zCoord,
xCoord,
yCoord,
zCoord,
20,
aspects.get(1).getColor(),
20);
ThaumicTinkerer.tcProxy.essentiaTrailFx(
worldObj,
ped3.xCoord,
ped3.yCoord,
ped3.zCoord,
xCoord,
yCoord,
zCoord,
20,
aspects.get(2).getColor(),
20);
}
}
if (isInfused) {
ItemMobAspect.markLastUsedTablet(ped1.getStackInSlot(0), this);
ItemMobAspect.markLastUsedTablet(ped2.getStackInSlot(0), this);
ItemMobAspect.markLastUsedTablet(ped3.getStackInSlot(0), this);
}
return;
}
}
}
@@ -3,11 +3,14 @@ package thaumic.tinkerer.common.core.helper;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.monster.EntityBlaze;
import net.minecraft.entity.monster.EntityCaveSpider;
import net.minecraft.entity.monster.EntityCreeper;
@@ -72,17 +75,40 @@ public enum EnumMobAspect {
LavaSlime(EntityMagmaCube.class, new Aspect[] { Aspect.FIRE, Aspect.SLIME, Aspect.SLIME }, 1.5f) {
@Override
protected Entity createEntity(World worldObj) {
public EntityLiving createEntity(World worldObj) {
return setSlimeSize(super.createEntity(worldObj), 1);
}
},
Ghast(EntityGhast.class, new Aspect[] { Aspect.FIRE, Aspect.FLIGHT, Aspect.FLIGHT }, 0.2f, 0.6f),
Firebat(EntityFireBat.class, new Aspect[] { Aspect.FLIGHT, Aspect.FIRE, Aspect.MAGIC }, 1.9f, 0f, "Thaumcraft."),
Firebat(EntityFireBat.class, new Aspect[] { Aspect.FLIGHT, Aspect.FIRE, Aspect.MAGIC }, 1.9f, 0f),
/// Must be before Zombie because EntityBrainyZombie extends EntityZombie
BrainyZombie(EntityBrainyZombie.class, new Aspect[] { Aspect.MAGIC, Aspect.UNDEAD, Aspect.FLESH }, 0.8f, 0,
"Thaumcraft."),
BrainyZombie(EntityBrainyZombie.class, new Aspect[] { Aspect.MAGIC, Aspect.UNDEAD, Aspect.FLESH }, 0.8f, 0),
Zombie(EntityZombie.class, new Aspect[] { Aspect.FLESH, Aspect.FLESH, Aspect.UNDEAD }, 0.8f),
Skeleton(EntitySkeleton.class, new Aspect[] { Aspect.UNDEAD, Aspect.MAN, Aspect.UNDEAD }, 0.8f),
Skeleton(EntitySkeleton.class, new Aspect[] { Aspect.UNDEAD, Aspect.MAN, Aspect.UNDEAD }, 0.8f) {
@Override
public boolean matches(EntityLiving e) {
if (e instanceof EntitySkeleton skeleton) {
return skeleton.getSkeletonType() == 0;
}
return false;
}
},
WitherSkeleton(EntitySkeleton.class, new Aspect[] { Aspect.UNDEAD, Aspect.POISON, Aspect.FIRE }, 0.8f) {
@Override
public EntityLiving createEntity(World worldObj) {
return setWither(super.createEntity(worldObj));
}
@Override
public boolean matches(EntityLiving e) {
if (e instanceof EntitySkeleton skeleton) {
return skeleton.getSkeletonType() == 1;
}
return false;
}
},
Creeper(EntityCreeper.class, new Aspect[] { Aspect.MAGIC, Aspect.BEAST, Aspect.ELDRITCH }, 0.8f),
Witch(EntityWitch.class, new Aspect[] { Aspect.MAGIC, Aspect.UNDEAD, Aspect.ELDRITCH }, 0.8f),
/// Must be before Spider because EntityCaveSpider extends EntitySpider
@@ -91,36 +117,32 @@ public enum EnumMobAspect {
Slime(EntitySlime.class, new Aspect[] { Aspect.SLIME, Aspect.SLIME, Aspect.BEAST }, 1.5f) {
@Override
protected Entity createEntity(World worldObj) {
public EntityLiving createEntity(World worldObj) {
return setSlimeSize(super.createEntity(worldObj), 1);
}
},
Silverfish(EntitySilverfish.class, new Aspect[] { Aspect.METAL, Aspect.METAL, Aspect.EARTH }, 1.2f),
Enderman(EntityEnderman.class, new Aspect[] { Aspect.ELDRITCH, Aspect.ELDRITCH, Aspect.MAN }, 0.7f),
Wisp(EntityWisp.class, new Aspect[] { Aspect.AIR, Aspect.MAGIC, Aspect.MAGIC }, "Thaumcraft.");
Wisp(EntityWisp.class, new Aspect[] { Aspect.AIR, Aspect.MAGIC, Aspect.MAGIC });
public static final Map<EnumMobAspect, Entity> entityCache = Maps.newHashMap();
public static final Map<EnumMobAspect, EntityLiving> entityCache = Maps.newHashMap();
private static final Map<String, EnumMobAspect> LOOKUP = Arrays.stream(values())
.collect(Collectors.toMap(Enum::name, Function.identity()));
public final Aspect[] aspects;
public final Class<? extends Entity> entity;
public final String prefix;
public final Class<? extends EntityLiving> entity;
private final float scale;
private final float offset;
private final MethodHandle ctor;
EnumMobAspect(Class<? extends Entity> entity, Aspect[] aspects, float scale, float offset) {
this(entity, aspects, scale, offset, "");
}
EnumMobAspect(Class<? extends Entity> entity, Aspect[] aspects, float scale) {
EnumMobAspect(Class<? extends EntityLiving> entity, Aspect[] aspects, float scale) {
this(entity, aspects, scale, 0);
}
EnumMobAspect(Class<? extends Entity> entity, Aspect[] aspects, float scale, float offset, String prefix) {
EnumMobAspect(Class<? extends EntityLiving> entity, Aspect[] aspects, float scale, float offset) {
this.aspects = aspects;
this.entity = entity;
this.scale = scale;
this.offset = offset;
this.prefix = prefix;
MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
this.ctor = lookup.findConstructor(entity, MethodType.methodType(void.class, World.class));
@@ -129,16 +151,16 @@ public enum EnumMobAspect {
}
}
EnumMobAspect(Class<? extends Entity> entity, Aspect[] aspects) {
EnumMobAspect(Class<? extends EntityLiving> entity, Aspect[] aspects) {
this(entity, aspects, 1.0f);
}
EnumMobAspect(Class<? extends Entity> entity, Aspect[] aspects, String prefix) {
this(entity, aspects, 1.0f, 0, prefix);
public static EnumMobAspect get(String name) {
return LOOKUP.get(name);
}
public static Entity getEntityFromCache(EnumMobAspect ent, World worldObj) {
Entity entity = entityCache.get(ent);
public static EntityLiving getEntityFromCache(EnumMobAspect ent, World worldObj) {
EntityLiving entity = entityCache.get(ent);
if (entity == null) {
entity = ent.createEntity(worldObj);
entityCache.put(ent, entity);
@@ -146,37 +168,34 @@ public enum EnumMobAspect {
return entity;
}
private static Entity setSlimeSize(Entity entity, int size) {
if (entity instanceof EntitySlime) {
((EntitySlime) entity).setSlimeSize(size);
private static EntityLiving setSlimeSize(EntityLiving entity, int size) {
if (entity instanceof EntitySlime slime) {
slime.setSlimeSize(size);
}
return entity;
}
public static Aspect[] getAspectsForEntity(Entity e) {
return getAspectsForEntity(e.getClass());
private static EntityLiving setWither(EntityLiving entity) {
if (entity instanceof EntitySkeleton skeleton) {
skeleton.setSkeletonType(1);
skeleton.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(4.0D);
}
return entity;
}
public static EnumMobAspect getMobAspectForType(String name) {
if (name.isEmpty()) return null;
Class<? extends Entity> clazz = EntityList.stringToClassMapping.get(name);
for (EnumMobAspect e : EnumMobAspect.values()) {
if (e.entity.isAssignableFrom(clazz)) {
return e;
public static Aspect[] getAspectsForEntity(EntityLiving e) {
for (EnumMobAspect aspect : EnumMobAspect.values()) {
if (aspect.matches(e)) {
return aspect.aspects;
}
}
return null;
}
public static Aspect[] getAspectsForEntity(Class<? extends Entity> clazz) {
for (EnumMobAspect e : EnumMobAspect.values()) {
if (e.entity.isAssignableFrom(clazz)) {
return e.aspects;
}
}
return null;
public boolean matches(EntityLiving e) {
return this.entity.isInstance(e);
}
public float getVerticalOffset() {
@@ -187,27 +206,18 @@ public enum EnumMobAspect {
return scale;
}
public Class<? extends Entity> getEntityClass() {
return entity;
}
public Entity getEntity(World worldObj) {
public EntityLiving getEntity(World worldObj) {
return getEntityFromCache(this, worldObj);
}
protected Entity createEntity(World worldObj) {
public EntityLiving createEntity(World worldObj) {
try {
return (Entity) ctor.invoke(worldObj);
return (EntityLiving) ctor.invoke(worldObj);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return prefix == null ? super.toString() : prefix + super.toString();
}
static {
MinecraftForge.EVENT_BUS.register(new EventHandler());
}
@@ -13,6 +13,7 @@ package thaumic.tinkerer.common.item;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier;
@@ -183,7 +184,7 @@ public class ItemBloodSword extends ItemSword implements IRepairable, ITTinkerer
@SubscribeEvent
public void onDrops(LivingDropsEvent event) {
if (!event.source.damageType.equals("player")) {
if (!event.source.damageType.equals("player") || !(event.entity instanceof EntityLiving entity)) {
return;
}
EntityPlayer player = (EntityPlayer) event.source.getEntity();
@@ -193,7 +194,7 @@ public class ItemBloodSword extends ItemSword implements IRepairable, ITTinkerer
|| stack.stackTagCompound.getInteger("Activated") != 1) {
return;
}
Aspect[] aspects = EnumMobAspect.getAspectsForEntity(event.entity);
Aspect[] aspects = EnumMobAspect.getAspectsForEntity(entity);
if (aspects != null) {
event.drops.clear();
for (Aspect a : aspects) {
@@ -3,8 +3,6 @@ package thaumic.tinkerer.common.item;
import java.util.List;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -39,20 +37,18 @@ public class ItemMobDisplay extends ItemBase {
}
public EnumMobAspect getEntityType(ItemStack stack) {
return EnumMobAspect.getMobAspectForType(ItemNBTHelper.getString(stack, TAG_TYPE, ""));
return EnumMobAspect.get(ItemNBTHelper.getString(stack, TAG_TYPE, ""));
}
public void setEntityType(ItemStack stack, String type) {
ItemNBTHelper.setString(stack, TAG_TYPE, type);
public void setEntityType(ItemStack stack, EnumMobAspect type) {
ItemNBTHelper.setString(stack, TAG_TYPE, type.name());
}
@Override
public void getSubItems(Item par1Item, CreativeTabs par2CreativeTabs, List<ItemStack> list) {
for (EnumMobAspect aspect : EnumMobAspect.values()) {
Class<? extends Entity> aspClass = aspect.getEntityClass();
String name = EntityList.classToStringMapping.get(aspClass);
ItemStack item = new ItemStack(this);
this.setEntityType(item, name);
this.setEntityType(item, aspect);
list.add(item);
}
}
@@ -66,7 +62,7 @@ public class ItemMobDisplay extends ItemBase {
public String getItemStackDisplayName(ItemStack stack) {
String mob = ItemNBTHelper.getString(stack, TAG_TYPE, "");
if (mob == null || mob.isEmpty()) return super.getItemStackDisplayName(stack);
EnumMobAspect aspect = EnumMobAspect.getMobAspectForType(mob);
EnumMobAspect aspect = EnumMobAspect.get(mob);
if (aspect == null) return super.getItemStackDisplayName(stack);
return ThaumicTinkerer.proxy.getMobDisplayName(aspect);
}