diff --git a/assets/Data/particles.json b/assets/Data/particles.json new file mode 100644 index 00000000..175e89e0 --- /dev/null +++ b/assets/Data/particles.json @@ -0,0 +1,13 @@ +{ + "data" : [ + { + "name" : "blood", + "maxLife" : 7, + "lifeCurrent" : 0, + "velocity" : 0.3, + "acceleration" : -0.1, + "size": 0.15, + "texture" : "Textures/bloodsplat1.png" + } + ] +} \ No newline at end of file diff --git a/assets/Textures/particles/blood1.png b/assets/Textures/particles/blood1.png new file mode 100644 index 00000000..da68586b Binary files /dev/null and b/assets/Textures/particles/blood1.png differ diff --git a/assets/Textures/particles/blood2.png b/assets/Textures/particles/blood2.png new file mode 100644 index 00000000..9a78b333 Binary files /dev/null and b/assets/Textures/particles/blood2.png differ diff --git a/assets/Textures/particles/blood3.png b/assets/Textures/particles/blood3.png new file mode 100644 index 00000000..53690385 Binary files /dev/null and b/assets/Textures/particles/blood3.png differ diff --git a/assets/Textures/particles/blood4.png b/assets/Textures/particles/blood4.png new file mode 100644 index 00000000..449d5486 Binary files /dev/null and b/assets/Textures/particles/blood4.png differ diff --git a/docs/src/progress/currenttarget.md b/docs/src/progress/currenttarget.md index 867d6de5..511d3a8f 100644 --- a/docs/src/progress/currenttarget.md +++ b/docs/src/progress/currenttarget.md @@ -20,6 +20,7 @@ + bug fixes Fix anime outlines drawing over solid geometry Fix anime outlines not drawing for first person pipeline + Fix falling tree not always deactivating on server Fix AI tracking deleted entity Fix server ground movement tree playing animation over falling animation Fix empty item slot not showing underneath dragged item diff --git a/net/combat.json b/net/combat.json index 5df40f75..bd2f6872 100644 --- a/net/combat.json +++ b/net/combat.json @@ -63,7 +63,10 @@ "receiverEntityID", "time", "hitboxType", - "hurtboxType" + "hurtboxType", + "positionX", + "positionY", + "positionZ" ] } diff --git a/src/main/java/electrosphere/client/collision/ClientHitboxCollision.java b/src/main/java/electrosphere/client/collision/ClientHitboxCollision.java index a97c9bb7..f53e1be4 100644 --- a/src/main/java/electrosphere/client/collision/ClientHitboxCollision.java +++ b/src/main/java/electrosphere/client/collision/ClientHitboxCollision.java @@ -2,8 +2,12 @@ package electrosphere.client.collision; import org.joml.Vector3d; +import electrosphere.client.effects.ParticleEffects; import electrosphere.engine.Globals; import electrosphere.entity.Entity; +import electrosphere.entity.types.creature.CreatureUtils; +import electrosphere.entity.types.item.ItemUtils; +import electrosphere.entity.types.object.ObjectUtils; import electrosphere.game.data.collidable.HitboxData; import electrosphere.logger.LoggerInterface; @@ -26,9 +30,11 @@ public class ClientHitboxCollision { case HitboxData.HITBOX_TYPE_HURT: case HitboxData.HITBOX_TYPE_HURT_CONNECTED: { Globals.hitboxAudioService.playAudioPositional(senderEntity, receiverEntity, hitboxType, hurtboxType, position); + ClientHitboxCollision.conditionallySpawnParticles(senderEntity, receiverEntity, hitboxType, hurtboxType, position); } break; case HitboxData.HITBOX_TYPE_BLOCK_CONNECTED: { Globals.hitboxAudioService.playAudioPositional(senderEntity, receiverEntity, hitboxType, hurtboxType, position); + ClientHitboxCollision.conditionallySpawnParticles(senderEntity, receiverEntity, hitboxType, hurtboxType, position); } break; default: { LoggerInterface.loggerEngine.WARNING("Client handling undefined hurtbox type: " + hurtboxType); @@ -41,4 +47,80 @@ public class ClientHitboxCollision { } } + + /** + * Figures out what particles to spawn based on a collisionn + * @param senderEntity The entity initiating the collision + * @param receiverEntity The entity receiving the collision + * @param hitboxType The hitbox type + * @param hurtboxType The hurtbox type + * @param position The position of the collision + */ + private static void conditionallySpawnParticles(Entity senderEntity, Entity receiverEntity, String hitboxType, String hurtboxType, Vector3d position){ + boolean isBlockSound = false; + boolean isDamageSound = false; + switch(hitboxType){ + case HitboxData.HITBOX_TYPE_HIT: + case HitboxData.HITBOX_TYPE_HIT_CONNECTED: { + switch(hurtboxType){ + case HitboxData.HITBOX_TYPE_HIT: + case HitboxData.HITBOX_TYPE_HIT_CONNECTED: { + isBlockSound = true; + } break; + case HitboxData.HITBOX_TYPE_BLOCK_CONNECTED: { + isBlockSound = true; + } break; + case HitboxData.HITBOX_TYPE_HURT: + case HitboxData.HITBOX_TYPE_HURT_CONNECTED: { + isDamageSound = true; + } break; + } + } break; + case HitboxData.HITBOX_TYPE_BLOCK_CONNECTED: { + switch(hurtboxType){ + case HitboxData.HITBOX_TYPE_HIT: + case HitboxData.HITBOX_TYPE_HIT_CONNECTED: { + isBlockSound = true; + } break; + case HitboxData.HITBOX_TYPE_BLOCK_CONNECTED: { + isBlockSound = true; + } break; + case HitboxData.HITBOX_TYPE_HURT: + case HitboxData.HITBOX_TYPE_HURT_CONNECTED: { + + } break; + } + } break; + case HitboxData.HITBOX_TYPE_HURT: + case HitboxData.HITBOX_TYPE_HURT_CONNECTED: { + + } break; + } + if(ItemUtils.isWeapon(senderEntity)){ + if(CreatureUtils.isCreature(receiverEntity)){ + if(isBlockSound){ + //TODO: handle + } else if(isDamageSound){ + ParticleEffects.spawnBloodsplats(position); + } + } else if(ItemUtils.isWeapon(receiverEntity)){ + if(isBlockSound){ + //TODO: handle + } + } else { + String message = "Getting audio for unhandled hurtbox collision type!\n" + + "Is creature: " + CreatureUtils.isCreature(receiverEntity) + "\n" + + "Is item: " + ItemUtils.isItem(receiverEntity) + "\n" + + "Is weapon: " + ItemUtils.isWeapon(receiverEntity) + "\n" + + "Is object: " + ObjectUtils.isObject(receiverEntity); + if(ItemUtils.isItem(receiverEntity)){ + message = message + "\nItem Type: " + ItemUtils.getType(receiverEntity); + } + LoggerInterface.loggerEngine.WARNING(message); + } + } else { + LoggerInterface.loggerEngine.WARNING("Getting audio for unhandled hitbox collision type!"); + } + } + } diff --git a/src/main/java/electrosphere/client/effects/ParticleEffects.java b/src/main/java/electrosphere/client/effects/ParticleEffects.java new file mode 100644 index 00000000..41953be5 --- /dev/null +++ b/src/main/java/electrosphere/client/effects/ParticleEffects.java @@ -0,0 +1,47 @@ +package electrosphere.client.effects; + +import electrosphere.engine.Globals; +import electrosphere.entity.ClientEntityUtils; +import electrosphere.entity.Entity; +import electrosphere.entity.EntityUtils; +import electrosphere.entity.types.particle.ParticleUtils; +import electrosphere.game.data.particle.ParticleData; + +import java.util.Random; + +import org.joml.Quaterniond; +import org.joml.Vector3d; + +/** + * Utility functions for spawning particle effects + */ +public class ParticleEffects { + + /** + * Spawns bloodsplats based on a collision + * @param position The position of the collision + */ + public static void spawnBloodsplats(Vector3d position){ + int max = 30; + int min = 10; + ParticleData bloodsplatData = null; + for(ParticleData data : Globals.gameConfigCurrent.getParticleDefinition().getData()){ + if(data.getName().equals("blood")){ + bloodsplatData = data; + } + } + Random rand = new Random(); + int num = (int)(rand.nextFloat() * (max - min)) + min; + for(int i = 0; i < num; i++){ + Vector3d destination = new Vector3d(rand.nextFloat() - 0.5f,rand.nextFloat() - 0.5f,rand.nextFloat() - 0.5f).normalize(); + Entity particleEntity = ParticleUtils.clientSpawnBillboardParticle(bloodsplatData, destination); + ClientEntityUtils.initiallyPositionEntity( + particleEntity, + position, + new Quaterniond() + ); + EntityUtils.getScale(particleEntity).mul(bloodsplatData.getSize()); + } + } + +} diff --git a/src/main/java/electrosphere/client/sim/ClientSimulation.java b/src/main/java/electrosphere/client/sim/ClientSimulation.java index 85922d1b..f4f75c81 100644 --- a/src/main/java/electrosphere/client/sim/ClientSimulation.java +++ b/src/main/java/electrosphere/client/sim/ClientSimulation.java @@ -16,7 +16,6 @@ import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.camera.CameraEntityUtils; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.item.ItemUtils; -import electrosphere.entity.types.particle.ParticleUtils; import electrosphere.renderer.actor.Actor; public class ClientSimulation { @@ -75,12 +74,6 @@ public class ClientSimulation { } Globals.profiler.endCpuSample(); // - //particle state updates - Globals.profiler.beginCpuSample("particle state updates"); - for(Entity particle : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){ - ParticleUtils.makeParticleBillboardFaceCamera(particle); - } - Globals.profiler.endCpuSample(); //update attached entity positions AttachUtils.clientUpdateAttachedEntityPositions(); // diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index 8e28e27b..8404ade9 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -38,6 +38,7 @@ import electrosphere.engine.time.Timekeeper; import electrosphere.entity.Entity; import electrosphere.entity.Scene; import electrosphere.game.config.UserSettings; +import electrosphere.game.data.particle.ParticleDefinition; import electrosphere.game.data.voxel.VoxelType; import electrosphere.game.server.structure.virtual.StructureManager; import electrosphere.game.server.world.MacroData; @@ -266,7 +267,11 @@ public class Globals { public static ShaderProgram defaultMeshShader; public static ShaderProgram terrainShaderProgram; + // + // Particle stuff + // public static String particleBillboardModel; + public static ParticleDefinition particleDefinition; public static ShaderOptionMap shaderOptionMap; @@ -515,6 +520,7 @@ public class Globals { "Textures/color/transparent_orange.png", "Textures/color/transparent_teal.png", "Textures/color/transparent_yellow.png", + "Textures/bloodsplat1.png", }; /** diff --git a/src/main/java/electrosphere/entity/state/life/ServerLifeTree.java b/src/main/java/electrosphere/entity/state/life/ServerLifeTree.java index c8dde958..11be6214 100644 --- a/src/main/java/electrosphere/entity/state/life/ServerLifeTree.java +++ b/src/main/java/electrosphere/entity/state/life/ServerLifeTree.java @@ -141,7 +141,10 @@ public class ServerLifeTree implements BehaviorTree { parent.getId(), Globals.timekeeper.getNumberOfSimFramesElapsed(), event.sourceHitboxData.getHitboxData().getType(), - HitboxData.HITBOX_TYPE_BLOCK_CONNECTED + HitboxData.HITBOX_TYPE_BLOCK_CONNECTED, + event.position.x, + event.position.y, + event.position.z ) ); } @@ -161,7 +164,10 @@ public class ServerLifeTree implements BehaviorTree { parent.getId(), Globals.timekeeper.getNumberOfSimFramesElapsed(), event.sourceHitboxData.getHitboxData().getType(), - event.parentHitboxData.getHitboxData().getType() + event.parentHitboxData.getHitboxData().getType(), + event.position.x, + event.position.y, + event.position.z ) ); @@ -189,7 +195,7 @@ public class ServerLifeTree implements BehaviorTree { * @param isBlock True if this is a block event */ public void addCollisionEvent(Entity collisionSource, HitboxState sourceHitboxData, HitboxState parentHitboxData, Vector3d position, boolean isDamage, boolean isBlock){ - CollisionEvent collisionEvent = new CollisionEvent(collisionSource, sourceHitboxData, parentHitboxData, isDamage, isBlock); + CollisionEvent collisionEvent = new CollisionEvent(collisionSource, sourceHitboxData, parentHitboxData, isDamage, isBlock, position); this.collisionAccumulator.add(collisionEvent); } @@ -314,6 +320,11 @@ public class ServerLifeTree implements BehaviorTree { */ boolean isBlock; + /** + * The position of the collision + */ + Vector3d position; + /** * Constructor * @param source The source of the collision @@ -321,13 +332,15 @@ public class ServerLifeTree implements BehaviorTree { * @param parentHitboxData The hitbox data for the parent of the tree * @param isDamage True if this is a damage event * @param isBlock True if this is a block event + * @param position The position of the collision */ - public CollisionEvent(Entity source, HitboxState sourceHitboxData, HitboxState parentHitboxData, boolean isDamage, boolean isBlock){ + public CollisionEvent(Entity source, HitboxState sourceHitboxData, HitboxState parentHitboxData, boolean isDamage, boolean isBlock, Vector3d position){ this.source = source; this.sourceHitboxData = sourceHitboxData; this.parentHitboxData = parentHitboxData; this.isDamage = isDamage; this.isBlock = isBlock; + this.position = position; } } diff --git a/src/main/java/electrosphere/entity/state/particle/ClientParticleTree.java b/src/main/java/electrosphere/entity/state/particle/ClientParticleTree.java index 1f5c5d43..11d787c4 100644 --- a/src/main/java/electrosphere/entity/state/particle/ClientParticleTree.java +++ b/src/main/java/electrosphere/entity/state/particle/ClientParticleTree.java @@ -1,13 +1,17 @@ package electrosphere.entity.state.particle; +import org.joml.AxisAngle4f; +import org.joml.Matrix4f; +import org.joml.Quaternionf; import org.joml.Vector3d; -import org.joml.Vector3f; import electrosphere.engine.Globals; +import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; +import electrosphere.game.data.particle.ParticleData; /** * Particle component for a client-side particle @@ -26,7 +30,7 @@ public class ClientParticleTree implements BehaviorTree { //The destination of the particle - Vector3f destination; + Vector3d destination; //the velocity of the particle float velocity; @@ -35,15 +39,29 @@ public class ClientParticleTree implements BehaviorTree { float acceleration; + /** + * Constructor + * @param parent + * @param params + */ private ClientParticleTree(Entity parent, Object ... params){ - //int maxLife, Vector3f destination, float velocity, float acceleration, boolean hasLife + if(params.length < 1){ + throw new IllegalArgumentException("No particle data was provided"); + } + if(params.length < 2){ + throw new IllegalArgumentException("No destination set for the particle"); + } + ParticleData particleData = (ParticleData)params[0]; + Vector3d destination = (Vector3d)params[1]; + + //sets data for the tree this.parent = parent; - this.maxLife = maxLife; + this.maxLife = particleData.getMaxLife(); this.destination = destination; - this.velocity = velocity; - this.acceleration = acceleration; - this.hasLife = hasLife; - lifeCurrent = maxLife; + this.velocity = particleData.getVelocity(); + this.acceleration = particleData.getAcceleration(); + this.hasLife = particleData.getMaxLife() != null; + this.lifeCurrent = maxLife; } public int getMaxLife() { @@ -54,7 +72,7 @@ public class ClientParticleTree implements BehaviorTree { return lifeCurrent; } - public Vector3f getDestination() { + public Vector3d getDestination() { return destination; } @@ -69,8 +87,8 @@ public class ClientParticleTree implements BehaviorTree { @Override public void simulate(float deltaTime){ Vector3d parentPosition = EntityUtils.getPosition(parent); - parentPosition.add(new Vector3f(destination).mul(velocity)); - velocity = velocity - acceleration; + parentPosition.add(new Vector3d(destination).mul(velocity)); + velocity = velocity + acceleration; if(velocity < 0){ velocity = 0; acceleration = 0; @@ -78,9 +96,14 @@ public class ClientParticleTree implements BehaviorTree { if(hasLife){ lifeCurrent--; if(lifeCurrent <= 0){ - EntityUtils.cleanUpEntity(parent); + ClientEntityUtils.destroyEntity(parent); } } + + //rotate the model to face the camera + Matrix4f rotationMatrix = new Matrix4f(Globals.viewMatrix).invert(); + Quaternionf rotation = new Quaternionf(rotationMatrix.getRotation(new AxisAngle4f())); + EntityUtils.getRotation(parent).set(rotation); } /** diff --git a/src/main/java/electrosphere/entity/types/particle/ParticleUtils.java b/src/main/java/electrosphere/entity/types/particle/ParticleUtils.java index 63148272..b2b1d553 100644 --- a/src/main/java/electrosphere/entity/types/particle/ParticleUtils.java +++ b/src/main/java/electrosphere/entity/types/particle/ParticleUtils.java @@ -1,17 +1,20 @@ package electrosphere.entity.types.particle; import electrosphere.engine.Globals; +import electrosphere.entity.DrawableUtils; import electrosphere.entity.Entity; import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityTags; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.ParticleTree; -import electrosphere.entity.types.camera.CameraEntityUtils; +import electrosphere.entity.state.particle.ClientParticleTree; +import electrosphere.game.data.particle.ParticleData; +import electrosphere.renderer.actor.Actor; +import electrosphere.renderer.actor.ActorTextureMask; + +import java.util.Arrays; -import org.joml.AxisAngle4f; -import org.joml.Matrix4f; -import org.joml.Quaternionf; import org.joml.Vector3d; import org.joml.Vector3f; @@ -22,17 +25,7 @@ public class ParticleUtils { - // public static Entity clientSpawnBillboardProjectileParticle(String texture, int maxLife, Vector3f destination, float velocity, float acceleration){ - // Entity rVal = EntityCreationUtils.createClientSpatialEntity(); - // EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel); - // EntityUtils.getActor(rVal).setTextureOverride(texture); - // Globals.assetManager.addTexturePathtoQueue(texture); - // ParticleTree particleTree = new ParticleTree(rVal, maxLife, destination, velocity, acceleration, true); - // rVal.putData(EntityDataStrings.TREE_CLIENTPARTICLETREE, particleTree); - // rVal.putData(EntityDataStrings.IS_PARTICLE, true); - // Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.PARTICLE); - // return rVal; - // } + public static Entity clientSpawnStaticBillboardParticle(){ Entity rVal = EntityCreationUtils.createClientSpatialEntity(); @@ -43,19 +36,36 @@ public class ParticleUtils { Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.PARTICLE); return rVal; } - - public static void makeParticleBillboardFaceCamera(Entity particle){ - Vector3f cameraCenter = CameraEntityUtils.getCameraCenter(Globals.playerCamera); - Vector3f cameraEye = new Vector3f(CameraEntityUtils.getCameraEye(Globals.playerCamera)).add(cameraCenter).mul(-1.0f); - Vector3d particlePosition = EntityUtils.getPosition(particle); -// Vector3f cameraEye = new Vector3f(CameraEntityUtils.getCameraEye(Globals.playerCamera)).mul(1.0f,-1.0f,-1.0f); -// Vector3f directionVector = new Vector3f(cameraCenter).sub(cameraEye); - Matrix4f rotationMatrix = new Matrix4f(Globals.viewMatrix).invert(); - Quaternionf rotation = new Quaternionf(rotationMatrix.getRotation(new AxisAngle4f())); - EntityUtils.getRotation(particle).set(rotation); + + /** + * Spawns a billboard particle + * @param data The particle definition + * @param destination the destination of the particle + * @return The particle entity + */ + public static Entity clientSpawnBillboardParticle(ParticleData data, Vector3d destination){ + Entity rVal = EntityCreationUtils.createClientSpatialEntity(); + EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel); + + //actor logic + Actor particleActor = EntityUtils.getActor(rVal); + DrawableUtils.makeEntityTransparent(rVal); + particleActor.addTextureMask(new ActorTextureMask("particleBillboard", Arrays.asList(data.getTexture()))); + + //behavior tree attachments + ClientParticleTree.attachTree(rVal, data, destination); + rVal.putData(EntityDataStrings.IS_PARTICLE, true); + Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.PARTICLE); + return rVal; } - - public static ParticleTree getParticleTree(Entity particle){ - return (ParticleTree)particle.getData(EntityDataStrings.TREE_CLIENTPARTICLETREE); + + /** + * Checks if the provided entity is a particle or not + * @param entity The entity + * @return true if it is a particle, false otherwise + */ + public static boolean isParticle(Entity entity){ + return entity.containsKey(EntityDataStrings.IS_PARTICLE); } + } diff --git a/src/main/java/electrosphere/game/data/Config.java b/src/main/java/electrosphere/game/data/Config.java index bd6b207c..3a9699fd 100644 --- a/src/main/java/electrosphere/game/data/Config.java +++ b/src/main/java/electrosphere/game/data/Config.java @@ -13,6 +13,7 @@ import electrosphere.game.data.item.type.model.ItemTypeMap; import electrosphere.game.data.object.type.ObjectData; import electrosphere.game.data.object.type.model.ObjectTypeLoader; import electrosphere.game.data.object.type.model.ObjectTypeMap; +import electrosphere.game.data.particle.ParticleDefinition; import electrosphere.game.data.projectile.ProjectileTypeHolder; import electrosphere.game.data.structure.type.model.StructureTypeMap; import electrosphere.game.data.tutorial.HintDefinition; @@ -45,6 +46,11 @@ public class Config { * The surface audio definitions */ SurfaceAudioCollection surfaceAudioCollection; + + /** + * The particle definition + */ + ParticleDefinition particleDefinition; /** * Loads the default data @@ -63,6 +69,7 @@ public class Config { config.projectileTypeHolder = FileUtils.loadObjectFromAssetPath("Data/projectile.json", ProjectileTypeHolder.class); config.hintData = FileUtils.loadObjectFromAssetPath("Data/tutorial/hints.json", HintDefinition.class); config.surfaceAudioCollection = FileUtils.loadObjectFromAssetPath("Data/audio/surface.json", SurfaceAudioCollection.class); + config.particleDefinition = FileUtils.loadObjectFromAssetPath("Data/particles.json", ParticleDefinition.class); config.projectileTypeHolder.init(); //validate @@ -240,5 +247,13 @@ public class Config { public SurfaceAudioCollection getSurfaceAudioCollection(){ return this.surfaceAudioCollection; } + + /** + * Gets the particle definition + * @return The particle definition + */ + public ParticleDefinition getParticleDefinition(){ + return particleDefinition; + } } diff --git a/src/main/java/electrosphere/game/data/particle/ParticleData.java b/src/main/java/electrosphere/game/data/particle/ParticleData.java new file mode 100644 index 00000000..cd2dbc7c --- /dev/null +++ b/src/main/java/electrosphere/game/data/particle/ParticleData.java @@ -0,0 +1,102 @@ +package electrosphere.game.data.particle; + +/** + * Data on how a particle should behave + */ +public class ParticleData { + + + /** + * The name of the particle type + */ + String name; + + /** + * The maximum life of the particle + */ + Integer maxLife; + + + /** + * The life the particle starts with + */ + Integer lifeCurrent; + + + /** + * The initial velocity of the particle + */ + Float velocity; + + /** + * The acceleration of the particle + */ + Float acceleration; + + /** + * The texture of the particle + */ + String texture; + + /** + * The size of the particle + */ + Float size; + + /** + * Gets the max life of the particle + * @return The max life + */ + public Integer getMaxLife(){ + return maxLife; + } + + /** + * Gets the starting life of the particle + * @return The starting life + */ + public Integer getLifeCurrent(){ + return lifeCurrent; + } + + /** + * Gets the starting velocity of the particle + * @return The starting velocity + */ + public Float getVelocity(){ + return velocity; + } + + /** + * Gets the acceleration of the particle + * @return The acceleration + */ + public Float getAcceleration(){ + return acceleration; + } + + /** + * Gets the texture of the particle + * @return The texture + */ + public String getTexture(){ + return texture; + } + + /** + * Gets the name of the particle type + * @return The name of the particle type + */ + public String getName(){ + return name; + } + + /** + * Gets the size of the particle + * @return The size of the particle + */ + public Float getSize(){ + return size; + } + +} diff --git a/src/main/java/electrosphere/game/data/particle/ParticleDefinition.java b/src/main/java/electrosphere/game/data/particle/ParticleDefinition.java new file mode 100644 index 00000000..e6f10ec8 --- /dev/null +++ b/src/main/java/electrosphere/game/data/particle/ParticleDefinition.java @@ -0,0 +1,23 @@ +package electrosphere.game.data.particle; + +import java.util.List; + +/** + * File that defines all particles + */ +public class ParticleDefinition { + + /** + * The particle data + */ + List data; + + /** + * Gets the particle data + * @return The particle data + */ + public List getData(){ + return data; + } + +} diff --git a/src/main/java/electrosphere/game/server/effects/ParticleEffects.java b/src/main/java/electrosphere/game/server/effects/ParticleEffects.java deleted file mode 100644 index 7d0e6abb..00000000 --- a/src/main/java/electrosphere/game/server/effects/ParticleEffects.java +++ /dev/null @@ -1,40 +0,0 @@ -package electrosphere.game.server.effects; - -import electrosphere.entity.Entity; -import electrosphere.entity.EntityUtils; -import electrosphere.entity.types.particle.ParticleUtils; -import java.util.Random; -import org.joml.Vector3f; - -/** - * Utility functions for spawning particle effects - */ -public class ParticleEffects { - - - // public static void spawnSparks(Vector3f position, int min, int max){ - // Random rand = new Random(); - // int num = (int)(rand.nextFloat() * (max - min)) + min; - // for(int i = 0; i < num; i++){ - // Vector3f direction = new Vector3f(rand.nextFloat() - 0.5f,rand.nextFloat() - 0.5f,rand.nextFloat() - 0.5f).normalize(); - // float velocity = rand.nextFloat() * 0.01f; - // float acceleration = 0.005f; - // Entity spark = ParticleUtils.clientSpawnBillboardProjectileParticle("Textures/spark1.png", 15, direction, velocity, acceleration); - // EntityUtils.getPosition(spark).set(position); - // EntityUtils.getScale(spark).mul(0.03f); - // } - // } - - // public static void spawnBloodsplats(Vector3f position, int min, int max){ - // Random rand = new Random(); - // int num = (int)(rand.nextFloat() * (max - min)) + min; - // for(int i = 0; i < num; i++){ - // Vector3f direction = new Vector3f(rand.nextFloat() - 0.5f,rand.nextFloat() - 0.5f,rand.nextFloat() - 0.5f).normalize(); - // float velocity = rand.nextFloat() * 0.001f; - // float acceleration = 0.000005f; - // Entity spark = ParticleUtils.clientSpawnBillboardProjectileParticle("Textures/bloodsplat1.png", 90, direction, velocity, acceleration); - // EntityUtils.getPosition(spark).set(position); - // EntityUtils.getScale(spark).mul(0.1f); - // } - // } -} diff --git a/src/main/java/electrosphere/net/parser/net/message/CombatMessage.java b/src/main/java/electrosphere/net/parser/net/message/CombatMessage.java index 142e2c69..106fb361 100644 --- a/src/main/java/electrosphere/net/parser/net/message/CombatMessage.java +++ b/src/main/java/electrosphere/net/parser/net/message/CombatMessage.java @@ -180,6 +180,15 @@ public class CombatMessage extends NetworkMessage { if(currentStreamLength < 26 + hitboxTypeSize + hurtboxTypeSize){ return false; } + if(currentStreamLength < 34 + hitboxTypeSize + hurtboxTypeSize){ + return false; + } + if(currentStreamLength < 42 + hitboxTypeSize + hurtboxTypeSize){ + return false; + } + if(currentStreamLength < 50 + hitboxTypeSize + hurtboxTypeSize){ + return false; + } return true; } @@ -191,16 +200,22 @@ public class CombatMessage extends NetworkMessage { rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer)); rVal.sethitboxType(ByteStreamUtils.popStringFromByteQueue(byteBuffer)); rVal.sethurtboxType(ByteStreamUtils.popStringFromByteQueue(byteBuffer)); + rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer)); + rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer)); + rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer)); return rVal; } - public static CombatMessage constructserverReportHitboxCollisionMessage(int entityID,int receiverEntityID,long time,String hitboxType,String hurtboxType){ + public static CombatMessage constructserverReportHitboxCollisionMessage(int entityID,int receiverEntityID,long time,String hitboxType,String hurtboxType,double positionX,double positionY,double positionZ){ CombatMessage rVal = new CombatMessage(CombatMessageType.SERVERREPORTHITBOXCOLLISION); rVal.setentityID(entityID); rVal.setreceiverEntityID(receiverEntityID); rVal.settime(time); rVal.sethitboxType(hitboxType); rVal.sethurtboxType(hurtboxType); + rVal.setpositionX(positionX); + rVal.setpositionY(positionY); + rVal.setpositionZ(positionZ); rVal.serialize(); return rVal; } @@ -211,7 +226,7 @@ public class CombatMessage extends NetworkMessage { byte[] stringBytes; switch(this.messageType){ case SERVERREPORTHITBOXCOLLISION: - rawBytes = new byte[2+4+4+8+4+hitboxType.length()+4+hurtboxType.length()]; + rawBytes = new byte[2+4+4+8+4+hitboxType.length()+4+hurtboxType.length()+8+8+8]; //message header rawBytes[0] = TypeBytes.MESSAGE_TYPE_COMBAT; //entity messaage header @@ -244,6 +259,18 @@ public class CombatMessage extends NetworkMessage { for(int i = 0; i < hurtboxType.length(); i++){ rawBytes[26+hitboxType.length()+i] = stringBytes[i]; } + intValues = ByteStreamUtils.serializeDoubleToBytes(positionX); + for(int i = 0; i < 8; i++){ + rawBytes[26+hitboxType.length()+hurtboxType.length()+i] = intValues[i]; + } + intValues = ByteStreamUtils.serializeDoubleToBytes(positionY); + for(int i = 0; i < 8; i++){ + rawBytes[34+hitboxType.length()+hurtboxType.length()+i] = intValues[i]; + } + intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ); + for(int i = 0; i < 8; i++){ + rawBytes[42+hitboxType.length()+hurtboxType.length()+i] = intValues[i]; + } break; } serialized = true; diff --git a/src/main/java/electrosphere/renderer/RenderUtils.java b/src/main/java/electrosphere/renderer/RenderUtils.java index 7caf015d..5c4fd055 100644 --- a/src/main/java/electrosphere/renderer/RenderUtils.java +++ b/src/main/java/electrosphere/renderer/RenderUtils.java @@ -150,7 +150,6 @@ public class RenderUtils { 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, - }; // @@ -199,10 +198,10 @@ public class RenderUtils { // FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8); float[] texturedata = { - 0,0, - 1,0, 0,1, - 1,1 + 1,1, + 0,0, + 1,0 }; texture_coords.put(texturedata); texture_coords.flip(); @@ -211,7 +210,7 @@ public class RenderUtils { - particleMesh.setShader(ShaderProgram.loadSpecificShader("Shaders/particleBillboard/particleBillboard.vs", "Shaders/particleBillboard/particleBillboard.fs")); + particleMesh.setShader(ShaderProgram.smartAssembleOITProgram(false, true)); diff --git a/src/main/java/electrosphere/renderer/actor/ActorTextureMask.java b/src/main/java/electrosphere/renderer/actor/ActorTextureMask.java index 42701571..fd27b818 100644 --- a/src/main/java/electrosphere/renderer/actor/ActorTextureMask.java +++ b/src/main/java/electrosphere/renderer/actor/ActorTextureMask.java @@ -4,28 +4,83 @@ import java.util.List; import electrosphere.renderer.texture.Texture; +/** + * A mask that overwrites the texture for a given mesh for a given actor + */ public class ActorTextureMask { + /** + * The mesh this mask is overwriting + */ String meshName; + + /** + * The texture objects used for this mask + */ List textures; + + /** + * The paths to textures to be used for this mask + */ + List texturePaths; + + /** + * The uniform names used for this mask + */ List uniformNames; + /** + * Constructor + * @param meshName The name of the mesh to mask + * @param textures The texture objects to use to mask (ie diffuse and normal) + * @param uniformNames The uniform names used for each texture + */ public ActorTextureMask(String meshName, List textures, List uniformNames){ this.meshName = meshName; this.textures = textures; this.uniformNames = uniformNames; } + /** + * Constructor (does not use non-standard uniform names) + * @param meshName The name of the mesh to mask + * @param texturePaths The texture paths to use to mask + */ + public ActorTextureMask(String meshName, List texturePaths){ + this.meshName = meshName; + this.texturePaths = texturePaths; + } + + /** + * Gets the name of the mesh this is masking + * @return The name of the mesh + */ public String getMeshName(){ return meshName; } + /** + * Gets the list of texture objects used to mask + * @return The list of texture objects + */ public List getTextures(){ return textures; } + /** + * Gets the list of uniform names + * @return The list of uniform names + */ public List getUniformNames(){ return uniformNames; } + /** + * Gets the texture paths to use + * @return The texture paths + */ + public List getTexturePaths(){ + return this.texturePaths; + } + } diff --git a/src/main/java/electrosphere/renderer/model/Mesh.java b/src/main/java/electrosphere/renderer/model/Mesh.java index a5b6d2a1..5b4e4c83 100644 --- a/src/main/java/electrosphere/renderer/model/Mesh.java +++ b/src/main/java/electrosphere/renderer/model/Mesh.java @@ -397,25 +397,32 @@ public class Mesh { - + // + //The texture masking logic if(textureMask != null){ - int i = 0; -// glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "groundTextures"), 5); -// for(int j = 1; j < 15; j++){ -// textureList.get(0).bind(j); -// } - for(Texture texture : textureMask.getTextures()){ -// System.out.println(texture.getPath() + " => groundTextures[" + i + "]" + "=>" + (i)); - if(texture != null){ - texture.bind(openGLState,5+i); + // + //path that uses already-defined texture objects + if(textureMask.getTextures() != null){ + int i = 0; + for(Texture texture : textureMask.getTextures()){ + if(texture != null){ + texture.bind(openGLState,5+i); + } + glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), textureMask.getUniformNames().get(i)),5+i); + i++; + } + } else if(textureMask.getTexturePaths() != null){ + // + //path that uses paths to textures in the asset manager + int i = 0; + for(String texturePath : textureMask.getTexturePaths()){ + Texture texture = Globals.assetManager.fetchTexture(texturePath); + if(texture != null){ + texture.bind(openGLState, i); + } + i++; } - glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), textureMask.getUniformNames().get(i)),5+i); - i++; } - // for(int j = i; j < 10; j++){ - // glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "groundTextures[" + j + "]"),6+j); - // } -// glActiveTexture(GL_TEXTURE0); Globals.renderingEngine.checkError(); } diff --git a/src/main/java/electrosphere/server/datacell/physics/ServerHitboxResolutionCallback.java b/src/main/java/electrosphere/server/datacell/physics/ServerHitboxResolutionCallback.java index 642421de..d8eca49b 100644 --- a/src/main/java/electrosphere/server/datacell/physics/ServerHitboxResolutionCallback.java +++ b/src/main/java/electrosphere/server/datacell/physics/ServerHitboxResolutionCallback.java @@ -102,7 +102,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba if(isItem){ if(hitboxAttachParent != receiverParent){ ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent); - serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, localPosition, isDamageEvent, isBlockEvent); + serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent); } } @@ -120,13 +120,13 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba //item is equipped to something ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(AttachUtils.getParent(receiverParent)); if(serverLifeTree != null){ - serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, localPosition, isDamageEvent, isBlockEvent); + serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent); } } else { //attacking an item that is not equipped to anything ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent); if(serverLifeTree != null){ - serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, localPosition, isDamageEvent, isBlockEvent); + serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent); } } diff --git a/src/main/java/electrosphere/server/simulation/MicroSimulation.java b/src/main/java/electrosphere/server/simulation/MicroSimulation.java index d6f511d7..17615f24 100644 --- a/src/main/java/electrosphere/server/simulation/MicroSimulation.java +++ b/src/main/java/electrosphere/server/simulation/MicroSimulation.java @@ -10,7 +10,6 @@ import electrosphere.entity.EntityTags; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.types.item.ItemUtils; -import electrosphere.entity.types.particle.ParticleUtils; import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.poseactor.PoseActor; @@ -49,12 +48,6 @@ public class MicroSimulation { for(Entity item : dataCell.getScene().getEntitiesWithTag(EntityTags.ITEM)){ ItemUtils.updateItemPoseActorAnimation(item); } - //particle state updates - for(Entity particle : dataCell.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){ - // ParticleTree tree = ParticleUtils.getParticleTree(particle); - // tree.simulate(Main.deltaFrames); - ParticleUtils.makeParticleBillboardFaceCamera(particle); - } //simulate behavior trees dataCell.getScene().simulateBehaviorTrees((float)Globals.timekeeper.getSimFrameTime()); //update attached entity positions