diff --git a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java index f56667f..d368602 100644 --- a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java +++ b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java @@ -10,6 +10,7 @@ import fathertoast.specialmobs.common.config.Config; import fathertoast.specialmobs.common.core.SpecialMobs; import fathertoast.specialmobs.common.core.register.SMEntities; import fathertoast.specialmobs.common.entity.creeper.EnderCreeperEntity; +import fathertoast.specialmobs.common.entity.enderman.RunicEndermanEntity; import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity; import fathertoast.specialmobs.common.entity.silverfish.PufferSilverfishEntity; import fathertoast.specialmobs.common.entity.skeleton.NinjaSkeletonEntity; @@ -82,11 +83,13 @@ public class ClientRegister { registerSpeciesRenderer( PufferSilverfishEntity.SPECIES, ShortSilverfishRenderer::new ); registerSpeciesRenderer( CorporealShiftGhastEntity.SPECIES, CorporealShiftGhastRenderer::new ); + + registerSpeciesRenderer( RunicEndermanEntity.SPECIES, RunicEndermanRenderer::new ); // Other registerRenderer( SMEntities.BONE_SHRAPNEL, BoneShrapnelRenderer::new ); registerRenderer( SMEntities.BUG_SPIT, BugSpitRenderer::new ); - registerSpriteRenderer( SMEntities.CORPOREAL_FIREBALL, game, 3.0F, true ); + registerSpriteRenderer( SMEntities.INCORPOREAL_FIREBALL, game, 3.0F, true ); registerRenderer( SMEntities.FISHING_BOBBER, SpecialFishingBobberRenderer::new ); } diff --git a/src/main/java/fathertoast/specialmobs/client/renderer/entity/species/RunicEndermanModel.java b/src/main/java/fathertoast/specialmobs/client/renderer/entity/species/RunicEndermanModel.java new file mode 100644 index 0000000..9221e33 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/client/renderer/entity/species/RunicEndermanModel.java @@ -0,0 +1,118 @@ +package fathertoast.specialmobs.client.renderer.entity.species; + +import fathertoast.specialmobs.common.entity.enderman.RunicEndermanEntity; +import net.minecraft.client.renderer.entity.model.BipedModel; +import net.minecraft.client.renderer.model.ModelRenderer; + +/** Epic copy-paste of {@link net.minecraft.client.renderer.entity.model.EndermanModel} */ +public class RunicEndermanModel extends BipedModel { + + public boolean carrying; + public boolean creepy; + + public RunicEndermanModel(float something) { + super(0.0F, -14.0F, 64, 32); + float f = -14.0F; + this.hat = new ModelRenderer(this, 0, 16); + this.hat.addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, something - 0.5F); + this.hat.setPos(0.0F, -14.0F, 0.0F); + this.body = new ModelRenderer(this, 32, 16); + this.body.addBox(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, something); + this.body.setPos(0.0F, -14.0F, 0.0F); + this.rightArm = new ModelRenderer(this, 56, 0); + this.rightArm.addBox(-1.0F, -2.0F, -1.0F, 2.0F, 30.0F, 2.0F, something); + this.rightArm.setPos(-3.0F, -12.0F, 0.0F); + this.leftArm = new ModelRenderer(this, 56, 0); + this.leftArm.mirror = true; + this.leftArm.addBox(-1.0F, -2.0F, -1.0F, 2.0F, 30.0F, 2.0F, something); + this.leftArm.setPos(5.0F, -12.0F, 0.0F); + this.rightLeg = new ModelRenderer(this, 56, 0); + this.rightLeg.addBox(-1.0F, 0.0F, -1.0F, 2.0F, 30.0F, 2.0F, something); + this.rightLeg.setPos(-2.0F, -2.0F, 0.0F); + this.leftLeg = new ModelRenderer(this, 56, 0); + this.leftLeg.mirror = true; + this.leftLeg.addBox(-1.0F, 0.0F, -1.0F, 2.0F, 30.0F, 2.0F, something); + this.leftLeg.setPos(2.0F, -2.0F, 0.0F); + } + @Override + public void setupAnim(T enderman, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + super.setupAnim(enderman, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + + this.head.visible = true; + this.body.xRot = 0.0F; + this.body.y = -14.0F; + this.body.z = -0.0F; + this.rightLeg.xRot -= 0.0F; + this.leftLeg.xRot -= 0.0F; + this.rightArm.xRot = (float)((double)this.rightArm.xRot * 0.5D); + this.leftArm.xRot = (float)((double)this.leftArm.xRot * 0.5D); + this.rightLeg.xRot = (float)((double)this.rightLeg.xRot * 0.5D); + this.leftLeg.xRot = (float)((double)this.leftLeg.xRot * 0.5D); + + if (this.rightArm.xRot > 0.4F) { + this.rightArm.xRot = 0.4F; + } + + if (this.leftArm.xRot > 0.4F) { + this.leftArm.xRot = 0.4F; + } + + if (this.rightArm.xRot < -0.4F) { + this.rightArm.xRot = -0.4F; + } + + if (this.leftArm.xRot < -0.4F) { + this.leftArm.xRot = -0.4F; + } + + if (this.rightLeg.xRot > 0.4F) { + this.rightLeg.xRot = 0.4F; + } + + if (this.leftLeg.xRot > 0.4F) { + this.leftLeg.xRot = 0.4F; + } + + if (this.rightLeg.xRot < -0.4F) { + this.rightLeg.xRot = -0.4F; + } + + if (this.leftLeg.xRot < -0.4F) { + this.leftLeg.xRot = -0.4F; + } + + if (this.carrying) { + this.rightArm.xRot = -0.5F; + this.leftArm.xRot = -0.5F; + this.rightArm.zRot = 0.05F; + this.leftArm.zRot = -0.05F; + } + this.rightArm.z = 0.0F; + this.leftArm.z = 0.0F; + this.rightLeg.z = 0.0F; + this.leftLeg.z = 0.0F; + this.rightLeg.y = -5.0F; + this.leftLeg.y = -5.0F; + this.head.z = -0.0F; + this.head.y = -13.0F; + this.hat.x = this.head.x; + this.hat.y = this.head.y; + this.hat.z = this.head.z; + this.hat.xRot = this.head.xRot; + this.hat.yRot = this.head.yRot; + this.hat.zRot = this.head.zRot; + + if (this.creepy) { + this.head.y -= 5.0F; + } + this.rightArm.setPos(-5.0F, -12.0F, 0.0F); + this.leftArm.setPos(5.0F, -12.0F, 0.0F); + + if (enderman.getBeamTargetId().isPresent()) { + leftArm.xRot = -0.5F; + rightArm.xRot = -0.5F; + leftArm.zRot = -0.25F; + rightArm.zRot = 0.25F; + } + } +} diff --git a/src/main/java/fathertoast/specialmobs/client/renderer/entity/species/RunicEndermanRenderer.java b/src/main/java/fathertoast/specialmobs/client/renderer/entity/species/RunicEndermanRenderer.java new file mode 100644 index 0000000..a1539dc --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/client/renderer/entity/species/RunicEndermanRenderer.java @@ -0,0 +1,108 @@ +package fathertoast.specialmobs.client.renderer.entity.species; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobEyesLayer; +import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobOverlayLayer; +import fathertoast.specialmobs.common.entity.ISpecialMob; +import fathertoast.specialmobs.common.entity.enderman.RunicEndermanEntity; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EnderDragonRenderer; +import net.minecraft.client.renderer.entity.EntityRendererManager; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Matrix3f; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3f; + +public class RunicEndermanRenderer extends MobRenderer> { + + public static final ResourceLocation CRYSTAL_BEAM_LOCATION = new ResourceLocation("textures/entity/end_crystal/end_crystal_beam.png"); + private static final RenderType BEAM = RenderType.entitySmoothCutout(CRYSTAL_BEAM_LOCATION); + + private final float baseShadowRadius; + + + public RunicEndermanRenderer(EntityRendererManager rendererManager) { + super(rendererManager, new RunicEndermanModel<>(0.0F), 0.5F); + + baseShadowRadius = shadowRadius; + addLayer( new SpecialMobEyesLayer<>( this ) ); + addLayer( new SpecialMobOverlayLayer<>( this, new RunicEndermanModel<>( 0.25F ) ) ); + } + + @Override + public void render(RunicEndermanEntity enderman, float rotation, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight) { + if (enderman.getBeamTargetId().isPresent()) { + Entity entity = enderman.level.getEntity(enderman.getBeamTargetId().getAsInt()); + + if (entity != null) { + matrixStack.pushPose(); + float x = (float)(entity.getX() - MathHelper.lerp(partialTicks, enderman.xo, enderman.getX())); + float y = (float)(entity.getY() - MathHelper.lerp(partialTicks, enderman.yo, enderman.getY())); + float z = (float)(entity.getZ() - MathHelper.lerp(partialTicks, enderman.zo, enderman.getZ())); + renderBeamAttack(x, y, z, partialTicks, enderman.tickCount, matrixStack, buffer, packedLight); + matrixStack.popPose(); + } + } + + super.render(enderman, rotation, partialTicks, matrixStack, buffer, packedLight); + } + + @Override + public ResourceLocation getTextureLocation(RunicEndermanEntity enderman) { + return ((ISpecialMob) enderman).getSpecialData().getTexture(); + } + + @Override + protected void scale(RunicEndermanEntity entity, MatrixStack matrixStack, float partialTick ) { + super.scale( entity, matrixStack, partialTick ); + + final float scale = ((ISpecialMob) entity).getSpecialData().getRenderScale(); + shadowRadius = baseShadowRadius * scale; + matrixStack.scale( scale, scale, scale ); + } + + /** Copy-paste Ender Crystal render code. {@link EnderDragonRenderer#renderCrystalBeams(float, float, float, float, int, MatrixStack, IRenderTypeBuffer, int)} */ + private void renderBeamAttack(float x, float y, float z, float partialTicks, int tickCount, MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight) { + float f = MathHelper.sqrt(x * x + z * z); + float xyzMul = x * x + y * y + z * z; + float f1 = MathHelper.sqrt(xyzMul); + + matrixStack.pushPose(); + matrixStack.translate(0.0D, 2.0D, 0.0D); + matrixStack.mulPose(Vector3f.YP.rotation((float)(-Math.atan2(z, x)) - ((float)Math.PI / 2F))); + matrixStack.mulPose(Vector3f.XP.rotation((float)(-Math.atan2(f, y)) - ((float)Math.PI / 2F))); + + IVertexBuilder ivertexbuilder = buffer.getBuffer(BEAM); + + float f2 = 0.0F - ((float)tickCount + partialTicks) * 0.01F; + float f3 = MathHelper.sqrt(xyzMul) / 32.0F - ((float)tickCount + partialTicks) * 0.01F; + float f4 = 0.0F; + float f5 = 0.75F; + float f6 = 0.0F; + + MatrixStack.Entry entry = matrixStack.last(); + Matrix4f matrix4f = entry.pose(); + Matrix3f matrix3f = entry.normal(); + + for(int j = 1; j <= 8; ++j) { + float f7 = MathHelper.sin((float)j * ((float)Math.PI * 2F) / 8.0F) * 0.75F; + float f8 = MathHelper.cos((float)j * ((float)Math.PI * 2F) / 8.0F) * 0.75F; + float f9 = (float)j / 8.0F; + + ivertexbuilder.vertex(matrix4f, f4 * 0.2F, f5 * 0.2F, 0.0F).color(0, 0, 0, 255).uv(f6, f2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(packedLight).normal(matrix3f, 0.0F, -1.0F, 0.0F).endVertex(); + ivertexbuilder.vertex(matrix4f, f4, f5, f1).color(255, 100, 255, 255).uv(f6, f3).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(packedLight).normal(matrix3f, 0.0F, -1.0F, 0.0F).endVertex(); + ivertexbuilder.vertex(matrix4f, f7, f8, f1).color(255, 100, 255, 255).uv(f9, f3).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(packedLight).normal(matrix3f, 0.0F, -1.0F, 0.0F).endVertex(); + ivertexbuilder.vertex(matrix4f, f7 * 0.2F, f8 * 0.2F, 0.0F).color(0, 0, 0, 255).uv(f9, f2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(packedLight).normal(matrix3f, 0.0F, -1.0F, 0.0F).endVertex(); + f4 = f7; + f5 = f8; + f6 = f9; + } + matrixStack.popPose(); + } +} diff --git a/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java b/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java index 2a34d7f..1991c9a 100644 --- a/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java +++ b/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java @@ -29,7 +29,7 @@ public class SMEntities { EntityType.Builder.of( BugSpitEntity::new, EntityClassification.MISC ) .sized( 0.25F, 0.25F ).clientTrackingRange( 4 ).updateInterval( 10 ) ); - public static final RegistryObject> CORPOREAL_FIREBALL = register( "incorporeal_fireball", + public static final RegistryObject> INCORPOREAL_FIREBALL = register( "incorporeal_fireball", EntityType.Builder.of( IncorporealFireballEntity::new, EntityClassification.MISC ) .sized( 1.0F, 1.0F ).clientTrackingRange( 4 ).updateInterval( 3 ) ); diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/RunicAttackGoal.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/RunicAttackGoal.java deleted file mode 100644 index 5b61b85..0000000 --- a/src/main/java/fathertoast/specialmobs/common/entity/ai/RunicAttackGoal.java +++ /dev/null @@ -1,22 +0,0 @@ -package fathertoast.specialmobs.common.entity.ai; - -import fathertoast.specialmobs.common.entity.enderman.RunicEndermanEntity; -import net.minecraft.entity.ai.goal.Goal; - -public class RunicAttackGoal extends Goal { - - private final RunicEndermanEntity runicEnderman; - private final int attackTime; - private final float baseDamage; - - public RunicAttackGoal( RunicEndermanEntity runicEnderman, int attackTime, float baseDamage ) { - this.runicEnderman = runicEnderman; - this.attackTime = attackTime; - this.baseDamage = baseDamage; - } - - @Override - public boolean canUse() { - return false; - } -} diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/RunicEndermanBeamAttackGoal.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/RunicEndermanBeamAttackGoal.java new file mode 100644 index 0000000..cc39393 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/RunicEndermanBeamAttackGoal.java @@ -0,0 +1,68 @@ +package fathertoast.specialmobs.common.entity.ai.goal; + +import fathertoast.specialmobs.common.entity.enderman.RunicEndermanEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.goal.Goal; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.MathHelper; + +public class RunicEndermanBeamAttackGoal extends Goal { + + private final RunicEndermanEntity runicEnderman; + private final int maxAttackTime; + private final double baseDamage; + + private int attackTime; + + public RunicEndermanBeamAttackGoal(RunicEndermanEntity runicEnderman, int maxAttackTime, double baseDamage ) { + this.runicEnderman = runicEnderman; + this.maxAttackTime = maxAttackTime; + this.baseDamage = baseDamage; + } + + @Override + public boolean canUse() { + if (runicEnderman.isVehicle()) + return false; + + LivingEntity target = runicEnderman.getTarget(); + + return target != null + && target.isAlive() + && runicEnderman.getSensing().canSee(target) + && (runicEnderman.tickCount % 8 == 0 && runicEnderman.getRandom().nextInt(10) == 0); + } + + @Override + public boolean canContinueToUse() { + LivingEntity target = runicEnderman.getTarget(); + + return attackTime > 0 && target != null && target.isAlive() && runicEnderman.getSensing().canSee(target); + } + + @Override + public void start() { + runicEnderman.setBeamTargetId(runicEnderman.getTarget().getId()); + attackTime = maxAttackTime; + } + + @Override + public void stop() { + runicEnderman.clearBeamTargetId(); + attackTime = 0; + } + + @SuppressWarnings("ConstantConditions") + @Override + public void tick() { + --attackTime; + + if (attackTime <= 0) { + LivingEntity target = runicEnderman.getTarget(); + double xRatio = MathHelper.sin(runicEnderman.yRot * ((float)Math.PI / 180F)); + double zRatio = -MathHelper.cos(runicEnderman.yRot * ((float)Math.PI / 180F)); + target.knockback(5, xRatio, zRatio); + target.hurt(DamageSource.mobAttack(runicEnderman), (float) baseDamage); + } + } +} diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/RunicEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/RunicEndermanEntity.java index ce394a7..83c2220 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/RunicEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/RunicEndermanEntity.java @@ -4,6 +4,7 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; +import fathertoast.specialmobs.common.entity.ai.goal.RunicEndermanBeamAttackGoal; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import net.minecraft.block.Blocks; @@ -11,9 +12,14 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.Effects; import net.minecraft.world.World; +import java.util.OptionalInt; + @SpecialMob public class RunicEndermanEntity extends _SpecialEndermanEntity { @@ -56,9 +62,31 @@ public class RunicEndermanEntity extends _SpecialEndermanEntity { //--------------- Variant-Specific Implementations ---------------- - + + public static final DataParameter BEAMING = EntityDataManager.defineId(RunicEndermanEntity.class, DataSerializers.BOOLEAN); + public static final DataParameter TARGET_ID = EntityDataManager.defineId(RunicEndermanEntity.class, DataSerializers.OPTIONAL_UNSIGNED_INT); + public RunicEndermanEntity( EntityType entityType, World world ) { super( entityType, world ); } - + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + entityData.define( BEAMING, false ); + entityData.define( TARGET_ID, OptionalInt.empty() ); + } + + public OptionalInt getBeamTargetId() { + return entityData.get( TARGET_ID ); + } + + public void setBeamTargetId(int targetId) { + entityData.set( TARGET_ID, OptionalInt.of(targetId) ); + } + + public void clearBeamTargetId() { + entityData.set( TARGET_ID, OptionalInt.empty() ); + } + /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( LivingEntity target ) { @@ -70,7 +98,6 @@ public class RunicEndermanEntity extends _SpecialEndermanEntity { @Override protected void registerVariantGoals() { super.registerVariantGoals(); + goalSelector.addGoal( 2, new RunicEndermanBeamAttackGoal(this, 50, 2.0D)); } - - // NOTE would be fun to try and make this mob shoot an 'end crystal laser' to deal ranged damage and/or knockback } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/projectile/IncorporealFireballEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/projectile/IncorporealFireballEntity.java index 4175588..cae32ef 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/projectile/IncorporealFireballEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/projectile/IncorporealFireballEntity.java @@ -1,10 +1,8 @@ package fathertoast.specialmobs.common.entity.projectile; -import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.core.register.SMEntities; import fathertoast.specialmobs.common.core.register.SMItems; import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity; -import fathertoast.specialmobs.common.util.References; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -42,21 +40,15 @@ public class IncorporealFireballEntity extends AbstractFireballEntity { } public IncorporealFireballEntity(World world, CorporealShiftGhastEntity ghast, double x, double y, double z ) { - super( SMEntities.CORPOREAL_FIREBALL.get(), ghast, x, y, z, world ); + super( SMEntities.INCORPOREAL_FIREBALL.get(), ghast, x, y, z, world ); target = ghast.getTarget(); } public IncorporealFireballEntity(World world, @Nullable PlayerEntity owner, LivingEntity target, double x, double y, double z ) { - super( SMEntities.CORPOREAL_FIREBALL.get(), owner, x, y, z, world ); + super( SMEntities.INCORPOREAL_FIREBALL.get(), owner, x, y, z, world ); this.target = target; } - - @SpecialMob.LanguageProvider - public static String[] getTranslations( String langKey ) { - return References.translations( langKey, "Incorporeal Fireball", - "", "", "", "", "", "" );//TODO - } - + @Override public void tick() { super.tick(); diff --git a/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java b/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java index 3e6ab25..f773ae7 100644 --- a/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java +++ b/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java @@ -66,7 +66,7 @@ public class SMLanguageProvider extends LanguageProvider { "", "", "", "", "", "" ) ); //TODO translationList.add( References.translations( SMEntities.BUG_SPIT.get().getDescriptionId(), "Bug Spit", "", "", "", "", "", "" ) ); //TODO - translationList.add( References.translations( SMEntities.CORPOREAL_FIREBALL.get().getDescriptionId(), "Bug Spit", + translationList.add( References.translations( SMEntities.INCORPOREAL_FIREBALL.get().getDescriptionId(), "Incorporeal Fireball", "", "", "", "", "", "" ) ); //TODO translationList.add( References.translations( SMEntities.FISHING_BOBBER.get().getDescriptionId(), "Fishing Bobber", "", "", "", "", "", "" ) ); //TODO