From 97bc8e217fabb99111997f13228c51a68b5b17f4 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 17 May 2013 17:18:08 +1000 Subject: [PATCH] Added the Glob, saved the spawning stuff for Forstride --- src/minecraft/biomesoplenty/ClientProxy.java | 7 +- .../configuration/BOPConfiguration.java | 2 + .../configuration/BOPEntities.java | 5 + .../biomesoplenty/mobs/EntityGlob.java | 346 ++++++++++++++++++ .../biomesoplenty/mobs/RenderGlob.java | 77 ++++ 5 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 src/minecraft/biomesoplenty/mobs/EntityGlob.java create mode 100644 src/minecraft/biomesoplenty/mobs/RenderGlob.java diff --git a/src/minecraft/biomesoplenty/ClientProxy.java b/src/minecraft/biomesoplenty/ClientProxy.java index 8168dfd58..c8025c585 100644 --- a/src/minecraft/biomesoplenty/ClientProxy.java +++ b/src/minecraft/biomesoplenty/ClientProxy.java @@ -1,10 +1,11 @@ package biomesoplenty; import net.minecraft.client.Minecraft; +import net.minecraft.client.model.ModelSlime; import net.minecraft.client.particle.EntityBreakingFX; import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.entity.RenderSlime; import net.minecraft.client.renderer.entity.RenderSnowball; -import net.minecraft.world.World; import biomesoplenty.api.Items; import biomesoplenty.blocks.renderers.FoliageRenderer; import biomesoplenty.blocks.renderers.PlantsRenderer; @@ -13,6 +14,8 @@ import biomesoplenty.items.projectiles.EntityMudball; import biomesoplenty.items.projectiles.EntityPoisonDart; import biomesoplenty.items.projectiles.RenderDart; import biomesoplenty.items.projectiles.RenderPoisonDart; +import biomesoplenty.mobs.EntityGlob; +import biomesoplenty.mobs.RenderGlob; import biomesoplenty.particles.EntityDandelionFX; import cpw.mods.fml.client.registry.RenderingRegistry; @@ -27,6 +30,8 @@ public class ClientProxy extends CommonProxy { RenderingRegistry.registerEntityRenderingHandler(EntityDart.class, new RenderDart()); RenderingRegistry.registerEntityRenderingHandler(EntityPoisonDart.class, new RenderPoisonDart()); + RenderingRegistry.registerEntityRenderingHandler(EntityGlob.class, new RenderGlob(new ModelSlime(16), new ModelSlime(0), 0.25F)); + RenderingRegistry.registerBlockHandler(new FoliageRenderer()); RenderingRegistry.registerBlockHandler(new PlantsRenderer()); } diff --git a/src/minecraft/biomesoplenty/configuration/BOPConfiguration.java b/src/minecraft/biomesoplenty/configuration/BOPConfiguration.java index 6707a7ed4..9ffb09a1c 100644 --- a/src/minecraft/biomesoplenty/configuration/BOPConfiguration.java +++ b/src/minecraft/biomesoplenty/configuration/BOPConfiguration.java @@ -322,6 +322,7 @@ public class BOPConfiguration { public static int jungleSpiderID; public static int rosesterID; + public static int globID; // Village biomes public static boolean alpsVillage; @@ -708,6 +709,7 @@ public class BOPConfiguration { //Mob IDs jungleSpiderID = config.get("Mob IDs", "Jungle Spider ID", 101, null).getInt(); rosesterID = config.get("Mob IDs", "Rosester ID", 102, null).getInt(); + globID = config.get("Mob IDs", "Glob ID", 106, null).getInt(); //Projectile IDs entityMudballID = config.get("Entity IDs", "Mudball ID", 103, null).getInt();; diff --git a/src/minecraft/biomesoplenty/configuration/BOPEntities.java b/src/minecraft/biomesoplenty/configuration/BOPEntities.java index 08e5f13ca..cc1ade70c 100644 --- a/src/minecraft/biomesoplenty/configuration/BOPEntities.java +++ b/src/minecraft/biomesoplenty/configuration/BOPEntities.java @@ -8,6 +8,7 @@ import biomesoplenty.api.Entities; import biomesoplenty.items.projectiles.EntityDart; import biomesoplenty.items.projectiles.EntityMudball; import biomesoplenty.items.projectiles.EntityPoisonDart; +import biomesoplenty.mobs.EntityGlob; import biomesoplenty.mobs.EntityJungleSpider; import biomesoplenty.mobs.EntityRosester; import cpw.mods.fml.common.registry.EntityRegistry; @@ -43,11 +44,14 @@ public class BOPEntities { EntityRegistry.registerModEntity(EntityMudball.class, "MudBall", BOPConfiguration.entityMudballID, BiomesOPlenty.instance, 80, 3, true); EntityRegistry.registerModEntity(EntityDart.class, "Dart", BOPConfiguration.entityDartID, BiomesOPlenty.instance, 80, 3, true); EntityRegistry.registerModEntity(EntityPoisonDart.class, "PoisonDart", BOPConfiguration.entityPoisonDartID, BiomesOPlenty.instance, 80, 3, true); + EntityRegistry.registerModEntity(EntityJungleSpider.class, "JungleSpider", BOPConfiguration.jungleSpiderID, BiomesOPlenty.instance, 80, 3, true); EntityRegistry.registerModEntity(EntityRosester.class, "Rosester", BOPConfiguration.rosesterID, BiomesOPlenty.instance, 80, 3, true); + EntityRegistry.registerModEntity(EntityGlob.class, "Glob", BOPConfiguration.globID, BiomesOPlenty.instance, 80, 3, true); registerEntityEgg(EntityJungleSpider.class, 5147192, 11013646); registerEntityEgg(EntityRosester.class, 14831439, 16756224); + registerEntityEgg(EntityGlob.class, 14831439, 16756224); if (Biomes.jungleNew.isPresent() && Biomes.tropicalRainforest.isPresent() && Biomes.oasis.isPresent() && Biomes.tropics.isPresent()) { @@ -61,5 +65,6 @@ public class BOPEntities { LanguageRegistry.instance().addStringLocalization("entity.BiomesOPlenty.JungleSpider.name", "en_US", "Jungle Spider"); LanguageRegistry.instance().addStringLocalization("entity.BiomesOPlenty.Rosester.name", "en_US", "Rosester"); + LanguageRegistry.instance().addStringLocalization("entity.BiomesOPlenty.Glob.name", "en_US", "Glob"); } } diff --git a/src/minecraft/biomesoplenty/mobs/EntityGlob.java b/src/minecraft/biomesoplenty/mobs/EntityGlob.java new file mode 100644 index 000000000..d1c3a9fe2 --- /dev/null +++ b/src/minecraft/biomesoplenty/mobs/EntityGlob.java @@ -0,0 +1,346 @@ +package biomesoplenty.mobs; + +import biomesoplenty.BiomesOPlenty; +import biomesoplenty.api.Items; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.WorldType; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.chunk.Chunk; + +public class EntityGlob extends EntityLiving implements IMob +{ + /** Chances for Globs to spawn in swamps for every moon phase. */ + private static final float[] spawnChances = new float[] {1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F}; + public float field_70813_a; + public float field_70811_b; + public float field_70812_c; + + /** the time between each jump of the Glob */ + private int GlobJumpDelay = 0; + + public EntityGlob(World par1World) + { + super(par1World); + this.texture = "/mods/BiomesOPlenty/textures/mobs/glob.png"; + int i = 1 << this.rand.nextInt(3); + this.yOffset = 0.0F; + this.GlobJumpDelay = this.rand.nextInt(20) + 10; + this.setGlobSize(i); + } + + protected void entityInit() + { + super.entityInit(); + this.dataWatcher.addObject(16, new Byte((byte)1)); + } + + protected void setGlobSize(int par1) + { + this.dataWatcher.updateObject(16, new Byte((byte)par1)); + this.setSize(0.6F * (float)par1, 0.6F * (float)par1); + this.setPosition(this.posX, this.posY, this.posZ); + this.setEntityHealth(this.getMaxHealth()); + this.experienceValue = par1; + } + + public int getMaxHealth() + { + int i = this.getGlobSize(); + return i * i; + } + + /** + * Returns the size of the Glob. + */ + public int getGlobSize() + { + return this.dataWatcher.getWatchableObjectByte(16); + } + + /** + * (abstract) Protected helper method to write subclass entity data to NBT. + */ + public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) + { + super.writeEntityToNBT(par1NBTTagCompound); + par1NBTTagCompound.setInteger("Size", this.getGlobSize() - 1); + } + + /** + * (abstract) Protected helper method to read subclass entity data from NBT. + */ + public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) + { + super.readEntityFromNBT(par1NBTTagCompound); + this.setGlobSize(par1NBTTagCompound.getInteger("Size") + 1); + } + + /** + * Returns the name of the sound played when the Glob jumps. + */ + protected String getJumpSound() + { + return "mob.slime." + (this.getGlobSize() > 1 ? "big" : "small"); + } + + /** + * Called to update the entity's position/logic. + */ + public void onUpdate() + { + if (!this.worldObj.isRemote && this.worldObj.difficultySetting == 0 && this.getGlobSize() > 0) + { + this.isDead = true; + } + + this.field_70811_b += (this.field_70813_a - this.field_70811_b) * 0.5F; + this.field_70812_c = this.field_70811_b; + boolean flag = this.onGround; + super.onUpdate(); + int i; + + if (this.onGround && !flag) + { + i = this.getGlobSize(); + + for (int j = 0; j < i * 8; ++j) + { + float f = this.rand.nextFloat() * (float)Math.PI * 2.0F; + float f1 = this.rand.nextFloat() * 0.5F + 0.5F; + float f2 = MathHelper.sin(f) * (float)i * 0.5F * f1; + float f3 = MathHelper.cos(f) * (float)i * 0.5F * f1; + BiomesOPlenty.proxy.spawnParticle("mud", this.posX + (double)f2, this.boundingBox.minY, this.posZ + (double)f3); + } + + if (this.makesSoundOnLand()) + { + this.playSound(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) / 0.8F); + } + + this.field_70813_a = -0.5F; + } + else if (!this.onGround && flag) + { + this.field_70813_a = 1.0F; + } + + this.func_70808_l(); + + if (this.worldObj.isRemote) + { + i = this.getGlobSize(); + this.setSize(0.6F * (float)i, 0.6F * (float)i); + } + } + + protected void updateEntityActionState() + { + this.despawnEntity(); + EntityPlayer entityplayer = this.worldObj.getClosestVulnerablePlayerToEntity(this, 16.0D); + + if (entityplayer != null) + { + this.faceEntity(entityplayer, 10.0F, 20.0F); + } + + if (this.onGround && this.GlobJumpDelay-- <= 0) + { + this.GlobJumpDelay = this.getJumpDelay(); + + if (entityplayer != null) + { + this.GlobJumpDelay /= 3; + } + + this.isJumping = true; + + if (this.makesSoundOnJump()) + { + this.playSound(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 0.8F); + } + + this.moveStrafing = 1.0F - this.rand.nextFloat() * 2.0F; + this.moveForward = (float)(1 * this.getGlobSize()); + } + else + { + this.isJumping = false; + + if (this.onGround) + { + this.moveStrafing = this.moveForward = 0.0F; + } + } + } + + protected void func_70808_l() + { + this.field_70813_a *= 0.6F; + } + + /** + * Gets the amount of time the Glob needs to wait between jumps. + */ + protected int getJumpDelay() + { + return this.rand.nextInt(20) + 10; + } + + protected EntityGlob createInstance() + { + return new EntityGlob(this.worldObj); + } + + /** + * Will get destroyed next tick. + */ + public void setDead() + { + int i = this.getGlobSize(); + + if (!this.worldObj.isRemote && i > 1 && this.getHealth() <= 0) + { + int j = 2 + this.rand.nextInt(3); + + for (int k = 0; k < j; ++k) + { + float f = ((float)(k % 2) - 0.5F) * (float)i / 4.0F; + float f1 = ((float)(k / 2) - 0.5F) * (float)i / 4.0F; + EntityGlob entityGlob = this.createInstance(); + entityGlob.setGlobSize(i / 2); + entityGlob.setLocationAndAngles(this.posX + (double)f, this.posY + 0.5D, this.posZ + (double)f1, this.rand.nextFloat() * 360.0F, 0.0F); + this.worldObj.spawnEntityInWorld(entityGlob); + } + } + + super.setDead(); + } + + /** + * Called by a player entity when they collide with an entity + */ + public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) + { + if (this.canDamagePlayer()) + { + int i = this.getGlobSize(); + + if (this.canEntityBeSeen(par1EntityPlayer) && this.getDistanceSqToEntity(par1EntityPlayer) < 0.6D * (double)i * 0.6D * (double)i && par1EntityPlayer.attackEntityFrom(DamageSource.causeMobDamage(this), this.getAttackStrength())) + { + this.playSound("mob.attack", 1.0F, (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F); + } + } + } + + /** + * Indicates weather the Glob is able to damage the player (based upon the Glob's size) + */ + protected boolean canDamagePlayer() + { + return this.getGlobSize() > 1; + } + + /** + * Gets the amount of damage dealt to the player when "attacked" by the Glob. + */ + protected int getAttackStrength() + { + return this.getGlobSize(); + } + + /** + * Returns the sound this mob makes when it is hurt. + */ + protected String getHurtSound() + { + return "mob.slime." + (this.getGlobSize() > 1 ? "big" : "small"); + } + + /** + * Returns the sound this mob makes on death. + */ + protected String getDeathSound() + { + return "mob.slime." + (this.getGlobSize() > 1 ? "big" : "small"); + } + + /** + * Returns the item ID for the item the mob drops on death. + */ + protected int getDropItemId() + { + return this.getGlobSize() == 1 ? Items.mudball.get().itemID : 0; + } + + /** + * Checks if the entity's current position is a valid location to spawn this entity. + */ + public boolean getCanSpawnHere() + { + Chunk chunk = this.worldObj.getChunkFromBlockCoords(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posZ)); + + if (this.worldObj.getWorldInfo().getTerrainType().handleSlimeSpawnReduction(rand, worldObj)) + { + return false; + } + else + { + if (this.getGlobSize() == 1 || this.worldObj.difficultySetting > 0) + { + BiomeGenBase biomegenbase = this.worldObj.getBiomeGenForCoords(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posZ)); + + if (biomegenbase == BiomeGenBase.swampland && this.posY > 50.0D && this.posY < 70.0D && this.rand.nextFloat() < 0.5F && this.rand.nextFloat() < spawnChances[this.worldObj.getMoonPhase()] && this.worldObj.getBlockLightValue(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) <= this.rand.nextInt(8)) + { + return super.getCanSpawnHere(); + } + + if (this.rand.nextInt(10) == 0 && chunk.getRandomWithSeed(987234911L).nextInt(10) == 0 && this.posY < 40.0D) + { + return super.getCanSpawnHere(); + } + } + + return false; + } + } + + /** + * Returns the volume for the sounds this mob makes. + */ + protected float getSoundVolume() + { + return 0.4F * (float)this.getGlobSize(); + } + + /** + * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently + * use in wolves. + */ + public int getVerticalFaceSpeed() + { + return 0; + } + + /** + * Returns true if the Glob makes a sound when it jumps (based upon the Glob's size) + */ + protected boolean makesSoundOnJump() + { + return this.getGlobSize() > 0; + } + + /** + * Returns true if the Glob makes a sound when it lands after a jump (based upon the Glob's size) + */ + protected boolean makesSoundOnLand() + { + return this.getGlobSize() > 2; + } +} diff --git a/src/minecraft/biomesoplenty/mobs/RenderGlob.java b/src/minecraft/biomesoplenty/mobs/RenderGlob.java new file mode 100644 index 000000000..56164b837 --- /dev/null +++ b/src/minecraft/biomesoplenty/mobs/RenderGlob.java @@ -0,0 +1,77 @@ +package biomesoplenty.mobs; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.renderer.entity.RenderLiving; +import net.minecraft.entity.EntityLiving; +import org.lwjgl.opengl.GL11; + +@SideOnly(Side.CLIENT) +public class RenderGlob extends RenderLiving +{ + private ModelBase scaleAmount; + + public RenderGlob(ModelBase par1ModelBase, ModelBase par2ModelBase, float par3) + { + super(par1ModelBase, par3); + this.scaleAmount = par2ModelBase; + } + + /** + * Determines whether Glob Render should pass or not. + */ + protected int shouldGlobRenderPass(EntityGlob par1EntityGlob, int par2, float par3) + { + if (par1EntityGlob.isInvisible()) + { + return 0; + } + else if (par2 == 0) + { + this.setRenderPassModel(this.scaleAmount); + GL11.glEnable(GL11.GL_NORMALIZE); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + return 1; + } + else + { + if (par2 == 1) + { + GL11.glDisable(GL11.GL_BLEND); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + } + + return -1; + } + } + + /** + * sets the scale for the Glob based on getGlobSize in EntityGlob + */ + protected void scaleGlob(EntityGlob par1EntityGlob, float par2) + { + float f1 = (float)par1EntityGlob.getGlobSize(); + float f2 = (par1EntityGlob.field_70812_c + (par1EntityGlob.field_70811_b - par1EntityGlob.field_70812_c) * par2) / (f1 * 0.5F + 1.0F); + float f3 = 1.0F / (f2 + 1.0F); + GL11.glScalef(f3 * f1, 1.0F / f3 * f1, f3 * f1); + } + + /** + * Allows the render to do any OpenGL state modifications necessary before the model is rendered. Args: + * entityLiving, partialTickTime + */ + protected void preRenderCallback(EntityLiving par1EntityLiving, float par2) + { + this.scaleGlob((EntityGlob)par1EntityLiving, par2); + } + + /** + * Queries whether should render the specified pass or not. + */ + protected int shouldRenderPass(EntityLiving par1EntityLiving, int par2, float par3) + { + return this.shouldGlobRenderPass((EntityGlob)par1EntityLiving, par2, par3); + } +} \ No newline at end of file