From aa3280ff315a0cc72e52ea8393bc0eb7a64f884e Mon Sep 17 00:00:00 2001 From: LemADEC Date: Thu, 9 Feb 2017 21:38:35 +0100 Subject: [PATCH] Added particle bunch entity with rendering (wip) --- src/main/java/cr0s/warpdrive/CommonProxy.java | 14 +- .../cr0s/warpdrive/api/ParticleRegistry.java | 10 +- .../cr0s/warpdrive/client/ClientProxy.java | 10 +- .../warpdrive/config/WarpDriveConfig.java | 3 + .../warpdrive/entity/EntityParticleBunch.java | 125 ++++++++++++++++ .../render/RenderEntityParticleBunch.java | 135 ++++++++++++++++++ 6 files changed, 287 insertions(+), 10 deletions(-) create mode 100644 src/main/java/cr0s/warpdrive/entity/EntityParticleBunch.java create mode 100644 src/main/java/cr0s/warpdrive/render/RenderEntityParticleBunch.java diff --git a/src/main/java/cr0s/warpdrive/CommonProxy.java b/src/main/java/cr0s/warpdrive/CommonProxy.java index 9093c782..404a3941 100644 --- a/src/main/java/cr0s/warpdrive/CommonProxy.java +++ b/src/main/java/cr0s/warpdrive/CommonProxy.java @@ -3,6 +3,7 @@ package cr0s.warpdrive; import com.mojang.authlib.GameProfile; import cpw.mods.fml.common.registry.EntityRegistry; import cr0s.warpdrive.config.WarpDriveConfig; +import cr0s.warpdrive.entity.EntityParticleBunch; import cr0s.warpdrive.render.EntityCamera; import cr0s.warpdrive.world.EntitySphereGen; import cr0s.warpdrive.world.EntityStarCore; @@ -21,13 +22,18 @@ import net.minecraftforge.event.world.BlockEvent; import java.lang.ref.WeakReference; import java.util.WeakHashMap; -public class CommonProxy { +public abstract class CommonProxy { private static final WeakHashMap> fakePlayers = new WeakHashMap<>(100); void registerEntities() { - EntityRegistry.registerModEntity(EntitySphereGen.class, "EntitySphereGenerator", WarpDriveConfig.G_ENTITY_SPHERE_GENERATOR_ID, WarpDrive.instance, 200, 1, false); - EntityRegistry.registerModEntity(EntityStarCore.class , "EntityStarCore" , WarpDriveConfig.G_ENTITY_STAR_CORE_ID , WarpDrive.instance, 300, 1, false); - EntityRegistry.registerModEntity(EntityCamera.class , "EntityCamera" , WarpDriveConfig.G_ENTITY_CAMERA_ID , WarpDrive.instance, 300, 1, false); + EntityRegistry.registerModEntity(EntitySphereGen.class , "EntitySphereGenerator", WarpDriveConfig.G_ENTITY_SPHERE_GENERATOR_ID, WarpDrive.instance, 200, 1, false); + EntityRegistry.registerModEntity(EntityStarCore.class , "EntityStarCore" , WarpDriveConfig.G_ENTITY_STAR_CORE_ID , WarpDrive.instance, 300, 1, false); + EntityRegistry.registerModEntity(EntityCamera.class , "EntityCamera" , WarpDriveConfig.G_ENTITY_CAMERA_ID , WarpDrive.instance, 300, 1, false); + EntityRegistry.registerModEntity(EntityParticleBunch.class, "EntityParticleBunch" , WarpDriveConfig.G_ENTITY_PARTICLE_BUNCH_ID , WarpDrive.instance, 300, 1, false); + } + + public void registerRendering() { + // client side only } private EntityPlayer getFakePlayer(EntityPlayer entityPlayer, WorldServer world, int x, int y, int z) { diff --git a/src/main/java/cr0s/warpdrive/api/ParticleRegistry.java b/src/main/java/cr0s/warpdrive/api/ParticleRegistry.java index 3bc47b8d..f191a469 100644 --- a/src/main/java/cr0s/warpdrive/api/ParticleRegistry.java +++ b/src/main/java/cr0s/warpdrive/api/ParticleRegistry.java @@ -16,11 +16,11 @@ public class ParticleRegistry { private static BiMap particles = HashBiMap.create(); - public static final Particle ION = new Particle("ion") { }.setColor(0xE5FF54).setRarity(EnumRarity.common); - public static final Particle PROTON = new Particle("proton") { }.setColor(0xE5FF54).setRarity(EnumRarity.common); - public static final Particle ANTIMATTER = new Particle("antimatter") { }.setColor(0x1C3CAF).setRarity(EnumRarity.uncommon); - public static final Particle STRANGE_MATTER = new Particle("strange_matter") { }.setColor(0xE2414C).setRarity(EnumRarity.rare); - // public static final Particle TACHYONS = new Particle("tachyons") { }.setColor(0xE5FF54).setRarity(EnumRarity.epic); + public static final Particle ION = new Particle("ion") { }.setColor(0xE5FF54).setRarity(EnumRarity.common).setColorIndex(0); + public static final Particle PROTON = new Particle("proton") { }.setColor(0xE5FF54).setRarity(EnumRarity.common).setColorIndex(1); + public static final Particle ANTIMATTER = new Particle("antimatter") { }.setColor(0x1C3CAF).setRarity(EnumRarity.uncommon).setColorIndex(2); + public static final Particle STRANGE_MATTER = new Particle("strange_matter") { }.setColor(0xE2414C).setRarity(EnumRarity.rare).setColorIndex(3); + // public static final Particle TACHYONS = new Particle("tachyons") { }.setColor(0xE5FF54).setRarity(EnumRarity.epic).setColorIndex(4); static { registerParticle(ION); diff --git a/src/main/java/cr0s/warpdrive/client/ClientProxy.java b/src/main/java/cr0s/warpdrive/client/ClientProxy.java index c728457f..641e0ee4 100644 --- a/src/main/java/cr0s/warpdrive/client/ClientProxy.java +++ b/src/main/java/cr0s/warpdrive/client/ClientProxy.java @@ -1,7 +1,15 @@ package cr0s.warpdrive.client; +import cpw.mods.fml.client.registry.RenderingRegistry; import cr0s.warpdrive.CommonProxy; +import cr0s.warpdrive.entity.EntityParticleBunch; +import cr0s.warpdrive.render.RenderEntityParticleBunch; public class ClientProxy extends CommonProxy { - + + @Override + public void registerRendering() { + super.registerRendering(); + RenderingRegistry.registerEntityRenderingHandler(EntityParticleBunch.class, new RenderEntityParticleBunch()); + } } \ No newline at end of file diff --git a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java index 65b19faf..6ce5e207 100644 --- a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java +++ b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java @@ -78,6 +78,7 @@ public class WarpDriveConfig { public static int G_ENTITY_SPHERE_GENERATOR_ID = 241; public static int G_ENTITY_STAR_CORE_ID = 242; public static int G_ENTITY_CAMERA_ID = 243; + public static int G_ENTITY_PARTICLE_BUNCH_ID = 244; public static final int LUA_SCRIPTS_NONE = 0; public static final int LUA_SCRIPTS_TEMPLATES = 1; @@ -362,6 +363,8 @@ public class WarpDriveConfig { config.get("general", "entity_star_core_id", G_ENTITY_STAR_CORE_ID, "Entity star core ID").getInt()); G_ENTITY_CAMERA_ID = clamp(Integer.MIN_VALUE, Integer.MAX_VALUE, config.get("general", "entity_camera_id", G_ENTITY_CAMERA_ID, "Entity camera ID").getInt()); + G_ENTITY_PARTICLE_BUNCH_ID = clamp(Integer.MIN_VALUE, Integer.MAX_VALUE, + config.get("general", "entity_particle_bunch_id", G_ENTITY_PARTICLE_BUNCH_ID, "Entity particle bunch ID").getInt()); G_LUA_SCRIPTS = clamp(0, 2, config.get("general", "lua_scripts", G_LUA_SCRIPTS, diff --git a/src/main/java/cr0s/warpdrive/entity/EntityParticleBunch.java b/src/main/java/cr0s/warpdrive/entity/EntityParticleBunch.java new file mode 100644 index 00000000..823bb0bc --- /dev/null +++ b/src/main/java/cr0s/warpdrive/entity/EntityParticleBunch.java @@ -0,0 +1,125 @@ +package cr0s.warpdrive.entity; + +import cr0s.warpdrive.WarpDrive; +import cr0s.warpdrive.config.WarpDriveConfig; +import cr0s.warpdrive.data.Vector3; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + +/* + * Created by LemADEC on 02/02/2017. + */ +public class EntityParticleBunch extends Entity { + + // persistent properties + public double energy = 0.0D; + public Vector3 vectorNextPosition = new Vector3(0.0D, 0.0D, 0.0D); + public Vector3 vectorTurningPoint = null; + + // computed properties + private int lastUpdateTicks = 0; + private static final int UPDATE_TICKS_TIMEOUT = 20; + + public EntityParticleBunch(World world) { + super(world); + if (WarpDriveConfig.LOGGING_ACCELERATOR) { + WarpDrive.logger.info(this + " created in dimension '" + worldObj.getWorldInfo().getWorldName() + "'"); + } + } + + public EntityParticleBunch(World world, int x, int y, int z) { + super(world); + this.posX = x + 0.5D; + this.posY = y + 0.5D; + this.posZ = z + 0.5D; + + if (WarpDriveConfig.LOGGING_ACCELERATOR) { + WarpDrive.logger.info(this + " created"); + } + } + + // override to skip the block bounding override on client side + @Override + public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int p_70056_9_) { + // super.setPositionAndRotation2(x, y, z, yaw, pitch, p_70056_9_); + this.setPosition(x, y, z); + this.setRotation(yaw, pitch); + } + + @Override + public boolean isEntityInvulnerable() { + return true; + } + + public void onRefreshFromSimulation(final double newEnergy, Vector3 vectorNewPosition, Vector3 vectorNewTurningPoint) { + setPosition(vectorNextPosition.x, vectorNextPosition.y, vectorNextPosition.z); + energy = newEnergy; + vectorNextPosition = vectorNewPosition; + vectorTurningPoint = vectorNewTurningPoint; + lastUpdateTicks = 0; + } + + @Override + public void onUpdate() { + if (worldObj.isRemote) { + return; + } + + lastUpdateTicks++; + if (lastUpdateTicks > UPDATE_TICKS_TIMEOUT) { + setDead(); + } + } + + @Override + protected void entityInit() { + // no data watcher + // entity size is used by vanilla to define render distance, so we force to a high value and adjust in render itself + setSize(2.0F, 2.0F); + yOffset = 2.0F; + noClip = true; + } + + @Override + public void setDead() { + super.setDead(); + if (WarpDriveConfig.LOGGING_ACCELERATOR) { + WarpDrive.logger.info(this + " dead"); + } + } + + @Override + public void onChunkLoad() { + super.onChunkLoad(); + // we're not supposed to reload this entity from a save + setDead(); + } + + @Override + protected void readEntityFromNBT(NBTTagCompound nbtTagCompound) { + energy = nbtTagCompound.getInteger("energy"); + vectorNextPosition = Vector3.createFromNBT(nbtTagCompound.getCompoundTag("nextPosition")); + if (nbtTagCompound.hasKey("turningPoint")) { + vectorTurningPoint = Vector3.createFromNBT(nbtTagCompound.getCompoundTag("turningPoint")); + } + } + + @Override + protected void writeEntityToNBT(NBTTagCompound nbtTagCompound) { + nbtTagCompound.setDouble("energy", energy); + nbtTagCompound.setTag("nextPosition", vectorNextPosition.writeToNBT(new NBTTagCompound())); + if (vectorTurningPoint != null) { + nbtTagCompound.setTag("turningPoint", vectorTurningPoint.writeToNBT(new NBTTagCompound())); + } + } + + @Override + public String toString() { + return String.format("%s/%d @ \'%s\' %.2f %.2f %.2f", + getClass().getSimpleName(), + getEntityId(), + worldObj == null ? "~NULL~" : worldObj.getWorldInfo().getWorldName(), + posX, posY, posZ); + } +} \ No newline at end of file diff --git a/src/main/java/cr0s/warpdrive/render/RenderEntityParticleBunch.java b/src/main/java/cr0s/warpdrive/render/RenderEntityParticleBunch.java new file mode 100644 index 00000000..90be2dd5 --- /dev/null +++ b/src/main/java/cr0s/warpdrive/render/RenderEntityParticleBunch.java @@ -0,0 +1,135 @@ +package cr0s.warpdrive.render; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import cr0s.warpdrive.entity.EntityParticleBunch; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderEntity; +import net.minecraft.entity.Entity; +import org.lwjgl.opengl.GL11; + +import java.util.Random; + +@SideOnly(Side.CLIENT) +public class RenderEntityParticleBunch extends RenderEntity { + + @Override + public void doRender(Entity entity, double x, double y, double z, float rotation, float partialTick) { + if (entity instanceof EntityParticleBunch) { + doRender((EntityParticleBunch) entity, x, y, z, rotation, partialTick); + } + } + + @Override + public void doRenderShadowAndFire(Entity entity, double x, double y, double z, float rotation, float partialTick) { + // super.doRenderShadowAndFire(entity, x, y, z, rotation, partialTick); + } + + public void doRender(EntityParticleBunch entityParticleBunch, double x, double y, double z, float rotation, float partialTick) { + // adjust render distance + final int maxRenderDistanceSquared; + if (Minecraft.getMinecraft().gameSettings.fancyGraphics) { + maxRenderDistanceSquared = 128 * 128; + } else { + maxRenderDistanceSquared = 20 * 20; + } + if ((x * x + y * y + z * z) > maxRenderDistanceSquared) { + return; + } + + // translate + GL11.glPushMatrix(); + GL11.glTranslatef((float) x, (float) y, (float) z); + + // compute parameters + final float energy = (float) entityParticleBunch.energy; + final float size = Math.min(Math.max(energy / 50000F, 0.01F), 0.07F); + final int rayCount_base = 45; + + renderStar(entityParticleBunch.ticksExisted + partialTick, entityParticleBunch.getEntityId(), rayCount_base, + 1.0F, 0.2F, 0.5F, 0.5F, 1.0F, 0.2F, size, size, size); + + // restore + GL11.glPopMatrix(); + } + + // Loosely based on ender dragon death effect + private static void renderStar(final float ticksExisted, final long seed, final int rayCount_base, + final float redIn, final float greenIn, final float blueIn, + final float redOut, final float greenOut, final float blueOut, + final float scaleX, final float scaleY, final float scaleZ) { + Random random = new Random(seed); + + // compute rotation cycle + final int tickRotationPeriod = 220 + 2 * random.nextInt(30); + int tickRotation = (int) (ticksExisted % tickRotationPeriod); + if (tickRotation >= tickRotationPeriod / 2) { + tickRotation = tickRotationPeriod - tickRotation - 1; + } + final float cycleRotation = 2 * tickRotation / (float) tickRotationPeriod; + + // compute boost pulsation cycle + final int tickBoostPeriod = 15 + 2 * random.nextInt(10); + int tickBoost = (int) (ticksExisted % tickBoostPeriod); + if (tickBoost >= tickBoostPeriod / 2) { + tickBoost = tickBoostPeriod - tickBoost - 1; + } + final float cycleBoost = 2 * tickBoost / (float) tickBoostPeriod; + float boost = 0.0F; + if (cycleBoost > 0.7F) { + boost = (cycleBoost - 0.6F) / 0.4F; + } + + // compute number of rays + // final int rayCount = 45 + (int) ((cycleRotation + cycleRotation * cycleRotation) * 15.0F); + final int rayCount = rayCount_base + random.nextInt(10); + + // drawing preparation + Tessellator tessellator = Tessellator.instance; + RenderHelper.disableStandardItemLighting(); + GL11.glPushAttrib(GL11.GL_LIGHTING_BIT | GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glShadeModel(GL11.GL_SMOOTH); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + GL11.glDisable(GL11.GL_ALPHA_TEST); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glDepthMask(false); + GL11.glPushMatrix(); + GL11.glScalef(scaleX, scaleY, scaleZ); + + for (int i = 0; i < rayCount; i++) { + GL11.glRotatef(random.nextFloat() * 360.0F, 1.0F, 0.0F, 0.0F); + GL11.glRotatef(random.nextFloat() * 360.0F, 0.0F, 1.0F, 0.0F); + GL11.glRotatef(random.nextFloat() * 360.0F, 0.0F, 0.0F, 1.0F); + GL11.glRotatef(random.nextFloat() * 360.0F, 1.0F, 0.0F, 0.0F); + GL11.glRotatef(random.nextFloat() * 360.0F, 0.0F, 1.0F, 0.0F); + GL11.glRotatef(random.nextFloat() * 360.0F + cycleRotation * 90F, 0.0F, 0.0F, 1.0F); + tessellator.startDrawing(6); + float rayLength = random.nextFloat() * 20.0F + 5.0F + boost * 10.0F; + float rayWidth = random.nextFloat() * 2.0F + 1.0F + boost * 2.0F; + tessellator.setColorRGBA_F(redIn, greenIn, blueIn, (int) (255F * (1.0F - boost))); + tessellator.addVertex(0.0D , 0.0D, 0.0D); + tessellator.setColorRGBA_F(redOut, greenOut, blueOut, 0); + tessellator.addVertex(-0.866D * rayWidth, rayLength, -0.5D * rayWidth); + tessellator.addVertex( 0.866D * rayWidth, rayLength, -0.5D * rayWidth); + tessellator.addVertex( 0.000D , rayLength, 1.0D * rayWidth); + tessellator.addVertex(-0.866D * rayWidth, rayLength, -0.5D * rayWidth); + tessellator.draw(); + } + + // drawing closure + GL11.glPopMatrix(); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_CULL_FACE); + GL11.glDisable(GL11.GL_BLEND); + GL11.glShadeModel(GL11.GL_FLAT); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_ALPHA_TEST); + GL11.glPopAttrib(); + RenderHelper.enableStandardItemLighting(); + } +} \ No newline at end of file