Merge pull request 'WIP threading-rework-1' (#95) from threading-rework-1 into master

Reviewed-on: https://git.austinwhoover.com/gitadmin/Renderer/pulls/95
This commit is contained in:
gitadmin 2022-05-05 03:39:39 +00:00
commit b24041f9a8
46 changed files with 1957 additions and 541 deletions

View File

@ -68,6 +68,47 @@
"primaryBone" : "UpperTorso",
"minValue" : -0.2,
"maxValue" : 0.2
},
{
"attributeId" : "TorsoWidth",
"type" : "bone",
"subtype" : "scalex",
"primaryBone" : "UpperTorso",
"minValue" : 0.8,
"maxValue" : 1.2
},
{
"attributeId" : "ShoulderSize",
"type" : "bone",
"subtype" : "scale",
"primaryBone" : "Shoulder.R",
"mirrorBone" : "Shoulder.L",
"minValue" : 0.8,
"maxValue" : 1.2
},
{
"attributeId" : "JawWidth",
"type" : "bone",
"subtype" : "scalex",
"primaryBone" : "Jaw",
"minValue" : 0.8,
"maxValue" : 1.2
},
{
"attributeId" : "JawExtrude",
"type" : "bone",
"subtype" : "posz",
"primaryBone" : "Jaw",
"minValue" : -0.1,
"maxValue" : 0.1
},
{
"attributeId" : "HeadWidth",
"type" : "bone",
"subtype" : "scalex",
"primaryBone" : "Head",
"minValue" : 0.8,
"maxValue" : 1.2
}
],
"movementSystems" : [

File diff suppressed because one or more lines are too long

51
net/character.json Normal file
View File

@ -0,0 +1,51 @@
{
"outputPath" : "./src/main/java/electrosphere/net/parser/",
"packageName" : "electrosphere.net.parser",
"categories":[
{
"categoryName" : "Character",
"data" : [
{
"name" : "data",
"type" : "VAR_STRING"
}
],
"messageTypes" : [
{
"messageName" : "RequestCharacterList",
"data" : []
},
{
"messageName" : "ResponseCharacterList",
"data" : [
"data"
]
},
{
"messageName" : "RequestCreateCharacter",
"data" : [
"data"
]
},
{
"messageName" : "ResponseCreateCharacterSuccess",
"data" : []
},
{
"messageName" : "ResponseCreateCharacterFailure",
"data" : []
},
{
"messageName" : "RequestSpawnCharacter",
"data" : []
},
{
"messageName" : "ResponseSpawnCharacter",
"data" : [
"data"
]
}
]
}
]
}

View File

@ -17,6 +17,10 @@
"name" : "entityID",
"type" : "FIXED_INT"
},
{
"name" : "creatureTemplate",
"type" : "VAR_STRING"
},
{
"name" : "positionX",
"type" : "FIXED_DOUBLE"
@ -94,6 +98,16 @@
"positionZ"
]
},
{
"messageName" : "SpawnCreature",
"data" : [
"entityID",
"creatureTemplate",
"positionX",
"positionY",
"positionZ"
]
},
{
"messageName" : "SetPosition",
"data" : [

View File

@ -2,47 +2,6 @@
"outputPath" : "./src/main/java/electrosphere/net/parser/",
"packageName" : "electrosphere.net.parser",
"categories":[
{
"categoryName" : "Character",
"data" : [
{
"name" : "data",
"type" : "VAR_STRING"
}
],
"messageTypes" : [
{
"messageName" : "RequestCharacterList",
"data" : []
},
{
"messageName" : "ResponseCharacterList",
"data" : [
"data"
]
},
{
"messageName" : "RequestCreateCharacter",
"data" : []
},
{
"messageName" : "ResponseCreateCharacter",
"data" : [
"data"
]
},
{
"messageName" : "RequestSpawnCharacter",
"data" : []
},
{
"messageName" : "ResponseSpawnCharacter",
"data" : [
"data"
]
}
]
},
{
"categoryName" : "Player",
"data" : [

View File

@ -61,11 +61,11 @@
{
"name" : "realLocationX",
"type" : "FIXED_FLOAT"
"type" : "FIXED_DOUBLE"
},
{
"name" : "realLocationY",
"type" : "FIXED_FLOAT"
"type" : "FIXED_DOUBLE"
},

View File

@ -40,6 +40,7 @@ import electrosphere.game.simulation.MicroSimulation;
import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.menu.MenuGenerators;
import electrosphere.menu.MenuGeneratorsMultiplayer;
import electrosphere.menu.WindowStrings;
import electrosphere.menu.WindowUtils;
import electrosphere.net.NetUtils;
@ -64,6 +65,7 @@ import electrosphere.game.server.unit.UnitUtils;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.WidgetUtils;
import electrosphere.renderer.ui.Window;
import electrosphere.util.Utilities;
import java.util.LinkedList;
import java.util.List;
@ -86,6 +88,8 @@ public class LoadingThread extends Thread {
public static final int LOAD_TITLE_MENU = 0;
public static final int LOAD_MAIN_GAME = 1;
public static final int LOAD_ARENA = 2;
public static final int LOAD_CHARACTER_SERVER = 3;
public static final int LOAD_CLIENT_WORLD = 4;
int threadType;
@ -124,99 +128,154 @@ public class LoadingThread extends Thread {
case LOAD_MAIN_GAME:
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true);
//disable menu input
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
//initialize the terrain manager (server only)
// if(Globals.RUN_SERVER){
// initServerGameTerrainManager();
// }
if(Globals.RUN_SERVER){
//TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,0.0f,0);
SaveUtils.loadSave(Globals.currentSaveName);
Globals.dataCellManager = new DataCellManager(Globals.serverWorldData);
//TODO: set spawnpoint
//TODO: Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
//TODO: Globals.dataCellManager = new DataCellManager(Globals.serverWorldData);
//TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,0.0f,0);
SaveUtils.loadSave(Globals.currentSaveName);
Globals.dataCellManager = new DataCellManager(Globals.serverWorldData);
//TODO: set spawnpoint
//TODO: Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
//TODO: Globals.dataCellManager = new DataCellManager(Globals.serverWorldData);
// Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
// Globals.dataCellManager = new DataCellManager(Globals.serverWorldData);
}
LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT);
//init the data of the world
if(Globals.RUN_SERVER){
// initServerGameWorldData();
initDataCellManager();
}
initDataCellManager();
//init authentication
initAuthenticationManager();
//initialize the server thread (server only)
if(Globals.RUN_SERVER){
initServerThread();
initAuthenticationManager();
}
initServerThread();
//initialize the "virtual" objects simulation
if(Globals.RUN_SERVER){
initMacroSimulation();
}
initMacroSimulation();
//initialize the "real" objects simulation
initMicroSimulation();
//initialize the client thread (client)
if(Globals.RUN_CLIENT){
initClientThread();
stallForClientPlayerData();
}
//init client terrain manager
initClientTerrainManager();
//collision engine
initCommonWorldData(Globals.RUN_SERVER);
//initialize the cell manager (client)
//init draw cell manager
initDrawCellManager();
//initialize the basic graphical entities of the world (skybox, camera)
initWorldBaseGraphicalEntities();
//init game specific stuff (ie different skybox colors)
initGameGraphicalEntities();
// while(Globals.clientConnection.getClientProtocol().isLoading()){
// try {
// TimeUnit.MILLISECONDS.sleep(5);
// } catch (InterruptedException ex) {
// }
// }
//set simulations to ready if they exist
setSimulationsToReady();
//log
LoggerInterface.loggerEngine.INFO("[Server]Finished loading main world");
break;
case LOAD_ARENA:
//init server arena terrain manager separately
initServerArenaTerrainManager();
//init the data of the world
initServerArenaWorldData();
//init data cell manager
initDataCellManager();
//init authentication
initAuthenticationManager();
//initialize the server thread (server only)
initServerThread();
//collision engine
initCommonWorldData(Globals.RUN_SERVER);
//init draw cell manager
initDrawCellManager();
//initialize the "virtual" objects simulation
//not really relevant in arena mode
// initMacroSimulation();
//initialize the "real" objects simulation
initMicroSimulation();
//init arena specific stuff (ie different skybox colors)
initArenaGraphicalEntities();
//create arena entities
creatingRandomEntities();
//set simulations to ready if they exist
setSimulationsToReady();
LoggerInterface.loggerEngine.INFO("[Server]Finished loading arena world");
break;
case LOAD_CHARACTER_SERVER:
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true);
//disable menu input
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
//initialize the client thread (client)
initClientThread();
//while we don't know what races are playable, wait
while(Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces().size() == 0){
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException ex) {}
}
//once we have them, bring up the character creation interface
//init character creation window
//eventually should replace with at ui to select an already created character or create a new one
WindowUtils.replaceMainMenuContents(MenuGeneratorsMultiplayer.createMultiplayerCharacterCreationWindow());
//make loading dialog disappear
loadingWindow.setVisible(false);
//make character creation window visible
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), true);
//recapture window
Globals.controlHandler.setShouldRecapture(true);
//log
LoggerInterface.loggerEngine.INFO("[Client]Finished loading character creation menu");
//set menu controls again
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.TITLE_MENU);
break;
case LOAD_CLIENT_WORLD:
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true);
//disable menu input
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
//collision engine
if(!Globals.RUN_SERVER){
initCommonWorldData(Globals.RUN_SERVER);
}
//initialize the "real" objects simulation
initMicroSimulation();
//init client terrain manager
initClientTerrainManager();
//initialize the cell manager (client)
initDrawCellManager();
//initialize the basic graphical entities of the world (skybox, camera)
initWorldBaseGraphicalEntities();
//init arena specific stuff (ie different skybox colors)
if(!Globals.RUN_SERVER){
initArenaGraphicalEntities();
}
//sets micro and macro sims to ready if they exist
if(!Globals.RUN_SERVER){
setSimulationsToReady();
}
//hide cursor
Globals.controlHandler.hideMouse();
//make loading window disappear
loadingWindow.setVisible(false);
//recapture screen
Globals.controlHandler.setShouldRecapture(true);
//set rendering flags to main game mode
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = true;
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = true;
Globals.RENDER_FLAG_RENDER_UI = true;
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
LoggerInterface.loggerEngine.INFO("Finished loading");
LoggerInterface.loggerEngine.INFO("[Client]Finished loading main game");
//set controls state
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.MAIN_GAME);
break;
@ -226,109 +285,6 @@ public class LoadingThread extends Thread {
case LOAD_ARENA:
if(Globals.RUN_CLIENT){
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true);
}
//disable menu input
if(Globals.RUN_CLIENT){
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
}
//init server arena terrain manager separately
initServerArenaTerrainManager();
//init the data of the world
initServerArenaWorldData();
//init data cell manager
if(Globals.RUN_SERVER){
initDataCellManager();
}
//initialize the server thread (server only)
if(Globals.RUN_SERVER){
initServerThread();
initAuthenticationManager();
}
//collision engine
initCommonWorldData(Globals.RUN_SERVER);
//initialize the "virtual" objects simulation
//not really relevant in arena mode
// initMacroSimulation();
//initialize the "real" objects simulation
initMicroSimulation();
//initialize the client thread (client)
if(Globals.RUN_CLIENT){
initClientThread();
stallForClientPlayerData();
}
//init client terrain manager
if(Globals.RUN_CLIENT){
initClientTerrainManager();
}
//initialize the cell manager (client)
if(Globals.RUN_CLIENT){
initDrawCellManager();
}
//initialize the basic graphical entities of the world (skybox, camera)
initWorldBaseGraphicalEntities();
//init arena specific stuff (ie different skybox colors)
initArenaGraphicalEntities();
creatingRandomEntities();
// while(Globals.clientConnection.getClientProtocol().isLoading()){
// try {
// TimeUnit.MILLISECONDS.sleep(5);
// } catch (InterruptedException ex) {
// }
// }
setSimulationsToReady();
//hide cursor
if(Globals.RUN_CLIENT){
Globals.controlHandler.hideMouse();
loadingWindow.setVisible(false);
Globals.controlHandler.setShouldRecapture(true);
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = true;
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = true;
Globals.RENDER_FLAG_RENDER_UI = true;
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
}
LoggerInterface.loggerEngine.INFO("Finished loading");
if(Globals.RUN_CLIENT){
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.MAIN_GAME);
}
break;
}
lock.release();
}
@ -406,7 +362,7 @@ public class LoadingThread extends Thread {
static void initServerArenaWorldData(){
Globals.serverWorldData = ServerWorldData.createArenaWorld();
Globals.spawnPoint = new Vector3f(1,0.1f,1);
Globals.spawnPoint = new Vector3d(1,0.1,1);
// Globals.serverTerrainManager.getChunk(0, 0).addModification(new TerrainModification(0,0,5,5,5));
}
@ -415,17 +371,19 @@ public class LoadingThread extends Thread {
}
static void initCommonWorldData(boolean FLAG_INIT_SERVER){
if(FLAG_INIT_SERVER){
Globals.commonWorldData = new CommonWorldData(Globals.serverWorldData, Globals.serverTerrainManager);
if(Globals.macroSimulation != null){
Town startTown = Globals.macroData.getTowns().get(0);
Vector2i firstPos = startTown.getPositions().get(0);
double startX = firstPos.x * Globals.serverTerrainManager.getChunkWidth();
double startZ = firstPos.y * Globals.serverTerrainManager.getChunkWidth();
Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ);
if(Globals.commonWorldData == null){
if(FLAG_INIT_SERVER){
Globals.commonWorldData = new CommonWorldData(Globals.serverWorldData, Globals.serverTerrainManager);
if(Globals.macroSimulation != null){
Town startTown = Globals.macroData.getTowns().get(0);
Vector2i firstPos = startTown.getPositions().get(0);
double startX = firstPos.x * Globals.serverTerrainManager.getChunkWidth();
double startZ = firstPos.y * Globals.serverTerrainManager.getChunkWidth();
Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ);
}
} else {
Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager);
}
} else {
Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager);
}
}
@ -458,55 +416,52 @@ public class LoadingThread extends Thread {
Thread clientThread = null;
if(Globals.RUN_CLIENT){
Globals.clientConnection = new ClientNetworking(NetUtils.getAddress(),NetUtils.getPort());
System.out.println(Globals.clientConnection.socket);
clientThread = new Thread(Globals.clientConnection);
clientThread.start();
}
}
static void stallForClientPlayerData(){
// while(!Globals.clientPlayerData.hasLoaded()){
// try {
// TimeUnit.MILLISECONDS.sleep(5);
// } catch (InterruptedException ex) {
// ex.printStackTrace();
// }
// }
}
static void initDrawCellManager(){
Globals.drawCellManager = new DrawCellManager(
Globals.clientWorldData,
Globals.clientTerrainManager,
Globals.clientPlayerData.getWorldPositionX(),
Globals.clientPlayerData.getWorldPositionY()
// Globals.terrainManager.getDynamicInterpolationRatio(),
// Globals.terrainManager.getRandomDampener()
);
while(Globals.drawCellManager.containsInvalidCell()){
// Globals.drawCellManager.updateInvalidCell();
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
}
// System.out.println("invalid cell");
if(Globals.drawCellManager == null){
Globals.drawCellManager = new DrawCellManager(
Globals.commonWorldData,
Globals.clientTerrainManager,
Globals.clientPlayerData.getWorldPositionX(),
Globals.clientPlayerData.getWorldPositionY()
// Globals.terrainManager.getDynamicInterpolationRatio(),
// Globals.terrainManager.getRandomDampener()
);
} else {
//set our draw cell manager to actually generate drawable chunks
Globals.drawCellManager.setGenerateDrawables(true);
}
while(Globals.drawCellManager.containsUndrawableCell()){
// Globals.drawCellManager.makeCellDrawable();
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
//wait for all the terrain data to arrive
if(Globals.RUN_CLIENT){
while(Globals.drawCellManager.containsInvalidCell()){
// Globals.drawCellManager.updateInvalidCell();
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
}
// System.out.println("invalid cell");
}
// System.out.println("undrawable");
}
while(Globals.drawCellManager.containsPhysicsNeedingCell()){
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
while(Globals.drawCellManager.containsUndrawableCell()){
// Globals.drawCellManager.makeCellDrawable();
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
}
// System.out.println("undrawable");
}
while(Globals.drawCellManager.containsPhysicsNeedingCell()){
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
}
}
}
System.out.println("Draw Cell Manager ready");
@ -612,7 +567,9 @@ public class LoadingThread extends Thread {
static void initMicroSimulation(){
Globals.microSimulation = new MicroSimulation();
if(Globals.microSimulation == null){
Globals.microSimulation = new MicroSimulation();
}
}
static void setSimulationsToReady(){

View File

@ -45,6 +45,7 @@ public class EntityDataStrings {
public static final String ROTATOR_TREE = "rotatorTree";
public static final String JUMP_TREE = "jumpTree";
public static final String FALL_TREE = "fallTree";
public static final String CREATURE_TEMPLATE = "creatureTemplate";
/*

View File

@ -78,6 +78,20 @@ public class EntityUtils {
Globals.entityManager.registerUIEntity(rVal);
return rVal;
}
/**
* Spawns an entity that has a position in the world, but isn't necessarily drawable
* @return the entity
*/
public static Entity spawnSpatialEntity(){
Entity rVal = new Entity();
// rVal.putData(EntityDataStrings.DATA_STRING_MODEL_PATH, modelPath);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaternionf().identity());
rVal.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
Globals.entityManager.registerEntity(rVal);
return rVal;
}
public static void cleanUpDrawableEntity(Entity e){
if(e != null){

View File

@ -174,11 +174,11 @@ public class CollisionObjUtils {
return (CollisionObject)e.getData(EntityDataStrings.PHYSICS_COLLISION_BODY);
}
public static void positionCharacter(Entity e, Vector3f position){
public static void positionCharacter(Entity e, Vector3d position){
EntityUtils.getPosition(e).set(position);
Quaternionf rotation = EntityUtils.getRotation(e);
CollisionObject body = getCollisionBody(e);
PhysicsUtils.setRigidBodyTransform(position, rotation, body);
PhysicsUtils.setRigidBodyTransform(new Vector3f((float)position.x,(float)position.y,(float)position.z), rotation, body);
}
public static Collidable getCollidable(Entity e){

View File

@ -0,0 +1,64 @@
package electrosphere.entity.types.creature;
import java.util.HashMap;
import java.util.Map;
public class CreatureTemplate {
String creatureType;
Map<String,CreatureTemplateAttributeValue> attributeMap = new HashMap<String,CreatureTemplateAttributeValue>();
public CreatureTemplate(String creatureType){
this.creatureType = creatureType;
}
public void putValue(String attributeName, float value){
attributeMap.put(attributeName,new CreatureTemplateAttributeValue(value));
}
public void putValue(String attributeName, String value){
attributeMap.put(attributeName,new CreatureTemplateAttributeValue(value));
}
public CreatureTemplateAttributeValue getValue(String attributeName){
return attributeMap.get(attributeName);
}
public String getCreatureType(){
return creatureType;
}
public class CreatureTemplateAttributeValue {
String variantId;
float value;
public CreatureTemplateAttributeValue(float value){
this.value = value;
}
public CreatureTemplateAttributeValue(String variantId){
this.variantId = variantId;
}
public float getValue(){
return value;
}
public String getVariantId(){
return variantId;
}
public void setValue(float value){
this.value = value;
}
public void setVariantId(String variantId){
this.variantId = variantId;
}
}
}

View File

@ -54,6 +54,7 @@ import electrosphere.renderer.actor.ActorStaticMorph;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.light.PointLight;
import electrosphere.util.ModelLoader;
import electrosphere.util.Utilities;
import java.util.LinkedList;
import java.util.List;
@ -88,7 +89,7 @@ public class CreatureUtils {
// return rVal;
// }
public static Entity spawnBasicCreature(String type){
public static Entity spawnBasicCreature(String type, CreatureTemplate template){
CreatureType rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type);
Entity rVal = EntityUtils.spawnDrawableEntity(rawType.getModelPath());
Actor creatureActor = EntityUtils.getActor(rVal);
@ -195,7 +196,7 @@ public class CreatureUtils {
}
//round out end of move system
rVal.putData(EntityDataStrings.DATA_STRING_MOVEMENT_BT, moveTree);
rVal.putData(EntityDataStrings.DATA_STRING_FACING_VECTOR, new Vector3f(0,0,0));
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_MAX_NATURAL_VELOCITY, groundMovementSystem.getMaxVelocity());
rVal.putData(EntityDataStrings.DATA_STRING_ACCELERATION, groundMovementSystem.getAcceleration());
rVal.putData(EntityDataStrings.DATA_STRING_VELOCITY, 0f);
@ -291,10 +292,28 @@ public class CreatureUtils {
//variants
if(rawType.getVisualAttributes() != null){
ActorStaticMorph staticMorph = null;
CreatureTemplate storedTemplate = new CreatureTemplate(rawType.getCreatureId());
for(VisualAttribute attributeType : rawType.getVisualAttributes()){
if(attributeType.getType().equals("remesh")){
if(attributeType.getVariants() != null && attributeType.getVariants().size() > 0){
AttributeVariant variant = attributeType.getVariants().get(0);
//if the template isn't null, try to find the variant from the template in the variant list
//if the variant is found, set the variable "variant" to the searched for variant
if(template != null && template.getValue(attributeType.getAttributeId()) != null){
String variantId = template.getValue(attributeType.getAttributeId()).getVariantId();
for(AttributeVariant searchVariant : attributeType.getVariants()){
if(searchVariant.getId().equals(variantId)){
variant = searchVariant;
//if we find the variant, store in on-creature template as well
storedTemplate.putValue(attributeType.getAttributeId(), variantId);
break;
}
}
}
//make sure stored template contains creature data
if(storedTemplate.getValue(attributeType.getAttributeId())==null){
storedTemplate.putValue(attributeType.getAttributeId(), attributeType.getVariants().get(0).getId());
}
// attributeType.getAttributeId();
// variant.getId();
rVal.putData(EntityDataStrings.CREATURE_ATTRIBUTE_VARIANT + attributeType.getAttributeId(), variant.getId());
@ -311,12 +330,31 @@ public class CreatureUtils {
}
if(attributeType.getPrimaryBone() != null && staticMorph.getBoneTransforms(attributeType.getPrimaryBone()) == null){
staticMorph.initBoneTransforms(attributeType.getPrimaryBone());
//if the template isn't null, set the value of the morph
if(template != null && template.getValue(attributeType.getAttributeId()) != null){
float templateValue = template.getValue(attributeType.getAttributeId()).getValue();
staticMorph.updateValue(attributeType.getSubtype(), attributeType.getPrimaryBone(), templateValue);
}
}
if(attributeType.getMirrorBone() != null && staticMorph.getBoneTransforms(attributeType.getMirrorBone()) == null){
staticMorph.initBoneTransforms(attributeType.getMirrorBone());
//if the template isn't null, set the value of the morph
if(template != null && template.getValue(attributeType.getAttributeId()) != null){
float templateValue = template.getValue(attributeType.getAttributeId()).getValue();
staticMorph.updateValue(attributeType.getSubtype(), attributeType.getMirrorBone(), templateValue);
}
}
//make sure stored template contains creature data
if(template != null && template.getValue(attributeType.getAttributeId()) != null) {
storedTemplate.putValue(attributeType.getAttributeId(), template.getValue(attributeType.getAttributeId()).getValue());
} else {
float midpoint = (attributeType.getMaxValue() - attributeType.getMinValue())/2.0f + attributeType.getMinValue();
storedTemplate.putValue(attributeType.getAttributeId(), midpoint);
}
}
}
//store template on creature
CreatureUtils.setCreatureTemplate(rVal, storedTemplate);
}
//rotator system
if(rawType.getRotatorSystem() != null){
@ -345,7 +383,7 @@ public class CreatureUtils {
Globals.entityManager.registerCreatureEntity(rVal);
rVal.putData(EntityDataStrings.DATA_STRING_CREATURE_IS_CREATURE, true);
rVal.putData(EntityDataStrings.DATA_STRING_CREATURE_TYPE, type);
rVal.putData(EntityDataStrings.DATA_STRING_FACING_VECTOR, new Vector3d(0,0,1));
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
return rVal;
}
@ -354,7 +392,13 @@ public class CreatureUtils {
int id = creature.getId();
String type = CreatureUtils.getType(creature);
Vector3d position = EntityUtils.getPosition(creature);
NetworkMessage message = EntityMessage.constructCreateMessage(id, EntityDataStrings.ENTITY_CATEGORY_CREATURE, type, (float)position.x, (float)position.y, (float)position.z);
NetworkMessage message = EntityMessage.constructSpawnCreatureMessage(
id,
Utilities.stringify(CreatureUtils.getCreatureTemplate(creature)),
(float)position.x,
(float)position.y,
(float)position.z);
// NetworkMessage message = EntityMessage.constructCreateMessage(id, EntityDataStrings.ENTITY_CATEGORY_CREATURE, type, (float)position.x, (float)position.y, (float)position.z);
player.addMessage(message);
if(CreatureUtils.hasControllerPlayerId(creature)){
LoggerInterface.loggerNetworking.INFO("Sending controller packets");
@ -442,6 +486,14 @@ public class CreatureUtils {
return (SprintTree)e.getData(EntityDataStrings.SPRINT_TREE);
}
public static void setCreatureTemplate(Entity e, CreatureTemplate template){
e.putData(EntityDataStrings.CREATURE_TEMPLATE, template);
}
public static CreatureTemplate getCreatureTemplate(Entity e){
return (CreatureTemplate)e.getData(EntityDataStrings.CREATURE_TEMPLATE);
}
public static void repositionCreature(Entity creature, Vector3d position){
//if server, get current server data cell
@ -465,7 +517,8 @@ public class CreatureUtils {
}
}
//reposition entity
CollisionObjUtils.positionCharacter(creature, new Vector3f(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z));
// CreatureUtils.repositionCreature(creature, Globals.spawnPoint);
CollisionObjUtils.positionCharacter(creature, Globals.spawnPoint);
}

View File

@ -125,6 +125,13 @@ public class DrawCell {
}
public void generatePhysics(){
//if we're in no-graphics mode, need to generate the entity
if(modelEntity == null){
modelEntity = EntityUtils.spawnSpatialEntity();
modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
EntityUtils.getPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellY * dynamicInterpolationRatio));
}
//then actually perform the attach
physicsObject = PhysicsUtils.attachTerrainRigidBody(modelEntity,heightmap);
Globals.collisionEngine.registerPhysicsEntity(modelEntity);
// System.out.println("generate physics");

View File

@ -2,7 +2,9 @@ package electrosphere.game.client.cells;
import electrosphere.game.client.terrain.manager.ClientTerrainManager;
import electrosphere.game.server.terrain.manager.ServerTerrainManager;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.renderer.ShaderProgram;
@ -54,22 +56,25 @@ public class DrawCellManager {
int worldBoundDiscreteMax = 0;
//metadata about the game world
ClientWorldData clientWorldData;
CommonWorldData commonWorldData;
//client terrain manager
ClientTerrainManager clientTerrainManager;
// ClientTerrainManager clientTerrainManager;
//ready to start updating?
boolean update = false;
//controls whether we try to generate the drawable entities
//we want this to be false when in server-only mode
boolean generateDrawables = false;
public DrawCellManager(ClientWorldData clientWorldData, ClientTerrainManager clientTerrainManager, int discreteX, int discreteY){
this.clientWorldData = clientWorldData;
worldBoundDiscreteMax = (int)(this.clientWorldData.getWorldBoundMax().x / this.clientWorldData.getDynamicInterpolationRatio() * 1.0f);
this.clientTerrainManager = clientTerrainManager;
this.miniCellWidth = miniCellWidth;
public DrawCellManager(CommonWorldData commonWorldData, ClientTerrainManager clientTerrainManager, int discreteX, int discreteY){
this.commonWorldData = commonWorldData;
worldBoundDiscreteMax = (int)(commonWorldData.getWorldBoundMin().x / commonWorldData.getDynamicInterpolationRatio() * 1.0f);
// this.clientTerrainManager = clientTerrainManager;
cells = new DrawCell[drawRadius * 2 + 1][drawRadius * 2 + 1];
valid = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
drawable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
@ -148,17 +153,17 @@ public class DrawCellManager {
if(
currentCellX >= 0 &&
currentCellX < clientWorldData.getWorldDiscreteSize() &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < clientWorldData.getWorldDiscreteSize()
currentCellY < commonWorldData.getWorldDiscreteSize()
){
if(clientTerrainManager.containsHeightmapAtDiscretePoint(currentCellX, currentCellY)){
if(containsHeightmapAtDiscretePoint(currentCellX, currentCellY)){
cells[targetX][targetY] = DrawCell.generateTerrainCell(
currentCellX,
currentCellY,
clientTerrainManager.getHeightmapAtPoint(currentCellX, currentCellY),
clientTerrainManager.getTextureMapAtPoint(currentCellX, currentCellY),
clientWorldData.getDynamicInterpolationRatio(),
getHeightmapAtPoint(currentCellX, currentCellY),
getTextureMapAtPoint(currentCellX, currentCellY),
commonWorldData.getDynamicInterpolationRatio(),
program
);
valid[targetX][targetY] = true;
@ -207,9 +212,9 @@ public class DrawCellManager {
int currentCellY = cellY - drawRadius + targetY;
if(
currentCellX >= 0 &&
currentCellX < clientWorldData.getWorldDiscreteSize() &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < clientWorldData.getWorldDiscreteSize()
currentCellY < commonWorldData.getWorldDiscreteSize()
){
//physics radius calculation
// if(Math.abs(physicsRadius + 1 - targetX) < physicsRadius && Math.abs(physicsRadius + 1 - targetY) < physicsRadius){
@ -217,8 +222,8 @@ public class DrawCellManager {
// }
//calculation for stride
int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius));//Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){
int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){
stride = stride + 1;
}
//make drawable entity
@ -251,16 +256,16 @@ public class DrawCellManager {
int currentCellY = cellY - drawRadius + targetY;
if(
currentCellX >= 0 &&
currentCellX < clientWorldData.getWorldDiscreteSize() &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < clientWorldData.getWorldDiscreteSize()
currentCellY < commonWorldData.getWorldDiscreteSize()
){
// if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){
// needsPhysics[targetX][targetY] = true;
// }
int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius)); //Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){
int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){
stride = stride + 1;
}
cells[targetX][targetY].generateDrawableEntity(stride);
@ -289,7 +294,7 @@ public class DrawCellManager {
public boolean containsUndrawableCell(){
for(int x = 0;x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(!drawable[x][y]){
if(!drawable[x][y] && this.generateDrawables){
return true;
}
}
@ -300,7 +305,7 @@ public class DrawCellManager {
public boolean containsUpdateableCell(){
for(int x = 0;x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(updateable[x][y]){
if(updateable[x][y] && this.generateDrawables){
return true;
}
}
@ -343,9 +348,9 @@ public class DrawCellManager {
int currentCellY = cellY - physicsRadius + targetY;
if(
currentCellX >= 0 &&
currentCellX < clientWorldData.getWorldDiscreteSize() &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < clientWorldData.getWorldDiscreteSize()
currentCellY < commonWorldData.getWorldDiscreteSize()
){
// if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){
// needsPhysics[targetX][targetY] = true;
@ -530,7 +535,7 @@ public class DrawCellManager {
public int transformRealSpaceToCellSpace(double input){
return (int)(input / clientWorldData.getDynamicInterpolationRatio());
return (int)(input / commonWorldData.getDynamicInterpolationRatio());
}
@ -647,6 +652,46 @@ public class DrawCellManager {
public boolean coordsInPhysicsSpace(int worldX, int worldY){
return worldX <= cellX + physicsRadius && worldX >= cellX - physicsRadius && worldY <= cellY + physicsRadius && worldY >= cellY - physicsRadius;
}
public void setGenerateDrawables(boolean generate){
this.generateDrawables = generate;
}
boolean containsHeightmapAtDiscretePoint(int currentCellX, int currentCellY){
if(Globals.clientTerrainManager != null){
return Globals.clientTerrainManager.containsHeightmapAtDiscretePoint(currentCellX, currentCellY);
}
return true;
}
float[][] getHeightmapAtPoint(int currentCellX, int currentCellY){
if(Globals.clientTerrainManager != null){
return Globals.clientTerrainManager.getHeightmapAtPoint(currentCellX, currentCellY);
}
return Globals.serverTerrainManager.getChunk(currentCellX, currentCellY).getHeightMap();
}
float[][] getTextureMapAtPoint(int currentCellX, int currentCellY){
if(Globals.clientTerrainManager != null){
return Globals.clientTerrainManager.getTextureMapAtPoint(currentCellX,currentCellY);
} else {
//hacky fix to +2 to this, I think the interpolation ratio was different for server/client data
//now that we're merging/ambiguous within this class, it's out of bounds-ing unless I +2
//TODO: investigate
float[][] rVal = new float[commonWorldData.getDynamicInterpolationRatio() + 2][commonWorldData.getDynamicInterpolationRatio() + 2];
rVal[1][1] = 1;
rVal[2][1] = 1;
rVal[3][1] = 1;
rVal[4][1] = 1;
rVal[5][1] = 1;
rVal[5][2] = 1;
rVal[6][1] = 1;
rVal[6][2] = 1;
return rVal;
}
}
// public

View File

@ -79,4 +79,29 @@ public class CommonWorldData {
return serverWorldData.convertRealToChunkSpace(real);
}
}
public int getDynamicInterpolationRatio(){
if(clientWorldData != null){
return clientWorldData.getDynamicInterpolationRatio();
} else {
return serverWorldData.getDynamicInterpolationRatio();
}
}
public int getWorldDiscreteSize(){
if(clientWorldData != null){
return clientWorldData.getWorldDiscreteSize();
} else {
return serverWorldData.getWorldSizeDiscrete();
}
}
public float getRandomDampener(){
if(clientWorldData != null){
return clientWorldData.getRandomDampener();
} else {
return serverWorldData.getRandomDampener();
}
}
}

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
public class CreatureTypeLoader {
@ -11,6 +12,8 @@ public class CreatureTypeLoader {
List<String> playableRaceNames = new LinkedList<String>();
Semaphore playableRaceLock = new Semaphore(1);
public void putCreature(String name, CreatureType type){
creatureMap.put(name,type);
}
@ -24,7 +27,21 @@ public class CreatureTypeLoader {
}
public List<String> getPlayableRaces(){
return playableRaceNames;
List<String> races = null;
playableRaceLock.acquireUninterruptibly();
races = playableRaceNames;
playableRaceLock.release();
return races;
}
public void clearPlayableRaces(){
playableRaceNames.clear();
}
public void loadPlayableRaces(List<String> races){
playableRaceLock.acquireUninterruptibly();
playableRaceNames = races;
playableRaceLock.release();
}

View File

@ -4,11 +4,14 @@ import java.util.List;
public class VisualAttribute {
public static final String TYPE_REMESH = "remesh";
public static final String TYPE_BONE = "bone";
String attributeId;
String type; //remesh or bone
String subtype; //if bone: yaw,pitch,roll,scalex,scaley,scalez,offx,offy,offz,offl
//offl = length offset, scaling along the offset from the previous bone (as if to elongate a limb)
//likely not updated, check out ActorStaticMorph for more details on up to date docs if out of date
List<AttributeVariant> variants;
float minValue;
float maxValue;

View File

@ -7,6 +7,8 @@ import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.server.ai.creature.MillAbout;
import org.joml.Vector3d;
import org.joml.Vector3f;
/**
@ -16,8 +18,8 @@ import org.joml.Vector3f;
public class UnitUtils {
public static void spawnTextGoblin(float posX, float posY, float posZ){
Entity goblin = CreatureUtils.spawnBasicCreature("Goblin");
CollisionObjUtils.positionCharacter(goblin, new Vector3f(posX, posY, posZ));
Entity goblin = CreatureUtils.spawnBasicCreature("Goblin",null);
CollisionObjUtils.positionCharacter(goblin, new Vector3d(posX, posY, posZ));
EntityUtils.getScale(goblin).set(0.005f);
//give evil goblin sword
Entity goblinSword = ItemUtils.spawnBasicItem("Katana");

View File

@ -70,6 +70,7 @@ import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.joml.Matrix4f;
import org.joml.Vector3d;
import org.joml.Vector3f;
import electrosphere.util.ModelLoader;
import electrosphere.util.Utilities;
@ -196,6 +197,7 @@ public class Globals {
public static int WINDOW_TITLE_BAR_HEIGHT = 0;
public static float verticalFOV = 90;
public static float aspectRatio = 2.0f;
//matrices for drawing models
public static Matrix4f viewMatrix = new Matrix4f();
@ -248,7 +250,7 @@ public class Globals {
//terrain manager
// public static boolean LOAD_TERRAIN = true;
public static ServerTerrainManager serverTerrainManager;
public static Vector3f spawnPoint = new Vector3f(0,0,0);
public static Vector3d spawnPoint = new Vector3d(0,0,0);
//manages all models loaded into memory
public static AssetManager assetManager;
@ -286,7 +288,7 @@ public class Globals {
public static ArrayList<Vector3f> skyboxColors;
//thread for loading different game states
public static LoadingThread loadingThread;
public static List<LoadingThread> loadingThreadsList = new LinkedList<LoadingThread>();
//manager for all widgets currently being drawn to screen
public static ElementManager elementManager;

View File

@ -191,11 +191,14 @@ public class Main {
//fire off a loading thread for the title menus/screen
LoggerInterface.loggerStartup.INFO("Fire off loading thread");
if(Globals.RUN_CLIENT){
Globals.loadingThread = new LoadingThread(LoadingThread.LOAD_TITLE_MENU);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_TITLE_MENU);
Globals.loadingThreadsList.add(serverThread);
serverThread.start();
} else {
Globals.loadingThread = new LoadingThread(LoadingThread.LOAD_ARENA);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_ARENA);
Globals.loadingThreadsList.add(clientThread);
clientThread.start();
}
Globals.loadingThread.start();
//recapture the screen for rendering
if(Globals.RUN_CLIENT){

View File

@ -33,6 +33,7 @@ import electrosphere.renderer.ui.ClickableElement.ClickEventCallback;
import electrosphere.renderer.ui.DraggableElement.DragEventCallback;
import electrosphere.renderer.ui.FocusableElement.FocusEventCallback;
import electrosphere.renderer.ui.NavigableElement.NavigationEventCallback;
import electrosphere.renderer.ui.ValueElement.ValueChangeEventCallback;
import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.Div;
import electrosphere.renderer.ui.elements.ImagePanel;
@ -44,6 +45,7 @@ import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.DragEvent;
import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.NavigationEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.renderer.ui.form.FormElement;
import java.util.List;
@ -74,10 +76,11 @@ public class MenuGenerators {
singleplayerButton.addChild(singleplayerLabel);
rVal.addChild(singleplayerButton);
singleplayerButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
Globals.loadingThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
Globals.loadingThreadsList.add(clientThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
Globals.loadingThread.start();
clientThread.start();
return false;
}});
@ -99,10 +102,14 @@ public class MenuGenerators {
arenaButton.addChild(arenaLabel);
rVal.addChild(arenaButton);
arenaButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
Globals.loadingThread = new LoadingThread(LoadingThread.LOAD_ARENA);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
Globals.loadingThreadsList.add(clientThread);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_ARENA);
Globals.loadingThreadsList.add(serverThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
Globals.loadingThread.start();
clientThread.start();
serverThread.start();
return false;
}});
@ -131,6 +138,7 @@ public class MenuGenerators {
return rVal;
}
//Used when we're displaying loading window to make main menu invisible
public static Element createEmptyMainMenu(){
Div rVal = new Div();
return rVal;
@ -152,10 +160,14 @@ public class MenuGenerators {
rVal.addChild(selectButton);
selectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
if(SaveUtils.worldHasSave(saveName.toLowerCase())){
Globals.loadingThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
Globals.loadingThreadsList.add(clientThread);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
Globals.loadingThreadsList.add(serverThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
Globals.loadingThread.start();
clientThread.start();
serverThread.start();
} else {
Globals.currentSaveName = saveName.toLowerCase();
SaveUtils.loadTerrainAndCreateWorldData();
@ -282,10 +294,14 @@ public class MenuGenerators {
hostButton.addChild(hostLabel);
rVal.addChild(hostButton);
hostButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
Globals.loadingThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
Globals.loadingThreadsList.add(clientThread);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
Globals.loadingThreadsList.add(serverThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
Globals.loadingThread.start();
clientThread.start();
serverThread.start();
return false;
}});
@ -348,10 +364,11 @@ public class MenuGenerators {
connectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
NetUtils.setAddress(addressInput.getText());
NetUtils.setPort(Integer.parseInt(portInput.getText()));
Globals.loadingThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
Globals.loadingThreadsList.add(clientThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = false;
Globals.loadingThread.start();
clientThread.start();
return false;
}});
@ -763,68 +780,14 @@ public class MenuGenerators {
int posY = offset * 350 + 100;
if(attribute.getType().equals("bone")){
Slider attributeSlider = new Slider(50,posY,400,100,new Vector3f(0.1f,0.1f,0.1f),new Vector3f(1.0f,0,0));
attributeSlider.setOnValueChange(new Slider.OnSliderChangeCallback() {public void onChange(float value) {
attributeSlider.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event) {
float value = event.getAsFloat();
float minVal = attribute.getMinValue();
float range = attribute.getMaxValue() - minVal;
float actualValue = minVal + range * value;
switch(attribute.getSubtype()){
case "yaw":
staticMorph.setYaw(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setYaw(attribute.getMirrorBone(), -actualValue);
}
break;
case "pitch":
staticMorph.setPitch(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setPitch(attribute.getMirrorBone(), -actualValue);
}
break;
case "roll":
staticMorph.setRoll(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setRoll(attribute.getMirrorBone(), -actualValue);
}
break;
case "scalex":
staticMorph.setScaleX(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setScaleX(attribute.getMirrorBone(), -actualValue);
}
break;
case "scaley":
staticMorph.setScaleY(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setScaleY(attribute.getMirrorBone(), -actualValue);
}
break;
case "scalez":
staticMorph.setScaleZ(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setScaleZ(attribute.getMirrorBone(), -actualValue);
}
break;
case "offx":
staticMorph.setOffsetX(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setOffsetX(attribute.getMirrorBone(), -actualValue);
}
break;
case "offy":
staticMorph.setOffsetY(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setOffsetY(attribute.getMirrorBone(), -actualValue);
}
break;
case "offz":
staticMorph.setOffsetZ(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setOffsetZ(attribute.getMirrorBone(), -actualValue);
}
break;
case "offl":
//TODO
break;
staticMorph.updateValue(attribute.getSubtype(), attribute.getPrimaryBone(), event.getAsFloat());
if(attribute.getMirrorBone() != null){
staticMorph.updateValue(attribute.getSubtype(), attribute.getMirrorBone(), event.getAsFloat());
}
}});
scrollable.addChild(attributeSlider);

View File

@ -0,0 +1,218 @@
package electrosphere.menu;
import java.util.LinkedList;
import java.util.List;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.visualattribute.AttributeVariant;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorStaticMorph;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.actor.ActorStaticMorph.StaticMorphTransforms;
import electrosphere.renderer.anim.Animation;
import electrosphere.renderer.ui.ClickableElement;
import electrosphere.renderer.ui.Element;
import electrosphere.renderer.ui.ValueElement.ValueChangeEventCallback;
import electrosphere.renderer.ui.elements.ActorPanel;
import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.ImagePanel;
import electrosphere.renderer.ui.elements.Label;
import electrosphere.renderer.ui.elements.ScrollableContainer;
import electrosphere.renderer.ui.elements.Slider;
import electrosphere.renderer.ui.elements.StringCarousel;
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.renderer.ui.form.FormElement;
import electrosphere.util.Utilities;
public class MenuGeneratorsMultiplayer {
public static Element createMultiplayerCharacterSelectionWindow(){
FormElement rVal = new FormElement();
// int screenTop = Globals.WINDOW_HEIGHT - 150;
int verticalPosition = 125;
//button (create)
Button createButton = new Button();
Label createLabel = new Label(100,125 + verticalPosition + 200,1.0f);
createLabel.setText("Create Character");
createButton.addChild(createLabel);
rVal.addChild(createButton);
createButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldCreationMenu());
return false;
}});
return rVal;
}
static String selectedRace = "";
public static Element createMultiplayerCharacterCreationWindow(){
FormElement rVal = new FormElement();
// int screenTop = Globals.WINDOW_HEIGHT - 150;
int verticalPosition = 125;
//select race
StringCarousel raceCarousel = new StringCarousel(100, 125, 1.0f);
raceCarousel.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event){
selectedRace = event.getAsString();
}});
for(String raceName : Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces()){
raceCarousel.addOption(raceName);
}
rVal.addChild(raceCarousel);
//button (create)
Button createButton = new Button();
Label createLabel = new Label(100,275,1.0f);
createLabel.setText("Select Race");
createButton.addChild(createLabel);
rVal.addChild(createButton);
createButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
WindowUtils.replaceMainMenuContents(MenuGeneratorsMultiplayer.createMultiplayerCharacterCreationTweakWindow(selectedRace));
return false;
}});
return rVal;
}
public static Element createMultiplayerCharacterCreationTweakWindow(String race){
// int screenTop = Globals.WINDOW_HEIGHT - 150;
int verticalPosition = 125;
int horizontalPosition = 300;
//figure out race data
CreatureType selectedRaceType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(race);
//spawn camera so renderer doesn't crash (once render pipeline is modularized this shouldn't be necessary)
Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3f(0,0,0), new Vector3f(0,0.3f,1).normalize());
Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera);
// CameraEntityUtils.setCameraEye(Globals.playerCamera, new Vector3f(-1,3f,0).normalize());
// CameraEntityUtils.setCameraCenter(Globals.playerCamera, new Vector3f(0,0,0));
//create actor panel
Actor characterActor = ActorUtils.createActorFromModelPath(selectedRaceType.getModelPath());
ActorPanel actorPanel = new ActorPanel(1200, 100, 500, 500, characterActor);
actorPanel.setAnimation(Animation.ANIMATION_IDLE_1);
actorPanel.setPosition(new Vector3f(0,-1,-0.5f));
// actorPanel.setRotation(new Quaternionf().rotateLocalY(0));
actorPanel.setScale(new Vector3f(0.01f,0.01f,0.01f));
//have to build static morph while looping through attributes
ActorStaticMorph staticMorph = new ActorStaticMorph();
//create creature template
CreatureTemplate template = new CreatureTemplate(race);
List<Element> controlsToAdd = new LinkedList<Element>();
//create edit controls here
for(VisualAttribute attribute : selectedRaceType.getVisualAttributes()){
if(attribute.getType().equals(VisualAttribute.TYPE_BONE)){
//add label for slider
Label sliderName = new Label(20, verticalPosition, 0.6f);
sliderName.setText(attribute.getAttributeId());
controlsToAdd.add(sliderName);
//add a slider
Slider boneSlider = new Slider(horizontalPosition, verticalPosition + 10, 500, 20, new Vector3f(0.1f,0.1f,0.1f), new Vector3f(1,1,1));
float min = attribute.getMinValue();
float max = attribute.getMaxValue();
float defaultValue = min + (max - min)/2.0f;
boneSlider.setMinimum(min);
boneSlider.setMaximum(max);
boneSlider.setValue(defaultValue);
controlsToAdd.add(boneSlider);
//actually add attributes to static morph
if(attribute.getPrimaryBone() != null && staticMorph.getBoneTransforms(attribute.getPrimaryBone()) == null){
staticMorph.initBoneTransforms(attribute.getPrimaryBone());
}
if(attribute.getMirrorBone() != null && staticMorph.getBoneTransforms(attribute.getMirrorBone()) == null){
staticMorph.initBoneTransforms(attribute.getMirrorBone());
}
//add attribute to creature template
template.putValue(attribute.getAttributeId(), defaultValue);
//set callback for when we change the slider value to update the static morph
boneSlider.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event) {
if(characterActor.getStaticMorph() != null){
ActorStaticMorph staticMorph = characterActor.getStaticMorph();
staticMorph.updateValue(attribute.getSubtype(), attribute.getPrimaryBone(), event.getAsFloat());
if(attribute.getMirrorBone() != null){
staticMorph.updateValue(attribute.getSubtype(), attribute.getMirrorBone(), event.getAsFloat());
}
template.getValue(attribute.getAttributeId()).setValue(event.getAsFloat());
}
}});
} else if(attribute.getType().equals(VisualAttribute.TYPE_REMESH)){
//add label for carousel
Label sliderName = new Label(20, verticalPosition, 0.6f);
sliderName.setText(attribute.getAttributeId());
controlsToAdd.add(sliderName);
//for adding the value to the creature template
boolean hasAddedValue = false;
//add a carousel
StringCarousel variantCarousel = new StringCarousel(horizontalPosition, verticalPosition, 1.0f);
for(AttributeVariant variant : attribute.getVariants()){
variantCarousel.addOption(variant.getId());
//if we haven't already added a value, add a value to the creature template
if(!hasAddedValue){
hasAddedValue = true;
//add attribute to template
template.putValue(attribute.getAttributeId(), variant.getId());
}
}
//callback for updating remesh
variantCarousel.setOnValueChangeCallback(new ValueChangeEventCallback(){public void execute(ValueChangeEvent event) {
//TODO: implement updating visuals
template.getValue(attribute.getAttributeId()).setVariantId(event.getAsString());
}});
controlsToAdd.add(variantCarousel);
}
verticalPosition = verticalPosition + 100;
}
//finally set static morph
characterActor.setActorStaticMorph(staticMorph);
//add button to actually create the character
Button createCharacterButton = new Button();
Label createCharacterLabel = new Label(horizontalPosition,verticalPosition,1.0f);
createCharacterLabel.setText("Create");
createCharacterButton.addChild(createCharacterLabel);
controlsToAdd.add(createCharacterButton);
createCharacterButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestCreateCharacterMessage(Utilities.stringify(template)));
return false;
}});
int width = 1800;
int height = verticalPosition + 300;
ScrollableContainer scrollable = new ScrollableContainer(0, 0, width, height);
for(Element newControl : controlsToAdd){
scrollable.addChild(newControl);
}
scrollable.addChild(actorPanel);
// rVal.addChild(scrollable);
// Label testLabel = new Label(100,215,1.0f);
// testLabel.setText("Aaaaaaa");
// rVal.addChild(testLabel);
// //black texture background
// ImagePanel imagePanel = new ImagePanel(0,0,width,height + 1000,Globals.blackTexture);
// scrollable.addChild(imagePanel);
return scrollable;
}
}

View File

@ -22,6 +22,7 @@ import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.spec.SecretKeySpec;
@ -34,8 +35,10 @@ import org.apache.commons.crypto.stream.CryptoOutputStream;
*/
public class ClientNetworking implements Runnable{
String address;
int port;
Socket socket;
public Socket socket;
// CryptoInputStream inputStream;
// CryptoOutputStream outputStream;
InputStream inputStream;
@ -44,15 +47,12 @@ public class ClientNetworking implements Runnable{
NetworkParser parser;
ClientProtocol clientProtocol = new ClientProtocol();
static final int MAX_CONNECTION_ATTEMPTS = 10;
public ClientNetworking(String address, int port){
try {
this.socket = new Socket(address,port);
} catch (IOException ex) {
System.err.println("Failed to connect!");
ex.printStackTrace();
System.exit(1);
}
this.address = address;
this.port = port;
}
@ -75,14 +75,39 @@ public class ClientNetworking implements Runnable{
// ex.printStackTrace();
// System.exit(1);
// }
//attempt connection
int connectionAttempts = 0;
boolean connected = false;
while(!connected){
try {
this.socket = new Socket(address,port);
connected = true;
} catch (IOException ex) {
LoggerInterface.loggerNetworking.WARNING("Client failed to connect!");
}
if(!connected){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {}
connectionAttempts++;
}
if(connectionAttempts > MAX_CONNECTION_ATTEMPTS){
LoggerInterface.loggerNetworking.ERROR("Max client connection attempts!", new Exception());
System.exit(1);
}
}
//create parser
try {
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
parser = new NetworkParser(inputStream,outputStream);
} catch (IOException ex) {
Logger.getLogger(ClientNetworking.class.getName()).log(Level.SEVERE, null, ex);
LoggerInterface.loggerNetworking.ERROR("Error on client socket", ex);
}
//start parsing messages
initialized = true;
while(Main.isRunning()){
//attempt poll incoming messages
@ -90,6 +115,7 @@ public class ClientNetworking implements Runnable{
//outgoing messages
parser.pushMessagesOut();
}
}

View File

@ -4,6 +4,7 @@ import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.parser.net.message.TerrainMessage;
public class AuthProtocol {
@ -16,9 +17,8 @@ public class AuthProtocol {
Globals.clientConnection.queueOutgoingMessage(AuthMessage.constructAuthDetailsMessage("myuser","mypass"));
break;
case AUTHSUCCESS:
//trigger request to spawn character
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage());
//request playable races
Globals.clientConnection.queueOutgoingMessage(LoreMessage.constructRequestRacesMessage());
break;
case AUTHFAILURE:
//TODO: handle better

View File

@ -0,0 +1,31 @@
package electrosphere.net.client.protocol;
import electrosphere.engine.LoadingThread;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.TerrainMessage;
public class CharacterProtocol {
protected static void handleCharacterMessage(CharacterMessage message){
switch(message.getMessageSubtype()){
case RESPONSECREATECHARACTERSUCCESS:
//trigger request to spawn character
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage());
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CLIENT_WORLD);
Globals.loadingThreadsList.add(clientThread);
clientThread.start();
break;
case REQUESTCHARACTERLIST:
case REQUESTCREATECHARACTER:
case REQUESTSPAWNCHARACTER:
case RESPONSECHARACTERLIST:
case RESPONSECREATECHARACTERFAILURE:
case RESPONSESPAWNCHARACTER:
//silently ignore
break;
}
}
}

View File

@ -10,7 +10,9 @@ import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.ServerMessage;
@ -41,6 +43,12 @@ public class ClientProtocol {
case SERVER_MESSAGE:
ServerProtocol.handleServerMessage((ServerMessage)message);
break;
case LORE_MESSAGE:
LoreProtocol.handleLoreMessage((LoreMessage)message);
break;
case CHARACTER_MESSAGE:
CharacterProtocol.handleCharacterMessage((CharacterMessage)message);
break;
}
}

View File

@ -3,27 +3,29 @@ package electrosphere.net.client.protocol;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.util.Utilities;
public class EntityProtocol {
protected static void handleEntityMessage(EntityMessage message){
LoggerInterface.loggerNetworking.DEBUG("Parse entity message of type " + message.getMessageSubtype());
Entity newlySpawnedEntity;
switch(message.getMessageSubtype()){
case CREATE:
LoggerInterface.loggerNetworking.DEBUG("Spawn ID " + message.getentityID() + " of type " + message.getentityCategory() + " subtype " + message.getentitySubtype());
Entity newlySpawnedEntity;
switch(message.getentityCategory()){
case 0:
newlySpawnedEntity = CreatureUtils.spawnBasicCreature(message.getentitySubtype());
EntityUtils.getScale(newlySpawnedEntity).set(0.005f);
EntityUtils.getPosition(newlySpawnedEntity).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
EntityUtils.setEntityID(newlySpawnedEntity, message.getentityID());
// newlySpawnedEntity = CreatureUtils.spawnBasicCreature(message.getentitySubtype());
// EntityUtils.getScale(newlySpawnedEntity).set(0.005f);
// EntityUtils.getPosition(newlySpawnedEntity).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
// EntityUtils.setEntityID(newlySpawnedEntity, message.getentityID());
break;
case 1:
newlySpawnedEntity = ItemUtils.spawnBasicItem(message.getentitySubtype());
@ -33,6 +35,14 @@ public class EntityProtocol {
break;
}
break;
case SPAWNCREATURE:
LoggerInterface.loggerNetworking.DEBUG("Spawn Creature " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ());
CreatureTemplate template = Utilities.deserialize(message.getcreatureTemplate(), CreatureTemplate.class);
newlySpawnedEntity = CreatureUtils.spawnBasicCreature(template.getCreatureType(),template);
EntityUtils.getScale(newlySpawnedEntity).set(0.005f);
EntityUtils.getPosition(newlySpawnedEntity).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
EntityUtils.setEntityID(newlySpawnedEntity, message.getentityID());
break;
case DESTROY:
break;
case MOVE:

View File

@ -0,0 +1,32 @@
package electrosphere.net.client.protocol;
import java.util.List;
import com.google.gson.Gson;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.LoreMessage;
public class LoreProtocol {
protected static void handleLoreMessage(LoreMessage message){
switch(message.getMessageSubtype()){
case RESPONSEDATA:
break;
case RESPONSERACES:
//we get back the race list as a json array, deserialize, and push into type loader
List<String> playableRaces = new Gson().fromJson(message.getdata(), List.class);
Globals.gameConfigCurrent.getCreatureTypeLoader().loadPlayableRaces(playableRaces);
break;
case RESPONSERACEDATA:
break;
case REQUESTDATA:
case REQUESTRACEDATA:
case REQUESTRACES:
//silently ignore
break;
}
}
}

View File

@ -1,5 +1,7 @@
package electrosphere.net.client.protocol;
import javax.vecmath.Vector3d;
import org.joml.Vector3f;
import electrosphere.game.client.world.ClientWorldData;
@ -26,7 +28,7 @@ public class TerrainProtocol {
Globals.clientTerrainManager.attachTerrainMessage(message);
break;
case SPAWNPOSITION:
Globals.spawnPoint.set(new Vector3f(message.getrealLocationX(),0.25f,message.getrealLocationY()));
Globals.spawnPoint.set(message.getrealLocationX(),0.25,message.getrealLocationY());
break;
case CHUNKLOADSTART:
Globals.clientTerrainManager.attachTerrainMessage(message);

View File

@ -10,7 +10,8 @@ public class CharacterMessage extends NetworkMessage {
REQUESTCHARACTERLIST,
RESPONSECHARACTERLIST,
REQUESTCREATECHARACTER,
RESPONSECREATECHARACTER,
RESPONSECREATECHARACTERSUCCESS,
RESPONSECREATECHARACTERFAILURE,
REQUESTSPAWNCHARACTER,
RESPONSESPAWNCHARACTER,
}
@ -51,13 +52,19 @@ public class CharacterMessage extends NetworkMessage {
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST:
return CharacterMessage.canParseResponseCharacterListMessage(byteStream);
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER_SIZE){
return CharacterMessage.canParseRequestCreateCharacterMessage(byteStream);
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS_SIZE){
return true;
} else {
return false;
}
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE_SIZE){
return true;
} else {
return false;
}
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTER:
return CharacterMessage.canParseResponseCreateCharacterMessage(byteStream);
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER_SIZE){
return true;
@ -115,19 +122,7 @@ public class CharacterMessage extends NetworkMessage {
return rVal;
}
public static CharacterMessage parseRequestCreateCharacterMessage(List<Byte> byteStream){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCREATECHARACTER);
stripPacketHeader(byteStream);
return rVal;
}
public static CharacterMessage constructRequestCreateCharacterMessage(){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCREATECHARACTER);
rVal.serialize();
return rVal;
}
public static boolean canParseResponseCreateCharacterMessage(List<Byte> byteStream){
public static boolean canParseRequestCreateCharacterMessage(List<Byte> byteStream){
int currentStreamLength = byteStream.size();
List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0;
@ -146,20 +141,44 @@ public class CharacterMessage extends NetworkMessage {
return true;
}
public static CharacterMessage parseResponseCreateCharacterMessage(List<Byte> byteStream){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTER);
public static CharacterMessage parseRequestCreateCharacterMessage(List<Byte> byteStream){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCREATECHARACTER);
stripPacketHeader(byteStream);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream));
return rVal;
}
public static CharacterMessage constructResponseCreateCharacterMessage(String data){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTER);
public static CharacterMessage constructRequestCreateCharacterMessage(String data){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCREATECHARACTER);
rVal.setdata(data);
rVal.serialize();
return rVal;
}
public static CharacterMessage parseResponseCreateCharacterSuccessMessage(List<Byte> byteStream){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERSUCCESS);
stripPacketHeader(byteStream);
return rVal;
}
public static CharacterMessage constructResponseCreateCharacterSuccessMessage(){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERSUCCESS);
rVal.serialize();
return rVal;
}
public static CharacterMessage parseResponseCreateCharacterFailureMessage(List<Byte> byteStream){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERFAILURE);
stripPacketHeader(byteStream);
return rVal;
}
public static CharacterMessage constructResponseCreateCharacterFailureMessage(){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERFAILURE);
rVal.serialize();
return rVal;
}
public static CharacterMessage parseRequestSpawnCharacterMessage(List<Byte> byteStream){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTSPAWNCHARACTER);
stripPacketHeader(byteStream);
@ -233,18 +252,11 @@ public class CharacterMessage extends NetworkMessage {
}
break;
case REQUESTCREATECHARACTER:
rawBytes = new byte[2];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_CHARACTER;
//entity messaage header
rawBytes[1] = TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER;
break;
case RESPONSECREATECHARACTER:
rawBytes = new byte[2+4+data.length()];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_CHARACTER;
//entity messaage header
rawBytes[1] = TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTER;
rawBytes[1] = TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER;
intValues = ByteStreamUtils.serializeIntToBytes(data.length());
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
@ -254,6 +266,20 @@ public class CharacterMessage extends NetworkMessage {
rawBytes[6+i] = stringBytes[i];
}
break;
case RESPONSECREATECHARACTERSUCCESS:
rawBytes = new byte[2];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_CHARACTER;
//entity messaage header
rawBytes[1] = TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS;
break;
case RESPONSECREATECHARACTERFAILURE:
rawBytes = new byte[2];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_CHARACTER;
//entity messaage header
rawBytes[1] = TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE;
break;
case REQUESTSPAWNCHARACTER:
rawBytes = new byte[2];
//message header

View File

@ -8,6 +8,7 @@ public class EntityMessage extends NetworkMessage {
public enum EntityMessageType {
CREATE,
SPAWNCREATURE,
SETPOSITION,
SETFACING,
MOVEUPDATE,
@ -24,6 +25,7 @@ public class EntityMessage extends NetworkMessage {
int entityCategory;
String entitySubtype;
int entityID;
String creatureTemplate;
double positionX;
double positionY;
double positionZ;
@ -74,6 +76,14 @@ public class EntityMessage extends NetworkMessage {
this.entityID = entityID;
}
public String getcreatureTemplate() {
return creatureTemplate;
}
public void setcreatureTemplate(String creatureTemplate) {
this.creatureTemplate = creatureTemplate;
}
public double getpositionX() {
return positionX;
}
@ -211,6 +221,8 @@ public class EntityMessage extends NetworkMessage {
switch(secondByte){
case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE:
return EntityMessage.canParseCreateMessage(byteStream);
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE:
return EntityMessage.canParseSpawnCreatureMessage(byteStream);
case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION_SIZE){
return true;
@ -329,6 +341,59 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static boolean canParseSpawnCreatureMessage(List<Byte> byteStream){
int currentStreamLength = byteStream.size();
List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){
return false;
}
int creatureTemplateSize = 0;
if(currentStreamLength < 10){
return false;
} else {
temporaryByteQueue.add(byteStream.get(6 + 0));
temporaryByteQueue.add(byteStream.get(6 + 1));
temporaryByteQueue.add(byteStream.get(6 + 2));
temporaryByteQueue.add(byteStream.get(6 + 3));
creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
}
if(currentStreamLength < 10 + creatureTemplateSize){
return false;
}
if(currentStreamLength < 14){
return false;
}
if(currentStreamLength < 22){
return false;
}
if(currentStreamLength < 30){
return false;
}
return true;
}
public static EntityMessage parseSpawnCreatureMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNCREATURE);
stripPacketHeader(byteStream);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteStream));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
return rVal;
}
public static EntityMessage constructSpawnCreatureMessage(int entityID,String creatureTemplate,double positionX,double positionY,double positionZ){
EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNCREATURE);
rVal.setentityID(entityID);
rVal.setcreatureTemplate(creatureTemplate);
rVal.setpositionX(positionX);
rVal.setpositionY(positionY);
rVal.setpositionZ(positionZ);
rVal.serialize();
return rVal;
}
public static EntityMessage parseSetPositionMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETPOSITION);
stripPacketHeader(byteStream);
@ -612,6 +677,37 @@ public class EntityMessage extends NetworkMessage {
rawBytes[30+entitySubtype.length()+i] = intValues[i];
}
break;
case SPAWNCREATURE:
rawBytes = new byte[2+4+4+creatureTemplate.length()+8+8+8];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE;
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(creatureTemplate.length());
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
stringBytes = creatureTemplate.getBytes();
for(int i = 0; i < creatureTemplate.length(); i++){
rawBytes[10+i] = stringBytes[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
for(int i = 0; i < 8; i++){
rawBytes[10+creatureTemplate.length()+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
for(int i = 0; i < 8; i++){
rawBytes[18+creatureTemplate.length()+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
for(int i = 0; i < 8; i++){
rawBytes[26+creatureTemplate.length()+i] = intValues[i];
}
break;
case SETPOSITION:
rawBytes = new byte[2+4+8+8+8+8];
//message header

View File

@ -8,11 +8,11 @@ public abstract class NetworkMessage {
public enum MessageType {
ENTITY_MESSAGE,
LORE_MESSAGE,
CHARACTER_MESSAGE,
PLAYER_MESSAGE,
TERRAIN_MESSAGE,
SERVER_MESSAGE,
AUTH_MESSAGE,
CHARACTER_MESSAGE,
}
MessageType type;
@ -42,6 +42,11 @@ AUTH_MESSAGE,
rVal = EntityMessage.parseCreateMessage(byteStream);
}
break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){
rVal = EntityMessage.parseSpawnCreatureMessage(byteStream);
}
break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION:
if(EntityMessage.canParseMessage(byteStream,secondByte)){
rVal = EntityMessage.parseSetPositionMessage(byteStream);
@ -129,41 +134,6 @@ AUTH_MESSAGE,
break;
}
break;
case TypeBytes.MESSAGE_TYPE_CHARACTER:
secondByte = byteStream.get(1);
switch(secondByte){
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseRequestCharacterListMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseResponseCharacterListMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseRequestCreateCharacterMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseResponseCreateCharacterMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseRequestSpawnCharacterMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseResponseSpawnCharacterMessage(byteStream);
}
break;
}
break;
case TypeBytes.MESSAGE_TYPE_PLAYER:
secondByte = byteStream.get(1);
switch(secondByte){
@ -264,6 +234,46 @@ AUTH_MESSAGE,
break;
}
break;
case TypeBytes.MESSAGE_TYPE_CHARACTER:
secondByte = byteStream.get(1);
switch(secondByte){
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseRequestCharacterListMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseResponseCharacterListMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseRequestCreateCharacterMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseResponseCreateCharacterSuccessMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseResponseCreateCharacterFailureMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseRequestSpawnCharacterMessage(byteStream);
}
break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){
rVal = CharacterMessage.parseResponseSpawnCharacterMessage(byteStream);
}
break;
}
break;
}
}
return rVal;

View File

@ -30,8 +30,8 @@ public class TerrainMessage extends NetworkMessage {
float value;
int locationX;
int locationY;
float realLocationX;
float realLocationY;
double realLocationX;
double realLocationY;
float macroValue00;
float macroValue01;
float macroValue02;
@ -188,19 +188,19 @@ public class TerrainMessage extends NetworkMessage {
this.locationY = locationY;
}
public float getrealLocationX() {
public double getrealLocationX() {
return realLocationX;
}
public void setrealLocationX(float realLocationX) {
public void setrealLocationX(double realLocationX) {
this.realLocationX = realLocationX;
}
public float getrealLocationY() {
public double getrealLocationY() {
return realLocationY;
}
public void setrealLocationY(float realLocationY) {
public void setrealLocationY(double realLocationY) {
this.realLocationY = realLocationY;
}
@ -892,12 +892,12 @@ public class TerrainMessage extends NetworkMessage {
public static TerrainMessage parseSpawnPositionMessage(List<Byte> byteStream){
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.SPAWNPOSITION);
stripPacketHeader(byteStream);
rVal.setrealLocationX(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrealLocationY(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrealLocationX(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
rVal.setrealLocationY(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
return rVal;
}
public static TerrainMessage constructSpawnPositionMessage(float realLocationX,float realLocationY){
public static TerrainMessage constructSpawnPositionMessage(double realLocationX,double realLocationY){
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.SPAWNPOSITION);
rVal.setrealLocationX(realLocationX);
rVal.setrealLocationY(realLocationY);
@ -1216,18 +1216,20 @@ public class TerrainMessage extends NetworkMessage {
}
break;
case SPAWNPOSITION:
rawBytes = new byte[2+4+4];
rawBytes = new byte[2+8+8];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
//entity messaage header
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_SPAWNPOSITION;
intValues = ByteStreamUtils.serializeFloatToBytes(realLocationX);
for(int i = 0; i < 4; i++){
intValues = ByteStreamUtils.serializeDoubleToBytes(realLocationX);
for(int i = 0; i < 8; i++){
rawBytes[2+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(realLocationY);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
} break;
}
intValues = ByteStreamUtils.serializeDoubleToBytes(realLocationY);
for(int i = 0; i < 8; i++){
rawBytes[10+i] = intValues[i];
}
break;
}
serialized = true;
}

View File

@ -7,25 +7,26 @@ Message categories
*/
public static final byte MESSAGE_TYPE_ENTITY = 0;
public static final byte MESSAGE_TYPE_LORE = 1;
public static final byte MESSAGE_TYPE_CHARACTER = 2;
public static final byte MESSAGE_TYPE_PLAYER = 3;
public static final byte MESSAGE_TYPE_TERRAIN = 4;
public static final byte MESSAGE_TYPE_SERVER = 5;
public static final byte MESSAGE_TYPE_AUTH = 6;
public static final byte MESSAGE_TYPE_PLAYER = 2;
public static final byte MESSAGE_TYPE_TERRAIN = 3;
public static final byte MESSAGE_TYPE_SERVER = 4;
public static final byte MESSAGE_TYPE_AUTH = 5;
public static final byte MESSAGE_TYPE_CHARACTER = 6;
/*
Entity subcategories
*/
public static final byte ENTITY_MESSAGE_TYPE_CREATE = 0;
public static final byte ENTITY_MESSAGE_TYPE_SETPOSITION = 1;
public static final byte ENTITY_MESSAGE_TYPE_SETFACING = 2;
public static final byte ENTITY_MESSAGE_TYPE_MOVEUPDATE = 3;
public static final byte ENTITY_MESSAGE_TYPE_ATTACKUPDATE = 4;
public static final byte ENTITY_MESSAGE_TYPE_MOVE = 5;
public static final byte ENTITY_MESSAGE_TYPE_KILL = 6;
public static final byte ENTITY_MESSAGE_TYPE_DESTROY = 7;
public static final byte ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE = 8;
public static final byte ENTITY_MESSAGE_TYPE_SETPROPERTY = 9;
public static final byte ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY = 10;
public static final byte ENTITY_MESSAGE_TYPE_SPAWNCREATURE = 1;
public static final byte ENTITY_MESSAGE_TYPE_SETPOSITION = 2;
public static final byte ENTITY_MESSAGE_TYPE_SETFACING = 3;
public static final byte ENTITY_MESSAGE_TYPE_MOVEUPDATE = 4;
public static final byte ENTITY_MESSAGE_TYPE_ATTACKUPDATE = 5;
public static final byte ENTITY_MESSAGE_TYPE_MOVE = 6;
public static final byte ENTITY_MESSAGE_TYPE_KILL = 7;
public static final byte ENTITY_MESSAGE_TYPE_DESTROY = 8;
public static final byte ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE = 9;
public static final byte ENTITY_MESSAGE_TYPE_SETPROPERTY = 10;
public static final byte ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY = 11;
/*
Entity packet sizes
*/
@ -53,21 +54,6 @@ Message categories
public static final byte LORE_MESSAGE_TYPE_REQUESTRACES_SIZE = 2;
public static final byte LORE_MESSAGE_TYPE_REQUESTRACEDATA_SIZE = 2;
/*
Character subcategories
*/
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST = 0;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST = 1;
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER = 2;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTER = 3;
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER = 4;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER = 5;
/*
Character packet sizes
*/
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST_SIZE = 2;
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER_SIZE = 2;
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER_SIZE = 2;
/*
Player subcategories
*/
public static final byte PLAYER_MESSAGE_TYPE_SET_ID = 0;
@ -98,7 +84,7 @@ Message categories
public static final byte TERRAIN_MESSAGE_TYPE_CHUNKLOADSTART_SIZE = 14;
public static final short TERRAIN_MESSAGE_TYPE_MACROVALUE_SIZE = 310;
public static final byte TERRAIN_MESSAGE_TYPE_HEIGHTMAPMODIFICATION_SIZE = 22;
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION_SIZE = 10;
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION_SIZE = 18;
/*
Server subcategories
*/
@ -122,5 +108,22 @@ Message categories
public static final byte AUTH_MESSAGE_TYPE_AUTHREQUEST_SIZE = 2;
public static final byte AUTH_MESSAGE_TYPE_AUTHSUCCESS_SIZE = 2;
public static final byte AUTH_MESSAGE_TYPE_AUTHFAILURE_SIZE = 2;
/*
Character subcategories
*/
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST = 0;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST = 1;
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER = 2;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS = 3;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE = 4;
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER = 5;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER = 6;
/*
Character packet sizes
*/
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST_SIZE = 2;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS_SIZE = 2;
public static final byte CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE_SIZE = 2;
public static final byte CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER_SIZE = 2;
}

View File

@ -1,5 +1,6 @@
package electrosphere.net.server;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
@ -56,6 +57,7 @@ public class ServerConnectionHandler implements Runnable {
NetworkParser networkParser;
int playerID;
int playerCharacterID;
CreatureTemplate currentCreatureTemplate;
ServerProtocol serverProtocol;
@ -165,6 +167,8 @@ public class ServerConnectionHandler implements Runnable {
networkParser.addOutgoingMessage(message);
}
break;
case SPAWNCREATURE:
break;
default:
networkParser.addOutgoingMessage(message);
break;
@ -175,4 +179,13 @@ public class ServerConnectionHandler implements Runnable {
break;
}
}
public void setCreatureTemplate(CreatureTemplate currentCreatureTemplate){
this.currentCreatureTemplate = currentCreatureTemplate;
}
public CreatureTemplate getCurrentCreatureTemplate(){
return this.currentCreatureTemplate;
}
}

View File

@ -6,6 +6,7 @@ import org.joml.Vector3f;
import electrosphere.entity.Entity;
import electrosphere.entity.state.ironsight.IronSightTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.main.Globals;
import electrosphere.main.Main;
@ -14,6 +15,7 @@ import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player;
import electrosphere.util.Utilities;
public class CharacterProtocol {
@ -23,17 +25,20 @@ public class CharacterProtocol {
//TODO
break;
case REQUESTCREATECHARACTER:
//TODO
CreatureTemplate template = Utilities.deserialize(message.getdata(), CreatureTemplate.class);
if(template != null){
connectionHandler.setCreatureTemplate(Utilities.deserialize(message.getdata(), CreatureTemplate.class));
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterSuccessMessage());
} else {
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterFailureMessage());
}
break;
case REQUESTSPAWNCHARACTER:
spawnPlayerCharacter(connectionHandler);
break;
case RESPONSECHARACTERLIST:
//silently ignore
break;
case RESPONSECREATECHARACTER:
//silently ignore
break;
case RESPONSECREATECHARACTERSUCCESS:
case RESPONSECREATECHARACTERFAILURE:
case RESPONSESPAWNCHARACTER:
//silently ignore
break;
@ -43,7 +48,7 @@ public class CharacterProtocol {
static void spawnPlayerCharacter(ServerConnectionHandler connectionHandler){
Player playerObject = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
//spawn player in world
Entity newPlayerEntity = CreatureUtils.spawnBasicCreature("human");
Entity newPlayerEntity = CreatureUtils.spawnBasicCreature("human",connectionHandler.getCurrentCreatureTemplate());
int playerCharacterId = newPlayerEntity.getId();
connectionHandler.setPlayerCharacterId(playerCharacterId);
CreatureUtils.repositionCreature(newPlayerEntity, new Vector3d(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z));

View File

@ -17,10 +17,6 @@ public class EntityProtocol {
protected static void handleEntityMessage(ServerConnectionHandler connectionHandler, EntityMessage message){
Entity targetEntity;
switch(message.getMessageSubtype()){
case CREATE:
break;
case DESTROY:
break;
case MOVE:
targetEntity = Globals.entityManager.getEntityFromId(message.getentityID());
if(targetEntity != null){
@ -42,6 +38,10 @@ public class EntityProtocol {
}
break;
//ignore stack
case KILL:
case SPAWNCREATURE:
case DESTROY:
case CREATE:
case ATTACHENTITYTOENTITY:
case SETFACING:
case SETPOSITION:

View File

@ -198,6 +198,10 @@ public class RenderingEngine {
ShaderProgram activeProgram;
static int outputFramebuffer = 0;
//used in calculating projection matrix
static float aspectRatio = 1.0f;
static float verticalFOV = 90.0f;
public void createOpenglContext(){
@ -388,10 +392,11 @@ public class RenderingEngine {
//
Globals.projectionMatrix = new Matrix4f();
Globals.viewMatrix = new Matrix4f();
float verticalFOV = (float)(Globals.verticalFOV * Math.PI /180.0f);
float aspectRatio = (float)Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT;
verticalFOV = (float)(Globals.verticalFOV * Math.PI /180.0f);
//set local aspect ratio and global aspect ratio at the same time
aspectRatio = Globals.aspectRatio = Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT;
float nearClip = 0.001f;
Globals.projectionMatrix.setPerspective(verticalFOV, aspectRatio, nearClip, Globals.userSettings.getGraphicsViewDistance());
Globals.projectionMatrix.setPerspective(verticalFOV, Globals.aspectRatio, nearClip, Globals.userSettings.getGraphicsViewDistance());
Globals.viewMatrix.translation(new Vector3f(0.0f,0.0f,-3.0f));
}
@ -1312,5 +1317,21 @@ public class RenderingEngine {
outputFramebuffer = 0;
}
}
public static void setFOV(float verticalFOV){
RenderingEngine.verticalFOV = verticalFOV;
calculateProjectionMatrix();
}
public static void setAspectRatio(float aspectRatio){
RenderingEngine.aspectRatio = aspectRatio;
calculateProjectionMatrix();
}
static void calculateProjectionMatrix(){
float radVerticalFOV = (float)(RenderingEngine.verticalFOV * Math.PI /180.0f);
float nearClip = 0.001f;
Globals.projectionMatrix.setPerspective(radVerticalFOV, RenderingEngine.aspectRatio, nearClip, Globals.userSettings.getGraphicsViewDistance());
}
}

View File

@ -19,60 +19,107 @@ public class ActorStaticMorph {
return boneTransformMap.get(boneName);
}
public void setYaw(String boneName, float yaw){
void setYaw(String boneName, float yaw){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).yaw = yaw;
}
}
public void setPitch(String boneName, float pitch){
void setPitch(String boneName, float pitch){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).pitch = pitch;
}
}
public void setRoll(String boneName, float roll){
void setRoll(String boneName, float roll){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).roll = roll;
}
}
public void setOffsetX(String boneName, float offsetX){
void setOffsetX(String boneName, float offsetX){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).offset.x = offsetX;
}
}
public void setOffsetY(String boneName, float offsetY){
void setOffsetY(String boneName, float offsetY){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).offset.y = offsetY;
}
}
public void setOffsetZ(String boneName, float offsetZ){
void setOffsetZ(String boneName, float offsetZ){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).offset.z = offsetZ;
}
}
public void setScaleX(String boneName, float scaleX){
void setScaleX(String boneName, float scaleX){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).scale.x = scaleX;
}
}
public void setScaleY(String boneName, float scaleY){
void setScaleY(String boneName, float scaleY){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).scale.y = scaleY;
}
}
public void setScaleZ(String boneName, float scaleZ){
void setScaleZ(String boneName, float scaleZ){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).scale.z = scaleZ;
}
}
void setScale(String boneName, float scale){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).scale.set(scale);
}
}
/**
* Instead of having this code be duplicated every time we want to update a static morph, putting it in here
*/
public void updateValue(String subtype, String bone, float value){
switch(subtype){
case "yaw":
this.setYaw(bone, value);
break;
case "pitch":
this.setPitch(bone, value);
break;
case "roll":
this.setRoll(bone, value);
break;
case "scalex":
this.setScaleX(bone, value);
break;
case "scaley":
this.setScaleY(bone, value);
break;
case "scalez":
this.setScaleZ(bone, value);
break;
case "offx":
this.setOffsetX(bone, value);
break;
case "offy":
this.setOffsetY(bone, value);
break;
case "offz":
this.setOffsetZ(bone, value);
break;
case "scale":
this.setScale(bone, value);
break;
case "offl":
//TODO
break;
}
}
public class StaticMorphTransforms {

View File

@ -0,0 +1,19 @@
package electrosphere.renderer.ui;
import electrosphere.renderer.ui.events.ValueChangeEvent;
/**
* Describes an element that contains a changeable value which will be used by the program somewhere
* IE a carousel, text input, radio dial, etc
*/
public interface ValueElement extends Element {
public void setOnValueChangeCallback(ValueChangeEventCallback callback);
public interface ValueChangeEventCallback {
public void execute(ValueChangeEvent event);
}
}

View File

@ -0,0 +1,257 @@
package electrosphere.renderer.ui.elements;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_LESS;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glDepthFunc;
import static org.lwjgl.opengl.GL11.glDepthMask;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glViewport;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import static org.lwjgl.opengl.GL30.glBindFramebuffer;
import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import electrosphere.renderer.Material;
import electrosphere.renderer.Model;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.framebuffer.Framebuffer;
import electrosphere.renderer.framebuffer.FramebufferUtils;
import electrosphere.renderer.texture.Texture;
import electrosphere.renderer.ui.DraggableElement;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.events.DragEvent;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.DragEvent.DragEventType;
public class ActorPanel implements DrawableElement, DraggableElement {
Material customMat = new Material();
Framebuffer elementBuffer;
Actor actor;
Matrix4f modelMatrix = new Matrix4f();
String currentAnim;
Vector3f actorPosition = new Vector3f(0,0,0);
Quaternionf actorRotation = new Quaternionf();
Vector3f actorScale = new Vector3f(1,1,1);
float FOV = 50.0f;
float aspectRatio = 1.9f;
Vector3f texPosition = new Vector3f(0,0,0);
Vector3f texScale = new Vector3f(1,1,0);
DragEventCallback onDragStart;
DragEventCallback onDrag;
DragEventCallback onDragRelease;
public ActorPanel(int x, int y, int width, int height, Actor actor){
elementBuffer = FramebufferUtils.generateTextureFramebuffer(width, height);
customMat.setTexturePointer(elementBuffer.getTexturePointer());
this.actor = actor;
this.positionX = x;
this.positionY = y;
this.width = width;
this.height = height;
this.aspectRatio = (float)width / (float)height;
recalculateModelMatrix();
}
@Override
public void draw(int parentFramebufferPointer, int parentWidth, int parentHeight) {
elementBuffer.bind();
// Globals.renderingEngine.setViewportSize(width, height);
RenderingEngine.setFOV(FOV);
RenderingEngine.setAspectRatio(aspectRatio);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(true);
glViewport(0, 0, width, height);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(currentAnim != null){
if(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)){
actor.playAnimation(currentAnim,3);
actor.incrementAnimationTime(Main.deltaFrames);
}
}
actor.applyModelMatrix(modelMatrix);
actor.draw(true);
RenderingEngine.setFOV(Globals.verticalFOV);
RenderingEngine.setAspectRatio(Globals.aspectRatio);
glDisable(GL_DEPTH_TEST);
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
//set viewport
Globals.renderingEngine.setViewportSize(parentWidth, parentHeight);
float ndcX = (float)positionX/parentWidth;
float ndcY = (float)positionY/parentHeight;
float ndcWidth = (float)width/parentWidth;
float ndcHeight = (float)height/parentHeight;
Vector3f boxPosition = new Vector3f(ndcX,ndcY,0);
Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
Model planeModel = Globals.assetManager.fetchModel(ImagePanel.imagePanelModelPath);
if(planeModel != null){
planeModel.pushUniformToMesh("plane", "mPosition", boxPosition);
planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions);
planeModel.pushUniformToMesh("plane", "tPosition", texPosition);
planeModel.pushUniformToMesh("plane", "tDimension", texScale);
planeModel.meshes.get(0).setMaterial(customMat);
planeModel.drawUI();
} else {
LoggerInterface.loggerRenderer.ERROR("Actor Panel unable to find plane model!!", new Exception());
}
}
public int width = 1;
public int height = 1;
public int positionX = 0;
public int positionY = 0;
public int parentWidth = 1;
public int parentHeight = 1;
public boolean visible = false;
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getPositionX() {
return positionX;
}
public int getPositionY() {
return positionY;
}
public boolean getVisible() {
return visible;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setPositionX(int positionX) {
this.positionX = positionX;
}
public void setPositionY(int positionY) {
this.positionY = positionY;
}
public void setVisible(boolean draw) {
this.visible = draw;
}
public void setParentWidth(int width){
parentWidth = width;
}
public void setParentHeight(int height){
this.parentHeight = height;
}
public void setAnimation(String animation){
currentAnim = animation;
}
public void setPosition(Vector3f position){
this.actorPosition.set(position);
recalculateModelMatrix();
}
public void setRotation(Quaternionf rotation){
this.actorRotation.set(rotation);
recalculateModelMatrix();
}
public void setScale(Vector3f scale){
this.actorScale.set(scale);
recalculateModelMatrix();
}
void recalculateModelMatrix(){
modelMatrix.identity();
modelMatrix.translate(actorPosition);
modelMatrix.rotate(actorRotation);
modelMatrix.scale(actorScale);
actor.applyModelMatrix(modelMatrix);
}
public boolean handleEvent(Event event){
boolean propagate = true;
if(event instanceof DragEvent){
if(onDragStart != null && ((DragEvent)event).getType() == DragEventType.START){
if(!onDragStart.execute((DragEvent)event)){
propagate = false;
}
}
if(onDrag != null && ((DragEvent)event).getType() == DragEventType.DRAG){
if(!onDrag.execute((DragEvent)event)){
propagate = false;
}
}
if(onDragRelease != null && ((DragEvent)event).getType() == DragEventType.RELEASE){
if(!onDragRelease.execute((DragEvent)event)){
propagate = false;
}
}
}
return propagate;
}
@Override
public void setOnDragStart(DragEventCallback callback) {
onDragStart = callback;
}
@Override
public void setOnDrag(DragEventCallback callback) {
onDrag = callback;
}
@Override
public void setOnDragRelease(DragEventCallback callback) {
onDragRelease = callback;
}
}

View File

@ -11,6 +11,7 @@ import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.FocusableElement;
import electrosphere.renderer.ui.KeyEventElement;
import electrosphere.renderer.ui.MenuEventElement;
import electrosphere.renderer.ui.ValueElement;
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.DragEvent;
import electrosphere.renderer.ui.events.Event;
@ -18,9 +19,10 @@ import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.KeyboardEvent;
import electrosphere.renderer.ui.events.MenuEvent;
import electrosphere.renderer.ui.events.MouseEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.renderer.ui.events.DragEvent.DragEventType;
public class Slider implements ClickableElement, DraggableElement, FocusableElement, DrawableElement, MenuEventElement {
public class Slider implements ClickableElement, DraggableElement, FocusableElement, DrawableElement, MenuEventElement, ValueElement {
public int width = 1;
public int height = 1;
@ -41,7 +43,7 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
DragEventCallback onDragRelease;
ClickEventCallback onClick;
MenuEventCallback onMenuEvent;
OnSliderChangeCallback onChangeValue;
ValueChangeEventCallback onValueChange;
float min = 0.0f;
float max = 1.0f;
@ -109,7 +111,7 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
//actual slider
ndcX = (float)(positionX + marginX)/parentWidth;
ndcY = (float)(positionY + marginY)/parentHeight;
ndcWidth = (float)(width * value - marginX * 2)/parentWidth;
ndcWidth = (float)((width - marginX * 2) * getValueAsPercentage())/parentWidth;
ndcHeight = (float)(height - marginY * 2)/parentHeight;
boxPosition = new Vector3f(ndcX,ndcY,0);
boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
@ -154,6 +156,10 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
return width;
}
float getValueAsPercentage(){
return (value - min) / (max - min);
}
public int getHeight() {
return height;
}
@ -238,8 +244,9 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
onMenuEvent = callback;
}
public void setOnValueChange(OnSliderChangeCallback callback){
this.onChangeValue = callback;
@Override
public void setOnValueChangeCallback(ValueChangeEventCallback callback) {
onValueChange = callback;
}
@ -253,6 +260,7 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
propagate = this.onFocusCallback.execute(focusEvent);
} else {
//default behavior/
colorForeground = new Vector3f(1,0,0);
propagate = true;
}
} else {
@ -260,6 +268,7 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
propagate = this.onLoseFocusCallback.execute(focusEvent);
} else {
//default behavior
colorForeground = new Vector3f(1,1,1);
propagate = true;
}
}
@ -272,15 +281,15 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
switch(menuEvent.getType()){
case INCREMENT:
value = Math.min(value + ((max - min) * 0.01f),max);
if(onChangeValue != null){
onChangeValue.onChange(value);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(value));
}
propagate = false;
break;
case DECREMENT:
value = Math.max(value - ((max - min) * 0.01f),min);
if(onChangeValue != null){
onChangeValue.onChange(value);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(value));
}
propagate = false;
break;
@ -320,8 +329,8 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
int percentage = clickEvent.getCurrentX() - positionX;
int max = width;
value = Math.max(Math.min((float)percentage/max,1.0f),0.0f);
if(onChangeValue != null){
onChangeValue.onChange(value);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(value));
}
propagate = false;
}
@ -329,12 +338,5 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
}
return propagate;
}
public interface OnSliderChangeCallback {
public void onChange(float value);
}
}

View File

@ -0,0 +1,326 @@
package electrosphere.renderer.ui.elements;
import java.util.LinkedList;
import java.util.List;
import org.joml.Vector3f;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.Element;
import electrosphere.renderer.ui.FocusableElement;
import electrosphere.renderer.ui.MenuEventElement;
import electrosphere.renderer.ui.ValueElement;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.MenuEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.renderer.ui.events.MenuEvent.MenuEventType;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter;
public class StringCarousel implements DrawableElement, MenuEventElement, FocusableElement, ValueElement {
public int width = 1;
public int height = 1;
public int positionX = 0;
public int positionY = 0;
public int parentWidth = 1;
public int parentHeight = 1;
public boolean visible = false;
MenuEventCallback onMenuEventCallback;
ValueChangeEventCallback onValueChange;
boolean focused = false;
FocusEventCallback onFocusCallback;
FocusEventCallback onLoseFocusCallback;
List<String> options = new LinkedList<String>();
int currentOption = -1;
String textCurrent = "";
int textPixelWidth = 0;
float fontSize = 1.0f;
List<BitmapCharacter> childrenElements = new LinkedList<BitmapCharacter>();
public StringCarousel(int x, int y, float fontSize){
this.positionX = x;
this.positionY = y;
this.width = 0;
this.height = (int)(FontUtils.getFontHeight() * fontSize);
this.fontSize = fontSize;
}
public void addOption(String option){
options.add(option);
if(currentOption == -1){
currentOption = 0;
setText(option);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(option));
}
}
}
public List<String> getOptions(){
return options;
}
public void removeOption(String option){
options.remove(option);
if(currentOption > options.size() - 1){
currentOption = options.size() - 1;
}
}
void generateLetters(){
childrenElements.clear();
int rollingOffset = 0;
for(int i = 0; i < textCurrent.length(); i++){
char toDraw = textCurrent.charAt(i);
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter((int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
rollingOffset += (int)bitMapDimension.x;
childrenElements.add(newLetter);
}
}
public void setText(String text){
this.textCurrent = text;
textPixelWidth = 0;
for(int i = 0; i < text.length(); i++){
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(text.charAt(i));
textPixelWidth = textPixelWidth + (int)bitMapDimension.x;
}
generateLetters();
if(focused){
setColor(new Vector3f(1,0,0));
}
}
public void setColor(Vector3f color){
for(BitmapCharacter character : childrenElements){
character.setColor(color);
}
}
public String getText(){
return textCurrent;
}
@Override
public void draw(int parentFramebufferPointer, int parentWidth, int parentHeight) {
for(DrawableElement child : childrenElements){
child.draw(parentFramebufferPointer, parentWidth, parentHeight);
}
}
public int getWidth() {
int minX = -1;
int maxX = -1;
for(BitmapCharacter child : childrenElements){
if(minX == -1){
minX = child.getPositionX();
} else if(child.getPositionX() < minX){
minX = child.getPositionX();
}
if(maxX == -1){
maxX = child.getPositionX() + child.getWidth();
} else if(child.getPositionX() + child.getWidth() > maxX){
maxX = child.getPositionX() + child.getWidth();
}
}
if(minX == -1){
minX = 0;
}
if(maxX == -1){
maxX = 0;
}
return maxX - minX;
}
public int getHeight() {
int minY = -1;
int maxY = -1;
for(BitmapCharacter child : childrenElements){
if(minY == -1){
minY = child.getPositionY();
} else if(child.getPositionY() < minY){
minY = child.getPositionY();
}
if(maxY == -1){
maxY = child.getPositionY() + child.getHeight();
} else if(child.getPositionY() + child.getHeight() > maxY){
maxY = child.getPositionY() + child.getHeight();
}
}
if(minY == -1){
minY = 0;
}
if(maxY == -1){
maxY = 0;
}
return maxY - minY;
}
public int getPositionX() {
int minX = -1;
for(BitmapCharacter child : childrenElements){
if(minX == -1){
minX = child.getPositionX();
} else if(child.getPositionX() < minX){
minX = child.getPositionX();
}
}
if(minX == -1){
minX = 0;
}
return minX;
}
public int getPositionY() {
int minY = -1;
for(BitmapCharacter child : childrenElements){
if(minY == -1){
minY = child.getPositionY();
} else if(child.getPositionY() < minY){
minY = child.getPositionY();
}
}
if(minY == -1){
minY = 0;
}
return minY;
}
public boolean getVisible() {
return visible;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setPositionX(int posX) {
int deltaX = posX - this.positionX;
this.positionX = posX;
for(Element child : childrenElements){
child.setPositionX(child.getPositionX() + deltaX);
}
}
public void setPositionY(int posY) {
int deltaY = posY - this.positionY;
this.positionY = posY;
for(Element child : childrenElements){
child.setPositionY(child.getPositionY() + deltaY);
}
}
public void setVisible(boolean draw) {
this.visible = draw;
}
public void setParentWidth(int width){
parentWidth = width;
}
public void setParentHeight(int height){
this.parentHeight = height;
}
public boolean handleEvent(Event event){
boolean propagate = true;
if(event instanceof MenuEvent){
MenuEvent menuEvent = (MenuEvent)event;
if(onMenuEventCallback != null){
propagate = onMenuEventCallback.execute(menuEvent);
} else {
//default behavior
if(menuEvent.getType() == MenuEventType.INCREMENT){
propagate = false;
if(options.size() > 0){
currentOption++;
if(currentOption > options.size() - 1){
currentOption = 0;
}
String newOption = options.get(currentOption);
setText(newOption);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(newOption));
}
}
} else if(menuEvent.getType() == MenuEventType.DECREMENT){
propagate = false;
if(options.size() > 0){
currentOption--;
if(currentOption < 0){
currentOption = options.size() - 1;
}
String newOption = options.get(currentOption);
setText(newOption);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(newOption));
}
}
}
}
} else if(event instanceof FocusEvent){
FocusEvent focusEvent = (FocusEvent) event;
if(focusEvent.isFocused()){
this.focused = true;
if(onFocusCallback != null){
propagate = onFocusCallback.execute(focusEvent);
} else {
//default behavior
propagate = false;
setColor(new Vector3f(1,0,0));
}
} else {
this.focused = false;
if(onLoseFocusCallback != null){
propagate = onLoseFocusCallback.execute(focusEvent);
} else {
//default behavior
propagate = false;
setColor(new Vector3f(1,1,1));
}
}
}
return propagate;
}
@Override
public void setOnMenuEventCallback(MenuEventCallback callback) {
onMenuEventCallback = callback;
}
@Override
public void setOnValueChangeCallback(ValueChangeEventCallback callback) {
onValueChange = callback;
}
@Override
public boolean isFocused() {
return focused;
}
@Override
public void setOnFocus(FocusEventCallback callback) {
onFocusCallback = callback;
}
@Override
public void setOnLoseFocus(FocusEventCallback callback) {
onLoseFocusCallback = callback;
}
}

View File

@ -0,0 +1,36 @@
package electrosphere.renderer.ui.events;
public class ValueChangeEvent {
public static enum ValueType {
STRING,
FLOAT,
}
String valueString;
float valueFloat;
ValueType valueType;
public ValueChangeEvent(String value){
valueString = value;
valueType = ValueType.STRING;
}
public ValueChangeEvent(float value){
valueFloat = value;
valueType = ValueType.FLOAT;
}
public ValueType getType(){
return valueType;
}
public float getAsFloat(){
return valueFloat;
}
public String getAsString(){
return valueString;
}
}

View File

@ -129,4 +129,8 @@ public class Utilities {
return gson.toJson(object);
}
public static <T>T deserialize(String object, Class<T> className){
return gson.fromJson(object, className);
}
}

View File

@ -11,7 +11,8 @@
"./net/player.json",
"./net/terrain.json",
"./net/world.json",
"./net/server.json"
"./net/server.json",
"./net/character.json"
]
}