play audio on client when server has collision
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
ab4b64942d
commit
ee44f76dcc
BIN
assets/Audio/weapons/collisions/Massive Punch A.wav
Normal file
BIN
assets/Audio/weapons/collisions/Massive Punch A.wav
Normal file
Binary file not shown.
BIN
assets/Audio/weapons/collisions/Massive Punch B.wav
Normal file
BIN
assets/Audio/weapons/collisions/Massive Punch B.wav
Normal file
Binary file not shown.
BIN
assets/Audio/weapons/collisions/Massive Punch C.wav
Normal file
BIN
assets/Audio/weapons/collisions/Massive Punch C.wav
Normal file
Binary file not shown.
@ -18,7 +18,6 @@ Things that feel bad:
|
|||||||
Part of this may be cylinder collidable instead of capsule
|
Part of this may be cylinder collidable instead of capsule
|
||||||
|
|
||||||
|
|
||||||
Sound effect on hit
|
|
||||||
Sound effect on block
|
Sound effect on block
|
||||||
Allow block hotboxes to block damage
|
Allow block hotboxes to block damage
|
||||||
Server packet on damage collision
|
Server packet on damage collision
|
||||||
|
|||||||
@ -516,6 +516,7 @@ Sound effects on footstep
|
|||||||
New sound effects for movement
|
New sound effects for movement
|
||||||
Jump sound effects
|
Jump sound effects
|
||||||
Don't play walking audio when entity is jumping
|
Don't play walking audio when entity is jumping
|
||||||
|
Sound effect on sword hit
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
|||||||
73
net/combat.json
Normal file
73
net/combat.json
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"outputPath" : "./src/main/java/electrosphere/net/parser/",
|
||||||
|
"packageName" : "electrosphere.net.parser",
|
||||||
|
"categories":[
|
||||||
|
{
|
||||||
|
"categoryName" : "Combat",
|
||||||
|
"data" : [
|
||||||
|
{
|
||||||
|
"name" : "entityID",
|
||||||
|
"type" : "FIXED_INT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "receiverEntityID",
|
||||||
|
"type" : "FIXED_INT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "positionX",
|
||||||
|
"type" : "FIXED_DOUBLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "positionY",
|
||||||
|
"type" : "FIXED_DOUBLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "positionZ",
|
||||||
|
"type" : "FIXED_DOUBLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "rotationX",
|
||||||
|
"type" : "FIXED_DOUBLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "rotationY",
|
||||||
|
"type" : "FIXED_DOUBLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "rotationZ",
|
||||||
|
"type" : "FIXED_DOUBLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "rotationW",
|
||||||
|
"type" : "FIXED_DOUBLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "time",
|
||||||
|
"type" : "FIXED_LONG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "hitboxType",
|
||||||
|
"type" : "VAR_STRING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "hurtboxType",
|
||||||
|
"type" : "VAR_STRING"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"messageTypes" : [
|
||||||
|
{
|
||||||
|
"messageName" : "serverReportHitboxCollision",
|
||||||
|
"description" : "Reports to clients that a hitbox collision happened",
|
||||||
|
"data" : [
|
||||||
|
"entityID",
|
||||||
|
"receiverEntityID",
|
||||||
|
"time",
|
||||||
|
"hitboxType",
|
||||||
|
"hurtboxType"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
package electrosphere.audio.collision;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.types.creature.CreatureUtils;
|
||||||
|
import electrosphere.entity.types.item.ItemUtils;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client service to play audio when hitbox collisions happen
|
||||||
|
*/
|
||||||
|
public class HitboxAudioService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default audio files to play. Eventually should probably refactor into service that determines audio based on materials
|
||||||
|
*/
|
||||||
|
static String[] defaultHitboxAudio = new String[]{
|
||||||
|
"Audio/weapons/collisions/Massive Punch A.wav",
|
||||||
|
"Audio/weapons/collisions/Massive Punch B.wav",
|
||||||
|
"Audio/weapons/collisions/Massive Punch C.wav",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The random for selecting which file to play
|
||||||
|
*/
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays an interaction
|
||||||
|
* @param voxelType The voxel type
|
||||||
|
* @param type The interaction type
|
||||||
|
*/
|
||||||
|
public void playAudio(Entity senderEntity, Entity receiverEntity, String hitboxType, String hurtboxType){
|
||||||
|
String audioPath = this.getAudioPath(senderEntity, receiverEntity, hitboxType, hurtboxType);
|
||||||
|
if(audioPath != null){
|
||||||
|
Globals.virtualAudioSourceManager.createVirtualAudioSource(audioPath, VirtualAudioSourceType.CREATURE, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays an interaction at a given position
|
||||||
|
* @param voxelType The voxel type
|
||||||
|
* @param type The interaction type
|
||||||
|
* @param position The position of the audio
|
||||||
|
*/
|
||||||
|
public void playAudioPositional(Entity senderEntity, Entity receiverEntity, String hitboxType, String hurtboxType, Vector3d position){
|
||||||
|
String audioPath = this.getAudioPath(senderEntity, receiverEntity, hitboxType, hurtboxType);
|
||||||
|
if(audioPath != null){
|
||||||
|
Globals.virtualAudioSourceManager.createVirtualAudioSource(audioPath, VirtualAudioSourceType.CREATURE, false, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the audio file to play when the given entities collide
|
||||||
|
* @param senderEntity The entity with the hitbox
|
||||||
|
* @param receiverEntity The entity with the hurtbox
|
||||||
|
* @param hitboxType The hitbox type
|
||||||
|
* @param hurtboxType The hurthox type
|
||||||
|
* @return The audio file to play
|
||||||
|
*/
|
||||||
|
private String getAudioPath(Entity senderEntity, Entity receiverEntity, String hitboxType, String hurtboxType){
|
||||||
|
if(ItemUtils.isWeapon(senderEntity)){
|
||||||
|
if(CreatureUtils.isCreature(receiverEntity)){
|
||||||
|
return this.getWeaponOnCreature();
|
||||||
|
} else {
|
||||||
|
LoggerInterface.loggerEngine.WARNING("Getting audio for unhandled hurtbox collision type!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LoggerInterface.loggerEngine.WARNING("Getting audio for unhandled hitbox collision type!");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the audio to play when a weapon collides with a creature
|
||||||
|
* @return The audio file to play
|
||||||
|
*/
|
||||||
|
private String getWeaponOnCreature(){
|
||||||
|
//return the audio
|
||||||
|
int roll = random.nextInt(defaultHitboxAudio.length);
|
||||||
|
return defaultHitboxAudio[roll];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package electrosphere.client.collision;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.game.data.collidable.HitboxData;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client methods for handling hitbox collisions reported by the server
|
||||||
|
*/
|
||||||
|
public class ClientHitboxCollision {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs client logic for a collision that the server reports
|
||||||
|
* @param position The real-space position of the collision
|
||||||
|
* @param hitboxType The type of hitbox
|
||||||
|
* @param hurtboxType The type of hurtbox
|
||||||
|
*/
|
||||||
|
public static void handleHitboxCollision(Entity senderEntity, Entity receiverEntity, Vector3d position, String hitboxType, String hurtboxType){
|
||||||
|
switch(hitboxType){
|
||||||
|
case HitboxData.HITBOX_TYPE_HIT_CONNECTED:
|
||||||
|
case HitboxData.HITBOX_TYPE_HIT: {
|
||||||
|
switch(hurtboxType){
|
||||||
|
case HitboxData.HITBOX_TYPE_HURT:
|
||||||
|
case HitboxData.HITBOX_TYPE_HURT_CONNECTED: {
|
||||||
|
Globals.hitboxAudioService.playAudio(senderEntity, receiverEntity, hitboxType, hurtboxType);
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
LoggerInterface.loggerEngine.WARNING("Client handling undefined hurtbox type: " + hurtboxType);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
LoggerInterface.loggerEngine.WARNING("Client handling undefined hitbox type: " + hitboxType);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ import org.joml.Vector3f;
|
|||||||
|
|
||||||
import electrosphere.audio.AudioEngine;
|
import electrosphere.audio.AudioEngine;
|
||||||
import electrosphere.audio.VirtualAudioSourceManager;
|
import electrosphere.audio.VirtualAudioSourceManager;
|
||||||
|
import electrosphere.audio.collision.HitboxAudioService;
|
||||||
import electrosphere.audio.movement.MovementAudioService;
|
import electrosphere.audio.movement.MovementAudioService;
|
||||||
import electrosphere.auth.AuthenticationManager;
|
import electrosphere.auth.AuthenticationManager;
|
||||||
import electrosphere.client.fluid.cells.FluidCellManager;
|
import electrosphere.client.fluid.cells.FluidCellManager;
|
||||||
@ -106,6 +107,7 @@ public class Globals {
|
|||||||
public static AudioEngine audioEngine;
|
public static AudioEngine audioEngine;
|
||||||
public static VirtualAudioSourceManager virtualAudioSourceManager;
|
public static VirtualAudioSourceManager virtualAudioSourceManager;
|
||||||
public static MovementAudioService movementAudioService = new MovementAudioService();
|
public static MovementAudioService movementAudioService = new MovementAudioService();
|
||||||
|
public static HitboxAudioService hitboxAudioService = new HitboxAudioService();
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -473,7 +475,9 @@ public class Globals {
|
|||||||
"/Audio/weapons/swordUnsheath1.ogg",
|
"/Audio/weapons/swordUnsheath1.ogg",
|
||||||
"/Audio/weapons/swoosh-03.ogg",
|
"/Audio/weapons/swoosh-03.ogg",
|
||||||
"/Audio/movement/Equip A.wav",
|
"/Audio/movement/Equip A.wav",
|
||||||
"/Audio/movement/landing-on-the-ground-4.wav",
|
"/Audio/weapons/collisions/Massive Punch A.wav",
|
||||||
|
"/Audio/weapons/collisions/Massive Punch B.wav",
|
||||||
|
"/Audio/weapons/collisions/Massive Punch C.wav",
|
||||||
};
|
};
|
||||||
LoggerInterface.loggerStartup.INFO("Loading default audio resources");
|
LoggerInterface.loggerStartup.INFO("Loading default audio resources");
|
||||||
for(String path : audioToInit){
|
for(String path : audioToInit){
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import java.util.concurrent.Semaphore;
|
|||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.net.client.protocol.AuthProtocol;
|
import electrosphere.net.client.protocol.AuthProtocol;
|
||||||
import electrosphere.net.client.protocol.CharacterProtocol;
|
import electrosphere.net.client.protocol.CharacterProtocol;
|
||||||
|
import electrosphere.net.client.protocol.CombatProtocol;
|
||||||
import electrosphere.net.client.protocol.EntityProtocol;
|
import electrosphere.net.client.protocol.EntityProtocol;
|
||||||
import electrosphere.net.client.protocol.InventoryProtocol;
|
import electrosphere.net.client.protocol.InventoryProtocol;
|
||||||
import electrosphere.net.client.protocol.LoreProtocol;
|
import electrosphere.net.client.protocol.LoreProtocol;
|
||||||
@ -16,6 +17,7 @@ import electrosphere.net.client.protocol.SynchronizationProtocol;
|
|||||||
import electrosphere.net.client.protocol.TerrainProtocol;
|
import electrosphere.net.client.protocol.TerrainProtocol;
|
||||||
import electrosphere.net.parser.net.message.AuthMessage;
|
import electrosphere.net.parser.net.message.AuthMessage;
|
||||||
import electrosphere.net.parser.net.message.CharacterMessage;
|
import electrosphere.net.parser.net.message.CharacterMessage;
|
||||||
|
import electrosphere.net.parser.net.message.CombatMessage;
|
||||||
import electrosphere.net.parser.net.message.EntityMessage;
|
import electrosphere.net.parser.net.message.EntityMessage;
|
||||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||||
import electrosphere.net.parser.net.message.LoreMessage;
|
import electrosphere.net.parser.net.message.LoreMessage;
|
||||||
@ -45,6 +47,7 @@ public class MessageProtocol {
|
|||||||
//The individual protocols
|
//The individual protocols
|
||||||
AuthProtocol authProtocol = new AuthProtocol();
|
AuthProtocol authProtocol = new AuthProtocol();
|
||||||
CharacterProtocol characterProtocol = new CharacterProtocol();
|
CharacterProtocol characterProtocol = new CharacterProtocol();
|
||||||
|
CombatProtocol combatProtocol = new CombatProtocol();
|
||||||
EntityProtocol entityProtocol = new EntityProtocol();
|
EntityProtocol entityProtocol = new EntityProtocol();
|
||||||
InventoryProtocol inventoryProtocol = new InventoryProtocol();
|
InventoryProtocol inventoryProtocol = new InventoryProtocol();
|
||||||
LoreProtocol loreProtocol = new LoreProtocol();
|
LoreProtocol loreProtocol = new LoreProtocol();
|
||||||
@ -67,6 +70,9 @@ public class MessageProtocol {
|
|||||||
case CHARACTER_MESSAGE:
|
case CHARACTER_MESSAGE:
|
||||||
result = this.characterProtocol.handleAsyncMessage((CharacterMessage)message);
|
result = this.characterProtocol.handleAsyncMessage((CharacterMessage)message);
|
||||||
break;
|
break;
|
||||||
|
case COMBAT_MESSAGE: {
|
||||||
|
result = this.combatProtocol.handleAsyncMessage((CombatMessage)message);
|
||||||
|
} break;
|
||||||
case ENTITY_MESSAGE:
|
case ENTITY_MESSAGE:
|
||||||
result = this.entityProtocol.handleAsyncMessage((EntityMessage)message);
|
result = this.entityProtocol.handleAsyncMessage((EntityMessage)message);
|
||||||
break;
|
break;
|
||||||
@ -109,6 +115,9 @@ public class MessageProtocol {
|
|||||||
case CHARACTER_MESSAGE:
|
case CHARACTER_MESSAGE:
|
||||||
this.characterProtocol.handleSyncMessage((CharacterMessage)message);
|
this.characterProtocol.handleSyncMessage((CharacterMessage)message);
|
||||||
break;
|
break;
|
||||||
|
case COMBAT_MESSAGE: {
|
||||||
|
this.combatProtocol.handleSyncMessage((CombatMessage)message);
|
||||||
|
} break;
|
||||||
case ENTITY_MESSAGE:
|
case ENTITY_MESSAGE:
|
||||||
this.entityProtocol.handleSyncMessage((EntityMessage)message);
|
this.entityProtocol.handleSyncMessage((EntityMessage)message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
package electrosphere.net.client.protocol;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.client.collision.ClientHitboxCollision;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.net.parser.net.message.CombatMessage;
|
||||||
|
import electrosphere.net.template.ClientProtocolTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client protocl for dealing with combat messages
|
||||||
|
*/
|
||||||
|
public class CombatProtocol implements ClientProtocolTemplate<CombatMessage> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CombatMessage handleAsyncMessage(CombatMessage message) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleSyncMessage(CombatMessage message) {
|
||||||
|
switch(message.getMessageSubtype()){
|
||||||
|
case SERVERREPORTHITBOXCOLLISION: {
|
||||||
|
Vector3d position = new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ());
|
||||||
|
Entity senderEntity = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID());
|
||||||
|
Entity receiverEntity = Globals.clientSceneWrapper.getEntityFromServerId(message.getreceiverEntityID());
|
||||||
|
ClientHitboxCollision.handleHitboxCollision(senderEntity, receiverEntity, position, message.gethitboxType(), message.gethurtboxType());
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,252 @@
|
|||||||
|
package electrosphere.net.parser.net.message;
|
||||||
|
|
||||||
|
import electrosphere.net.parser.util.ByteStreamUtils;
|
||||||
|
import electrosphere.net.parser.net.raw.CircularByteBuffer;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CombatMessage extends NetworkMessage {
|
||||||
|
|
||||||
|
public enum CombatMessageType {
|
||||||
|
SERVERREPORTHITBOXCOLLISION,
|
||||||
|
}
|
||||||
|
|
||||||
|
CombatMessageType messageType;
|
||||||
|
int entityID;
|
||||||
|
int receiverEntityID;
|
||||||
|
double positionX;
|
||||||
|
double positionY;
|
||||||
|
double positionZ;
|
||||||
|
double rotationX;
|
||||||
|
double rotationY;
|
||||||
|
double rotationZ;
|
||||||
|
double rotationW;
|
||||||
|
long time;
|
||||||
|
String hitboxType;
|
||||||
|
String hurtboxType;
|
||||||
|
|
||||||
|
CombatMessage(CombatMessageType messageType){
|
||||||
|
this.type = MessageType.COMBAT_MESSAGE;
|
||||||
|
this.messageType = messageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CombatMessageType getMessageSubtype(){
|
||||||
|
return this.messageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getentityID() {
|
||||||
|
return entityID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setentityID(int entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getreceiverEntityID() {
|
||||||
|
return receiverEntityID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setreceiverEntityID(int receiverEntityID) {
|
||||||
|
this.receiverEntityID = receiverEntityID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getpositionX() {
|
||||||
|
return positionX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setpositionX(double positionX) {
|
||||||
|
this.positionX = positionX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getpositionY() {
|
||||||
|
return positionY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setpositionY(double positionY) {
|
||||||
|
this.positionY = positionY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getpositionZ() {
|
||||||
|
return positionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setpositionZ(double positionZ) {
|
||||||
|
this.positionZ = positionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getrotationX() {
|
||||||
|
return rotationX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setrotationX(double rotationX) {
|
||||||
|
this.rotationX = rotationX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getrotationY() {
|
||||||
|
return rotationY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setrotationY(double rotationY) {
|
||||||
|
this.rotationY = rotationY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getrotationZ() {
|
||||||
|
return rotationZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setrotationZ(double rotationZ) {
|
||||||
|
this.rotationZ = rotationZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getrotationW() {
|
||||||
|
return rotationW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setrotationW(double rotationW) {
|
||||||
|
this.rotationW = rotationW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long gettime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void settime(long time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gethitboxType() {
|
||||||
|
return hitboxType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sethitboxType(String hitboxType) {
|
||||||
|
this.hitboxType = hitboxType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gethurtboxType() {
|
||||||
|
return hurtboxType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sethurtboxType(String hurtboxType) {
|
||||||
|
this.hurtboxType = hurtboxType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stripPacketHeader(CircularByteBuffer byteBuffer){
|
||||||
|
byteBuffer.read(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
|
||||||
|
switch(secondByte){
|
||||||
|
case TypeBytes.COMBAT_MESSAGE_TYPE_SERVERREPORTHITBOXCOLLISION:
|
||||||
|
return CombatMessage.canParseserverReportHitboxCollisionMessage(byteBuffer);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canParseserverReportHitboxCollisionMessage(CircularByteBuffer byteBuffer){
|
||||||
|
int currentStreamLength = byteBuffer.getRemaining();
|
||||||
|
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
|
||||||
|
if(currentStreamLength < 6){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(currentStreamLength < 10){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(currentStreamLength < 18){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int hitboxTypeSize = 0;
|
||||||
|
if(currentStreamLength < 22){
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(18 + 0));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(18 + 1));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(18 + 2));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(18 + 3));
|
||||||
|
hitboxTypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
|
||||||
|
}
|
||||||
|
if(currentStreamLength < 22 + hitboxTypeSize){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int hurtboxTypeSize = 0;
|
||||||
|
if(currentStreamLength < 26){
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 0));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 1));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 2));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 3));
|
||||||
|
hurtboxTypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
|
||||||
|
}
|
||||||
|
if(currentStreamLength < 26 + hitboxTypeSize + hurtboxTypeSize){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CombatMessage parseserverReportHitboxCollisionMessage(CircularByteBuffer byteBuffer){
|
||||||
|
CombatMessage rVal = new CombatMessage(CombatMessageType.SERVERREPORTHITBOXCOLLISION);
|
||||||
|
stripPacketHeader(byteBuffer);
|
||||||
|
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setreceiverEntityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
|
||||||
|
rVal.sethitboxType(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
|
||||||
|
rVal.sethurtboxType(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CombatMessage constructserverReportHitboxCollisionMessage(int entityID,int receiverEntityID,long time,String hitboxType,String hurtboxType){
|
||||||
|
CombatMessage rVal = new CombatMessage(CombatMessageType.SERVERREPORTHITBOXCOLLISION);
|
||||||
|
rVal.setentityID(entityID);
|
||||||
|
rVal.setreceiverEntityID(receiverEntityID);
|
||||||
|
rVal.settime(time);
|
||||||
|
rVal.sethitboxType(hitboxType);
|
||||||
|
rVal.sethurtboxType(hurtboxType);
|
||||||
|
rVal.serialize();
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void serialize(){
|
||||||
|
byte[] intValues = new byte[8];
|
||||||
|
byte[] stringBytes;
|
||||||
|
switch(this.messageType){
|
||||||
|
case SERVERREPORTHITBOXCOLLISION:
|
||||||
|
rawBytes = new byte[2+4+4+8+4+hitboxType.length()+4+hurtboxType.length()];
|
||||||
|
//message header
|
||||||
|
rawBytes[0] = TypeBytes.MESSAGE_TYPE_COMBAT;
|
||||||
|
//entity messaage header
|
||||||
|
rawBytes[1] = TypeBytes.COMBAT_MESSAGE_TYPE_SERVERREPORTHITBOXCOLLISION;
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[2+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(receiverEntityID);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[6+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeLongToBytes(time);
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
rawBytes[10+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(hitboxType.length());
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[18+i] = intValues[i];
|
||||||
|
}
|
||||||
|
stringBytes = hitboxType.getBytes();
|
||||||
|
for(int i = 0; i < hitboxType.length(); i++){
|
||||||
|
rawBytes[22+i] = stringBytes[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(hurtboxType.length());
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[22+hitboxType.length()+i] = intValues[i];
|
||||||
|
}
|
||||||
|
stringBytes = hurtboxType.getBytes();
|
||||||
|
for(int i = 0; i < hurtboxType.length(); i++){
|
||||||
|
rawBytes[26+hitboxType.length()+i] = stringBytes[i];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
serialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@ AUTH_MESSAGE,
|
|||||||
CHARACTER_MESSAGE,
|
CHARACTER_MESSAGE,
|
||||||
INVENTORY_MESSAGE,
|
INVENTORY_MESSAGE,
|
||||||
SYNCHRONIZATION_MESSAGE,
|
SYNCHRONIZATION_MESSAGE,
|
||||||
|
COMBAT_MESSAGE,
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageType type;
|
MessageType type;
|
||||||
@ -393,6 +394,16 @@ SYNCHRONIZATION_MESSAGE,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TypeBytes.MESSAGE_TYPE_COMBAT:
|
||||||
|
secondByte = byteBuffer.peek(1);
|
||||||
|
switch(secondByte){
|
||||||
|
case TypeBytes.COMBAT_MESSAGE_TYPE_SERVERREPORTHITBOXCOLLISION:
|
||||||
|
if(CombatMessage.canParseMessage(byteBuffer,secondByte)){
|
||||||
|
rVal = CombatMessage.parseserverReportHitboxCollisionMessage(byteBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
|
|||||||
@ -14,6 +14,7 @@ Message categories
|
|||||||
public static final byte MESSAGE_TYPE_CHARACTER = 6;
|
public static final byte MESSAGE_TYPE_CHARACTER = 6;
|
||||||
public static final byte MESSAGE_TYPE_INVENTORY = 7;
|
public static final byte MESSAGE_TYPE_INVENTORY = 7;
|
||||||
public static final byte MESSAGE_TYPE_SYNCHRONIZATION = 8;
|
public static final byte MESSAGE_TYPE_SYNCHRONIZATION = 8;
|
||||||
|
public static final byte MESSAGE_TYPE_COMBAT = 9;
|
||||||
/*
|
/*
|
||||||
Entity subcategories
|
Entity subcategories
|
||||||
*/
|
*/
|
||||||
@ -168,5 +169,12 @@ Message categories
|
|||||||
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_SERVERNOTIFYBTREETRANSITION_SIZE = 18;
|
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_SERVERNOTIFYBTREETRANSITION_SIZE = 18;
|
||||||
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE_SIZE = 10;
|
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE_SIZE = 10;
|
||||||
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE_SIZE = 10;
|
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE_SIZE = 10;
|
||||||
|
/*
|
||||||
|
Combat subcategories
|
||||||
|
*/
|
||||||
|
public static final byte COMBAT_MESSAGE_TYPE_SERVERREPORTHITBOXCOLLISION = 0;
|
||||||
|
/*
|
||||||
|
Combat packet sizes
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import electrosphere.engine.Globals;
|
|||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.parser.net.message.AuthMessage;
|
import electrosphere.net.parser.net.message.AuthMessage;
|
||||||
import electrosphere.net.parser.net.message.CharacterMessage;
|
import electrosphere.net.parser.net.message.CharacterMessage;
|
||||||
|
import electrosphere.net.parser.net.message.CombatMessage;
|
||||||
import electrosphere.net.parser.net.message.EntityMessage;
|
import electrosphere.net.parser.net.message.EntityMessage;
|
||||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||||
import electrosphere.net.parser.net.message.LoreMessage;
|
import electrosphere.net.parser.net.message.LoreMessage;
|
||||||
@ -18,6 +19,7 @@ import electrosphere.net.parser.net.message.SynchronizationMessage;
|
|||||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
import electrosphere.net.server.protocol.AuthProtocol;
|
import electrosphere.net.server.protocol.AuthProtocol;
|
||||||
import electrosphere.net.server.protocol.CharacterProtocol;
|
import electrosphere.net.server.protocol.CharacterProtocol;
|
||||||
|
import electrosphere.net.server.protocol.CombatProtocol;
|
||||||
import electrosphere.net.server.protocol.EntityProtocol;
|
import electrosphere.net.server.protocol.EntityProtocol;
|
||||||
import electrosphere.net.server.protocol.InventoryProtocol;
|
import electrosphere.net.server.protocol.InventoryProtocol;
|
||||||
import electrosphere.net.server.protocol.LoreProtocol;
|
import electrosphere.net.server.protocol.LoreProtocol;
|
||||||
@ -43,6 +45,7 @@ public class MessageProtocol {
|
|||||||
//The individual protocols
|
//The individual protocols
|
||||||
AuthProtocol authProtocol = new AuthProtocol();
|
AuthProtocol authProtocol = new AuthProtocol();
|
||||||
CharacterProtocol characterProtocol = new CharacterProtocol();
|
CharacterProtocol characterProtocol = new CharacterProtocol();
|
||||||
|
CombatProtocol combatProtocol = new CombatProtocol();
|
||||||
EntityProtocol entityProtocol = new EntityProtocol();
|
EntityProtocol entityProtocol = new EntityProtocol();
|
||||||
InventoryProtocol inventoryProtocol = new InventoryProtocol();
|
InventoryProtocol inventoryProtocol = new InventoryProtocol();
|
||||||
LoreProtocol loreProtocol = new LoreProtocol();
|
LoreProtocol loreProtocol = new LoreProtocol();
|
||||||
@ -74,6 +77,9 @@ public class MessageProtocol {
|
|||||||
case CHARACTER_MESSAGE:
|
case CHARACTER_MESSAGE:
|
||||||
result = this.characterProtocol.handleAsyncMessage(serverConnectionHandler, (CharacterMessage)message);
|
result = this.characterProtocol.handleAsyncMessage(serverConnectionHandler, (CharacterMessage)message);
|
||||||
break;
|
break;
|
||||||
|
case COMBAT_MESSAGE: {
|
||||||
|
result = this.combatProtocol.handleAsyncMessage(serverConnectionHandler, (CombatMessage)message);
|
||||||
|
} break;
|
||||||
case ENTITY_MESSAGE:
|
case ENTITY_MESSAGE:
|
||||||
result = this.entityProtocol.handleAsyncMessage(serverConnectionHandler, (EntityMessage)message);
|
result = this.entityProtocol.handleAsyncMessage(serverConnectionHandler, (EntityMessage)message);
|
||||||
break;
|
break;
|
||||||
@ -116,6 +122,9 @@ public class MessageProtocol {
|
|||||||
case CHARACTER_MESSAGE:
|
case CHARACTER_MESSAGE:
|
||||||
this.characterProtocol.handleSyncMessage(serverConnectionHandler, (CharacterMessage)message);
|
this.characterProtocol.handleSyncMessage(serverConnectionHandler, (CharacterMessage)message);
|
||||||
break;
|
break;
|
||||||
|
case COMBAT_MESSAGE: {
|
||||||
|
this.combatProtocol.handleSyncMessage(serverConnectionHandler, (CombatMessage)message);
|
||||||
|
} break;
|
||||||
case ENTITY_MESSAGE:
|
case ENTITY_MESSAGE:
|
||||||
this.entityProtocol.handleSyncMessage(serverConnectionHandler, (EntityMessage)message);
|
this.entityProtocol.handleSyncMessage(serverConnectionHandler, (EntityMessage)message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
package electrosphere.net.server.protocol;
|
||||||
|
|
||||||
|
import electrosphere.net.parser.net.message.CombatMessage;
|
||||||
|
import electrosphere.net.server.ServerConnectionHandler;
|
||||||
|
import electrosphere.net.template.ServerProtocolTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server protocol for dealing with combat messages
|
||||||
|
*/
|
||||||
|
public class CombatProtocol implements ServerProtocolTemplate<CombatMessage> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CombatMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, CombatMessage message) {
|
||||||
|
switch(message.getMessageSubtype()){
|
||||||
|
case SERVERREPORTHITBOXCOLLISION: {
|
||||||
|
//silently ignore
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleSyncMessage(ServerConnectionHandler connectionHandler, CombatMessage message) {
|
||||||
|
switch(message.getMessageSubtype()){
|
||||||
|
case SERVERREPORTHITBOXCOLLISION: {
|
||||||
|
//silently ignore
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import org.ode4j.ode.DGeom;
|
|||||||
|
|
||||||
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
|
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
|
||||||
import electrosphere.collision.collidable.Collidable;
|
import electrosphere.collision.collidable.Collidable;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||||
@ -15,6 +16,8 @@ import electrosphere.entity.state.movement.ProjectileTree;
|
|||||||
import electrosphere.entity.types.attach.AttachUtils;
|
import electrosphere.entity.types.attach.AttachUtils;
|
||||||
import electrosphere.entity.types.creature.CreatureUtils;
|
import electrosphere.entity.types.creature.CreatureUtils;
|
||||||
import electrosphere.entity.types.item.ItemUtils;
|
import electrosphere.entity.types.item.ItemUtils;
|
||||||
|
import electrosphere.net.parser.net.message.CombatMessage;
|
||||||
|
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for managing collisions on the server
|
* Callback for managing collisions on the server
|
||||||
@ -55,7 +58,18 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
|||||||
//to make sure you don't stab yourself for instance
|
//to make sure you don't stab yourself for instance
|
||||||
boolean isItem = ItemUtils.isItem(impactorParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
|
boolean isItem = ItemUtils.isItem(impactorParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
|
||||||
Entity hitboxAttachParent = AttachUtils.getParent(impactorParent);
|
Entity hitboxAttachParent = AttachUtils.getParent(impactorParent);
|
||||||
|
|
||||||
|
//tell clients an impact just happened
|
||||||
|
DataCellSearchUtils.getEntityDataCell(receiverParent).broadcastNetworkMessage(
|
||||||
|
CombatMessage.constructserverReportHitboxCollisionMessage(
|
||||||
|
impactorParent.getId(),
|
||||||
|
receiverParent.getId(),
|
||||||
|
Globals.timekeeper.getNumberOfSimFramesElapsed(),
|
||||||
|
impactorShapeStatus.getHitboxData().getType(),
|
||||||
|
receiverShapeStatus.getHitboxData().getType()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
if(isItem){
|
if(isItem){
|
||||||
if(hitboxAttachParent != receiverParent){
|
if(hitboxAttachParent != receiverParent){
|
||||||
int damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
|
int damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
|
||||||
|
|||||||
@ -14,7 +14,8 @@
|
|||||||
"./net/server.json",
|
"./net/server.json",
|
||||||
"./net/character.json",
|
"./net/character.json",
|
||||||
"./net/inventory.json",
|
"./net/inventory.json",
|
||||||
"./net/synchronization.json"
|
"./net/synchronization.json",
|
||||||
|
"./net/combat.json"
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user