synchronized time-of-day
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
69234adb60
commit
b70febb678
@ -2081,6 +2081,7 @@ Pathing construction for farm plots
|
|||||||
Bounding sphere work
|
Bounding sphere work
|
||||||
Don't allocate contact joints for geom-geom
|
Don't allocate contact joints for geom-geom
|
||||||
Remove potential collision engine footgun
|
Remove potential collision engine footgun
|
||||||
|
Synchronized time-of-day between server and client
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import electrosphere.client.player.ClientPlayerData;
|
|||||||
import electrosphere.client.scene.ClientLevelEditorData;
|
import electrosphere.client.scene.ClientLevelEditorData;
|
||||||
import electrosphere.client.scene.ClientSceneWrapper;
|
import electrosphere.client.scene.ClientSceneWrapper;
|
||||||
import electrosphere.client.scene.ClientWorldData;
|
import electrosphere.client.scene.ClientWorldData;
|
||||||
|
import electrosphere.client.service.ClientTemporalService;
|
||||||
import electrosphere.client.sim.ClientSimulation;
|
import electrosphere.client.sim.ClientSimulation;
|
||||||
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
||||||
import electrosphere.client.terrain.foliage.FoliageCellManager;
|
import electrosphere.client.terrain.foliage.FoliageCellManager;
|
||||||
@ -17,6 +18,7 @@ import electrosphere.client.terrain.manager.ClientTerrainManager;
|
|||||||
import electrosphere.collision.CollisionEngine;
|
import electrosphere.collision.CollisionEngine;
|
||||||
import electrosphere.data.entity.common.CommonEntityType;
|
import electrosphere.data.entity.common.CommonEntityType;
|
||||||
import electrosphere.data.voxel.VoxelType;
|
import electrosphere.data.voxel.VoxelType;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.scene.Scene;
|
import electrosphere.entity.scene.Scene;
|
||||||
import electrosphere.net.client.ClientNetworking;
|
import electrosphere.net.client.ClientNetworking;
|
||||||
@ -178,11 +180,17 @@ public class ClientState {
|
|||||||
*/
|
*/
|
||||||
public int openInventoriesCount = 0;
|
public int openInventoriesCount = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
//Services
|
||||||
|
//
|
||||||
|
public final ClientTemporalService clientTemporalService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public ClientState(){
|
public ClientState(){
|
||||||
this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, new CollisionEngine(), CollisionEngine.create(new ClientChemistryCollisionCallback()), new CollisionEngine());
|
this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, new CollisionEngine(), CollisionEngine.create(new ClientChemistryCollisionCallback()), new CollisionEngine());
|
||||||
|
this.clientTemporalService = (ClientTemporalService)Globals.engineState.serviceManager.registerService(new ClientTemporalService());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
package electrosphere.client.service;
|
||||||
|
|
||||||
|
import electrosphere.engine.signal.Signal.SignalType;
|
||||||
|
import electrosphere.server.simulation.temporal.TemporalSimulator;
|
||||||
|
import electrosphere.util.math.BasicMathUtils;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import electrosphere.data.macro.temporal.MacroTemporalData;
|
||||||
|
import electrosphere.engine.signal.SignalServiceImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronizes and interpolates temporal data between server and client
|
||||||
|
*/
|
||||||
|
public class ClientTemporalService extends SignalServiceImpl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lerp rate for synchronization
|
||||||
|
*/
|
||||||
|
private static final double LERP_RATE = 1.0 / (double)TemporalSimulator.TEMPORAL_SYNC_RATE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client's stored temporal data
|
||||||
|
*/
|
||||||
|
private MacroTemporalData clientTemporalData = new MacroTemporalData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The latest temporal data from the server
|
||||||
|
*/
|
||||||
|
private MacroTemporalData latestServerData = new MacroTemporalData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock for thread-safeing the service
|
||||||
|
*/
|
||||||
|
private ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public ClientTemporalService() {
|
||||||
|
super("ClientTemporalService", new SignalType[]{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates the service
|
||||||
|
*/
|
||||||
|
public void simulate(){
|
||||||
|
lock.lock();
|
||||||
|
clientTemporalData.setTime((long)BasicMathUtils.lerp((double)clientTemporalData.getTime(), (double)latestServerData.getTime(), LERP_RATE));
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the latest server data
|
||||||
|
* @param serverData The latest server data
|
||||||
|
*/
|
||||||
|
public void setLatestData(MacroTemporalData serverData){
|
||||||
|
lock.lock();
|
||||||
|
this.latestServerData = serverData;
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -152,10 +152,20 @@ public class ClientSimulation {
|
|||||||
AttachUtils.clientUpdateAttachedEntityPositions();
|
AttachUtils.clientUpdateAttachedEntityPositions();
|
||||||
ClientInteractionEngine.updateInteractionTargetLabel();
|
ClientInteractionEngine.updateInteractionTargetLabel();
|
||||||
ToolbarPreviewWindow.checkVisibility();
|
ToolbarPreviewWindow.checkVisibility();
|
||||||
|
this.runServices();
|
||||||
// updateCellManager();
|
// updateCellManager();
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the client services
|
||||||
|
*/
|
||||||
|
private void runServices(){
|
||||||
|
Globals.profiler.beginCpuSample("ClientSimulation.runServices");
|
||||||
|
Globals.clientState.clientTemporalService.simulate();
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the skybox position to center on the player
|
* Updates the skybox position to center on the player
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
package electrosphere.data.macro.temporal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporal data associated with the macro data (ie calendar date, world age, etc)
|
||||||
|
*/
|
||||||
|
public class MacroTemporalData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount of time per day
|
||||||
|
*/
|
||||||
|
public static final long TIME_PER_DAY = 60 * 60 * 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The noon remainder amount
|
||||||
|
*/
|
||||||
|
public static final long TIME_NOON = TIME_PER_DAY / 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The midnight remainder amount
|
||||||
|
*/
|
||||||
|
public static final long TIME_MIDNIGHT = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total age of the macro data in years
|
||||||
|
*/
|
||||||
|
private long age;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time WITHIN THE CURRENT YEAR
|
||||||
|
*/
|
||||||
|
private long time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the time of the temporal data by some amount
|
||||||
|
*/
|
||||||
|
public void increment(long amount){
|
||||||
|
this.time = this.time + amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the time WITHIN THE CURRENT YEAR of the data
|
||||||
|
* @return The time
|
||||||
|
*/
|
||||||
|
public long getTime(){
|
||||||
|
return this.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the age of the world in years
|
||||||
|
* @return The age of the world in years
|
||||||
|
*/
|
||||||
|
public long getAge(){
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the time of the temporal data
|
||||||
|
* @param time The time
|
||||||
|
*/
|
||||||
|
public void setTime(long time){
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -4,9 +4,11 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import electrosphere.data.macro.temporal.MacroTemporalData;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.net.parser.net.message.LoreMessage;
|
import electrosphere.net.parser.net.message.LoreMessage;
|
||||||
import electrosphere.net.template.ClientProtocolTemplate;
|
import electrosphere.net.template.ClientProtocolTemplate;
|
||||||
|
import electrosphere.util.SerializationUtils;
|
||||||
|
|
||||||
public class LoreProtocol implements ClientProtocolTemplate<LoreMessage> {
|
public class LoreProtocol implements ClientProtocolTemplate<LoreMessage> {
|
||||||
|
|
||||||
@ -18,15 +20,20 @@ public class LoreProtocol implements ClientProtocolTemplate<LoreMessage> {
|
|||||||
@Override
|
@Override
|
||||||
public void handleSyncMessage(LoreMessage message) {
|
public void handleSyncMessage(LoreMessage message) {
|
||||||
switch(message.getMessageSubtype()){
|
switch(message.getMessageSubtype()){
|
||||||
case RESPONSERACES:
|
case RESPONSERACES: {
|
||||||
//we get back the race list as a json array, deserialize, and push into type loader
|
//we get back the race list as a json array, deserialize, and push into type loader
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<String> playableRaces = new Gson().fromJson(message.getdata(), List.class);
|
List<String> playableRaces = new Gson().fromJson(message.getdata(), List.class);
|
||||||
Globals.gameConfigCurrent.getCreatureTypeLoader().loadPlayableRaces(playableRaces);
|
Globals.gameConfigCurrent.getCreatureTypeLoader().loadPlayableRaces(playableRaces);
|
||||||
break;
|
} break;
|
||||||
case REQUESTRACES:
|
case TEMPORALUPDATE: {
|
||||||
|
MacroTemporalData temporalData = SerializationUtils.deserialize(message.getdata(), MacroTemporalData.class);
|
||||||
|
Globals.clientState.clientTemporalService.setLatestData(temporalData);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case REQUESTRACES: {
|
||||||
//silently ignore
|
//silently ignore
|
||||||
break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ public class LoreMessage extends NetworkMessage {
|
|||||||
public enum LoreMessageType {
|
public enum LoreMessageType {
|
||||||
REQUESTRACES,
|
REQUESTRACES,
|
||||||
RESPONSERACES,
|
RESPONSERACES,
|
||||||
|
TEMPORALUPDATE,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,6 +108,36 @@ public class LoreMessage extends NetworkMessage {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a message of type TemporalUpdate
|
||||||
|
*/
|
||||||
|
public static LoreMessage parseTemporalUpdateMessage(ByteBuffer byteBuffer, MessagePool pool, Map<Short,BiConsumer<NetworkMessage,ByteBuffer>> customParserMap){
|
||||||
|
if(byteBuffer.remaining() < 4){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int lenAccumulator = 0;
|
||||||
|
int datalen = byteBuffer.getInt();
|
||||||
|
lenAccumulator = lenAccumulator + datalen;
|
||||||
|
if(byteBuffer.remaining() < 4 + lenAccumulator){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
LoreMessage rVal = (LoreMessage)pool.get(MessageType.LORE_MESSAGE);
|
||||||
|
rVal.messageType = LoreMessageType.TEMPORALUPDATE;
|
||||||
|
if(datalen > 0){
|
||||||
|
rVal.setdata(ByteStreamUtils.popStringFromByteBuffer(byteBuffer, datalen));
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a message of type TemporalUpdate
|
||||||
|
*/
|
||||||
|
public static LoreMessage constructTemporalUpdateMessage(String data){
|
||||||
|
LoreMessage rVal = new LoreMessage(LoreMessageType.TEMPORALUPDATE);
|
||||||
|
rVal.setdata(data);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
void serialize(){
|
void serialize(){
|
||||||
@ -135,6 +166,21 @@ public class LoreMessage extends NetworkMessage {
|
|||||||
rawBytes[6+i] = stringBytes[i];
|
rawBytes[6+i] = stringBytes[i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TEMPORALUPDATE:
|
||||||
|
rawBytes = new byte[2+4+data.length()];
|
||||||
|
//message header
|
||||||
|
rawBytes[0] = TypeBytes.MESSAGE_TYPE_LORE;
|
||||||
|
//entity messaage header
|
||||||
|
rawBytes[1] = TypeBytes.LORE_MESSAGE_TYPE_TEMPORALUPDATE;
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(data.length());
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[2+i] = intValues[i];
|
||||||
|
}
|
||||||
|
stringBytes = data.getBytes();
|
||||||
|
for(int i = 0; i < data.length(); i++){
|
||||||
|
rawBytes[6+i] = stringBytes[i];
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
serialized = true;
|
serialized = true;
|
||||||
}
|
}
|
||||||
@ -163,6 +209,21 @@ public class LoreMessage extends NetworkMessage {
|
|||||||
//Write variable length table in packet
|
//Write variable length table in packet
|
||||||
ByteStreamUtils.writeInt(stream, data.getBytes().length);
|
ByteStreamUtils.writeInt(stream, data.getBytes().length);
|
||||||
|
|
||||||
|
//
|
||||||
|
//Write body of packet
|
||||||
|
ByteStreamUtils.writeString(stream, data);
|
||||||
|
} break;
|
||||||
|
case TEMPORALUPDATE: {
|
||||||
|
|
||||||
|
//
|
||||||
|
//message header
|
||||||
|
stream.write(TypeBytes.MESSAGE_TYPE_LORE);
|
||||||
|
stream.write(TypeBytes.LORE_MESSAGE_TYPE_TEMPORALUPDATE);
|
||||||
|
|
||||||
|
//
|
||||||
|
//Write variable length table in packet
|
||||||
|
ByteStreamUtils.writeInt(stream, data.getBytes().length);
|
||||||
|
|
||||||
//
|
//
|
||||||
//Write body of packet
|
//Write body of packet
|
||||||
ByteStreamUtils.writeString(stream, data);
|
ByteStreamUtils.writeString(stream, data);
|
||||||
|
|||||||
@ -126,6 +126,9 @@ public abstract class NetworkMessage {
|
|||||||
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES:
|
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES:
|
||||||
rVal = LoreMessage.parseResponseRacesMessage(byteBuffer,pool,customParserMap);
|
rVal = LoreMessage.parseResponseRacesMessage(byteBuffer,pool,customParserMap);
|
||||||
break;
|
break;
|
||||||
|
case TypeBytes.LORE_MESSAGE_TYPE_TEMPORALUPDATE:
|
||||||
|
rVal = LoreMessage.parseTemporalUpdateMessage(byteBuffer,pool,customParserMap);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeBytes.MESSAGE_TYPE_PLAYER:
|
case TypeBytes.MESSAGE_TYPE_PLAYER:
|
||||||
|
|||||||
@ -48,6 +48,7 @@ public class TypeBytes {
|
|||||||
*/
|
*/
|
||||||
public static final byte LORE_MESSAGE_TYPE_REQUESTRACES = 0;
|
public static final byte LORE_MESSAGE_TYPE_REQUESTRACES = 0;
|
||||||
public static final byte LORE_MESSAGE_TYPE_RESPONSERACES = 1;
|
public static final byte LORE_MESSAGE_TYPE_RESPONSERACES = 1;
|
||||||
|
public static final byte LORE_MESSAGE_TYPE_TEMPORALUPDATE = 2;
|
||||||
/*
|
/*
|
||||||
Lore packet sizes
|
Lore packet sizes
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -155,9 +155,7 @@ public class Server implements Runnable {
|
|||||||
public void broadcastMessage(NetworkMessage message){
|
public void broadcastMessage(NetworkMessage message){
|
||||||
connectListLock.acquireUninterruptibly();
|
connectListLock.acquireUninterruptibly();
|
||||||
for(ServerConnectionHandler client : activeConnections){
|
for(ServerConnectionHandler client : activeConnections){
|
||||||
if(Globals.clientState.clientPlayer == null || client.playerID != Globals.clientState.clientPlayer.getId()){
|
client.addMessagetoOutgoingQueue(message);
|
||||||
client.addMessagetoOutgoingQueue(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
connectListLock.release();
|
connectListLock.release();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ public class LoreProtocol implements ServerProtocolTemplate<LoreMessage> {
|
|||||||
connectionHandler.addMessagetoOutgoingQueue(LoreMessage.constructResponseRacesMessage(returnData));
|
connectionHandler.addMessagetoOutgoingQueue(LoreMessage.constructResponseRacesMessage(returnData));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
case TEMPORALUPDATE:
|
||||||
case RESPONSERACES:
|
case RESPONSERACES:
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
@ -33,6 +34,7 @@ public class LoreProtocol implements ServerProtocolTemplate<LoreMessage> {
|
|||||||
switch(message.getMessageSubtype()){
|
switch(message.getMessageSubtype()){
|
||||||
case REQUESTRACES:
|
case REQUESTRACES:
|
||||||
case RESPONSERACES:
|
case RESPONSERACES:
|
||||||
|
case TEMPORALUPDATE:
|
||||||
//silently ignore
|
//silently ignore
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,72 +37,67 @@ public class Realm {
|
|||||||
/**
|
/**
|
||||||
* The set containing all data cells loaded into this realm
|
* The set containing all data cells loaded into this realm
|
||||||
*/
|
*/
|
||||||
Set<ServerDataCell> loadedDataCells = new HashSet<ServerDataCell>();
|
private Set<ServerDataCell> loadedDataCells = new HashSet<ServerDataCell>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this is the cell that all players loading into the game (via connection startup, death, etc) reside in
|
* this is the cell that all players loading into the game (via connection startup, death, etc) reside in
|
||||||
*/
|
*/
|
||||||
ServerDataCell loadingCell = new ServerDataCell(new Scene());
|
private ServerDataCell loadingCell = new ServerDataCell(new Scene());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data cell that will contain in-inventory items
|
* The data cell that will contain in-inventory items
|
||||||
*/
|
*/
|
||||||
ServerDataCell inventoryCell = new ServerDataCell(new Scene());
|
private ServerDataCell inventoryCell = new ServerDataCell(new Scene());
|
||||||
|
|
||||||
/**
|
|
||||||
* resolver for entity -> data cell within this realm
|
|
||||||
*/
|
|
||||||
EntityDataCellMapper entityDataCellMapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* provides functions for relating data cells to physical locations (eg creating cells, deleting cells, etc)
|
* provides functions for relating data cells to physical locations (eg creating cells, deleting cells, etc)
|
||||||
*/
|
*/
|
||||||
DataCellManager dataCellManager;
|
private DataCellManager dataCellManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The pathfinding manager
|
* The pathfinding manager
|
||||||
*/
|
*/
|
||||||
PathfindingManager pathfindingManager;
|
private PathfindingManager pathfindingManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entity physics collision checking engine
|
* Main entity physics collision checking engine
|
||||||
*/
|
*/
|
||||||
CollisionEngine collisionEngine;
|
private CollisionEngine collisionEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The chemistry collision engine
|
* The chemistry collision engine
|
||||||
*/
|
*/
|
||||||
CollisionEngine chemistryEngine;
|
private CollisionEngine chemistryEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hitbox manager for the realm
|
* Hitbox manager for the realm
|
||||||
*/
|
*/
|
||||||
HitboxManager hitboxManager;
|
private HitboxManager hitboxManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The world data about the server
|
* The world data about the server
|
||||||
*/
|
*/
|
||||||
ServerWorldData serverWorldData;
|
private ServerWorldData serverWorldData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The content manager
|
* The content manager
|
||||||
*/
|
*/
|
||||||
ServerContentManager serverContentManager;
|
private ServerContentManager serverContentManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The macro data for the realm
|
* The macro data for the realm
|
||||||
*/
|
*/
|
||||||
MacroData macroData;
|
private MacroData macroData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The instanceId of the scene that was loaded with this realm
|
* The instanceId of the scene that was loaded with this realm
|
||||||
*/
|
*/
|
||||||
int sceneInstanceId = NO_SCENE_INSTANCE;
|
private int sceneInstanceId = NO_SCENE_INSTANCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of available spawnpoints
|
* The list of available spawnpoints
|
||||||
*/
|
*/
|
||||||
List<Vector3d> spawnPoints = new LinkedList<Vector3d>();
|
private List<Vector3d> spawnPoints = new LinkedList<Vector3d>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Realm constructor
|
* Realm constructor
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import electrosphere.data.macro.temporal.MacroTemporalData;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.server.datacell.ServerWorldData;
|
import electrosphere.server.datacell.ServerWorldData;
|
||||||
@ -82,6 +83,11 @@ public class MacroData {
|
|||||||
*/
|
*/
|
||||||
private MacroPathCache pathingCache = new MacroPathCache();
|
private MacroPathCache pathingCache = new MacroPathCache();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro temporal data
|
||||||
|
*/
|
||||||
|
private MacroTemporalData temporalData = new MacroTemporalData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a world
|
* Generates a world
|
||||||
* @param seed The seed for the world
|
* @param seed The seed for the world
|
||||||
@ -396,5 +402,13 @@ public class MacroData {
|
|||||||
public MacroPathCache getPathCache(){
|
public MacroPathCache getPathCache(){
|
||||||
return this.pathingCache;
|
return this.pathingCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the temporal data
|
||||||
|
* @return The temporal data
|
||||||
|
*/
|
||||||
|
public MacroTemporalData getTemporalData(){
|
||||||
|
return this.temporalData;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import electrosphere.server.macro.civilization.town.Town;
|
|||||||
import electrosphere.server.macro.civilization.town.TownSimulator;
|
import electrosphere.server.macro.civilization.town.TownSimulator;
|
||||||
import electrosphere.server.service.CharacterService;
|
import electrosphere.server.service.CharacterService;
|
||||||
import electrosphere.server.simulation.chara.CharaSimulation;
|
import electrosphere.server.simulation.chara.CharaSimulation;
|
||||||
|
import electrosphere.server.simulation.temporal.TemporalSimulator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the macro-level (ie virtual, non-physics based) simulation
|
* Performs the macro-level (ie virtual, non-physics based) simulation
|
||||||
@ -53,6 +54,11 @@ public class MacroSimulation {
|
|||||||
TownSimulator.simualte(town);
|
TownSimulator.simualte(town);
|
||||||
}
|
}
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
|
|
||||||
|
//
|
||||||
|
//temporal update
|
||||||
|
TemporalSimulator.simulate(realm);
|
||||||
|
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
package electrosphere.server.simulation.temporal;
|
||||||
|
|
||||||
|
import electrosphere.data.macro.temporal.MacroTemporalData;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.net.parser.net.message.LoreMessage;
|
||||||
|
import electrosphere.server.datacell.Realm;
|
||||||
|
import electrosphere.util.SerializationUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporal macro data simulator
|
||||||
|
*/
|
||||||
|
public class TemporalSimulator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of temporal ticks per sim frame
|
||||||
|
*/
|
||||||
|
private static final int TEMPORAL_TICKS_PER_SIM_FRAME = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rate at which to send synchronization packets to clients to update temporal data
|
||||||
|
*/
|
||||||
|
public static final int TEMPORAL_SYNC_RATE = 600;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates the temporal macro data
|
||||||
|
* @param macroData The macro data
|
||||||
|
*/
|
||||||
|
public static void simulate(Realm realm){
|
||||||
|
MacroTemporalData temporalData = realm.getMacroData().getTemporalData();
|
||||||
|
temporalData.increment(TemporalSimulator.TEMPORAL_TICKS_PER_SIM_FRAME);
|
||||||
|
if(temporalData.getTime() % TEMPORAL_SYNC_RATE == 0){
|
||||||
|
String data = SerializationUtils.serialize(temporalData);
|
||||||
|
Globals.serverState.server.broadcastMessage(LoreMessage.constructTemporalUpdateMessage(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
src/main/java/electrosphere/util/math/BasicMathUtils.java
Normal file
19
src/main/java/electrosphere/util/math/BasicMathUtils.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package electrosphere.util.math;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic math functions
|
||||||
|
*/
|
||||||
|
public class BasicMathUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Linearly interpolates between two doubles
|
||||||
|
* @param a The first double
|
||||||
|
* @param b The second double
|
||||||
|
* @param percent The percentage to interpolate between them
|
||||||
|
* @return The interpolated value
|
||||||
|
*/
|
||||||
|
public static double lerp(double a, double b, double percent){
|
||||||
|
return a * (1.0 - percent) + (b * percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -22,6 +22,13 @@
|
|||||||
"data" : [
|
"data" : [
|
||||||
"data"
|
"data"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"messageName" : "TemporalUpdate",
|
||||||
|
"description" : "Sends the current temporal data to the client",
|
||||||
|
"data" : [
|
||||||
|
"data"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user