particle work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
0905157327
commit
af4d1317fc
13
assets/Data/particles.json
Normal file
13
assets/Data/particles.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"data" : [
|
||||
{
|
||||
"name" : "blood",
|
||||
"maxLife" : 7,
|
||||
"lifeCurrent" : 0,
|
||||
"velocity" : 0.3,
|
||||
"acceleration" : -0.1,
|
||||
"size": 0.15,
|
||||
"texture" : "Textures/bloodsplat1.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
assets/Textures/particles/blood1.png
Normal file
BIN
assets/Textures/particles/blood1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
assets/Textures/particles/blood2.png
Normal file
BIN
assets/Textures/particles/blood2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
assets/Textures/particles/blood3.png
Normal file
BIN
assets/Textures/particles/blood3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
BIN
assets/Textures/particles/blood4.png
Normal file
BIN
assets/Textures/particles/blood4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
@ -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
|
||||
|
||||
@ -63,7 +63,10 @@
|
||||
"receiverEntityID",
|
||||
"time",
|
||||
"hitboxType",
|
||||
"hurtboxType"
|
||||
"hurtboxType",
|
||||
"positionX",
|
||||
"positionY",
|
||||
"positionZ"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -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!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
//
|
||||
|
||||
@ -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",
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
102
src/main/java/electrosphere/game/data/particle/ParticleData.java
Normal file
102
src/main/java/electrosphere/game/data/particle/ParticleData.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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<ParticleData> data;
|
||||
|
||||
/**
|
||||
* Gets the particle data
|
||||
* @return The particle data
|
||||
*/
|
||||
public List<ParticleData> getData(){
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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<Texture> textures;
|
||||
|
||||
/**
|
||||
* The paths to textures to be used for this mask
|
||||
*/
|
||||
List<String> texturePaths;
|
||||
|
||||
/**
|
||||
* The uniform names used for this mask
|
||||
*/
|
||||
List<String> 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<Texture> textures, List<String> 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<String> 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<Texture> getTextures(){
|
||||
return textures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of uniform names
|
||||
* @return The list of uniform names
|
||||
*/
|
||||
public List<String> getUniformNames(){
|
||||
return uniformNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the texture paths to use
|
||||
* @return The texture paths
|
||||
*/
|
||||
public List<String> getTexturePaths(){
|
||||
return this.texturePaths;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user