Full flow environment generation for gridded chunks

This commit is contained in:
austin 2024-02-25 19:59:40 -05:00
parent c96cecf21d
commit fa11fc9bec
31 changed files with 535 additions and 55 deletions

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
#Sun Nov 05 10:58:49 EST 2023
buildNumber=12
#Sun Feb 25 14:43:29 EST 2024
buildNumber=13

View File

@ -0,0 +1,27 @@
# Macro World Partitioning
Different terrain levels:
Sky 1: 12000m - 14000m
Sky 1: 10000m - 12000m
Sky 1: 8000m - 10000m
Surface: 3000m - 8000m
Deep Earth 1: 2000m - 3000m
Deep Earth 2: 1000m - 2000m
Deep Earth 3: 0m - 1000m
Ocean starts at 4000m

View File

@ -0,0 +1,80 @@
# Entity Spawning
Recommended flow and tips for spawning entities from the server
## High Level Overview
#### Spawning a creature
```
CreatureTemplate template = <get creature template somehow>;
String raceName = template.getCreatureType();
//spawn creature in world
Realm realm = Globals.realmManager.getRealms().iterator().next();
Entity newCreature = CreatureUtils.serverSpawnBasicCreature(realm,new Vector3d(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z),raceName,template);
```
#### Spawning a plant
```
CreatureTemplate template = <get creature template somehow>;
String raceName = template.getCreatureType();
//spawn creature in world
Realm realm = Globals.realmManager.getRealms().iterator().next();
Entity newCreature = CreatureUtils.serverSpawnBasicCreature(realm,new Vector3d(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z),raceName,template);
```
## Major Usage Notes
- TODO
## Main Classes
[CreatureUtils.java](@ref #electrosphere.entity.types.creature.CreatureUtils) - Provides utilities for spawning creatures into the game world for both server and client
## Code Organization and Best Practices
#### Startup
#### Usage
## Terminology
## Future Goals

View File

@ -108,6 +108,10 @@
{
"name" : "propertyValueString",
"type" : "VAR_STRING"
},
{
"name" : "foliageSeed",
"type" : "FIXED_LONG"
}
],
"messageTypes" : [
@ -291,6 +295,17 @@
"bone",
"targetID"
]
},
{
"messageName" : "SpawnFoliageSeed",
"data" : [
"entityID",
"creatureTemplate",
"foliageSeed",
"positionX",
"positionY",
"positionZ"
]
}

View File

@ -159,9 +159,11 @@ public class CollisionEngine {
}
public void clearCollidableImpulseLists(){
spaceLock.acquireUninterruptibly();
for(Collidable collidable : collidableList){
collidable.clear();
}
spaceLock.release();
}
public List<Collidable> getCollidables(){
@ -375,9 +377,11 @@ public class CollisionEngine {
}
public void registerCollisionObject(DBody body, Collidable collidable){
spaceLock.acquireUninterruptibly();
registerPhysicsObject(body);
bodyPointerMap.put(body,collidable);
collidableList.add(collidable);
spaceLock.release();
}
public void listBodyPositions(){

View File

@ -62,6 +62,7 @@ import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.RawFontMap;
import electrosphere.script.ScriptEngine;
import electrosphere.server.ai.AIManager;
import electrosphere.server.content.ServerContentManager;
import electrosphere.server.datacell.EntityDataCellMapper;
import electrosphere.server.datacell.RealmManager;
import electrosphere.server.db.DatabaseController;
@ -244,6 +245,9 @@ public class Globals {
// public static boolean LOAD_TERRAIN = true;
public static ServerTerrainManager serverTerrainManager;
public static Vector3d spawnPoint = new Vector3d(0,0,0);
//content manager
public static ServerContentManager serverContentManager;
//manages all models loaded into memory
public static AssetManager assetManager;

View File

@ -14,6 +14,7 @@ import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.content.ServerContentManager;
import electrosphere.server.saves.SaveUtils;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.FileUtils;
@ -59,6 +60,7 @@ public class ArenaLoading {
private static void initServerArenaWorldData(){
Globals.serverWorldData = ServerWorldData.createArenaWorld();
Globals.serverContentManager = ServerContentManager.createServerContentManager();
Globals.spawnPoint = new Vector3d(1,0.1,1);
// Globals.serverTerrainManager.getChunk(0, 0).addModification(new TerrainModification(0,0,5,5,5));
}

View File

@ -254,13 +254,13 @@ public class ClientLoading {
// EntityUtils.getPosition(tree).set(5,0,i * 5);
// }
for(int x = 0; x < 5; x++){
for(int z = 0; z < 5; z++){
Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong());
ClientEntityUtils.initiallyPositionEntity(tree, new Vector3d(5 + x * 5,0,5 + z * 5));
EntityUtils.getScale(tree).set(0.5f);
}
}
// for(int x = 0; x < 5; x++){
// for(int z = 0; z < 5; z++){
// Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong());
// ClientEntityUtils.initiallyPositionEntity(tree, new Vector3d(5 + x * 5,0,5 + z * 5));
// EntityUtils.getScale(tree).set(0.5f);
// }
// }
}

View File

@ -16,6 +16,7 @@ import electrosphere.menu.WindowUtils;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.renderer.ui.Window;
import electrosphere.server.content.ServerContentManager;
import electrosphere.server.saves.SaveUtils;
import electrosphere.server.terrain.generation.OverworldChunkGenerator;
import electrosphere.server.terrain.manager.ServerTerrainManager;
@ -51,10 +52,13 @@ public class DebugSPWorldLoading {
SaveUtils.loadSave("random_sp_world");
//start initializing game datastructures
// Globals.griddedDataCellManager.init(Globals.serverWorldData);
LoadingUtils.initGriddedRealm();
//initialize the "virtual" objects simulation
LoadingUtils.initMacroSimulation();
Globals.serverContentManager = ServerContentManager.createServerContentManager();
LoadingUtils.initGriddedRealm();
LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT);
//init authentication

View File

@ -26,15 +26,10 @@ public class EntityCreationUtils {
Entity rVal = EntityUtils.spawnSpatialEntity();
//register to global entity id lookup table
EntityLookupUtils.registerServerEntity(rVal);
//register to data cell
ServerDataCell entityDataCell = realm.getDataCellManager().tryCreateCellAtPoint(position);
entityDataCell.getScene().registerEntity(rVal);
//maps this entity to its realm
Globals.realmManager.mapEntityToRealm(rVal, realm);
//position entity
ServerEntityUtils.initiallyPositionEntity(realm,rVal,position);
//enable behavior tree tracking
ServerBehaviorTreeUtils.registerEntity(rVal);
//register to entity data cell mapper
realm.getEntityDataCellMapper().registerEntity(rVal, entityDataCell);
return rVal;
}

View File

@ -241,6 +241,8 @@ public class EntityDataStrings {
public static final String FOLIAGE_IS_FOLIAGE = "foliageIsFoliage";
public static final String FOLIAGE_TYPE = "foliageType";
public static final String FOLIAGE_AMBIENT_TREE = "foliageAmbientTree";
public static final String FOLIAGE_SEED = "foliageSeed";
public static final String FOLIAGE_IS_SEEDED = "foliageIsSeeded";
/*
Equip state

View File

@ -11,6 +11,7 @@ public class EntityTags {
public static final String TARGETABLE = "targetable";
public static final String LIFE_STATE = "lifeState";
public static final String CREATURE = "creature";
public static final String FOLIAGE = "foliage";
public static final String UI = "ui";
public static final String DRAWABLE = "drawable";
public static final String DRAW_INSTANCED = "drawInstanced"; //if it's instanced, but not necessarily managed by a service (ie a tree branch)

View File

@ -41,6 +41,7 @@ public class Scene {
tagEntityMap.put(EntityTags.CREATURE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.UI, new HashSet<Entity>());
tagEntityMap.put(EntityTags.DRAWABLE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.DRAW_INSTANCED, new HashSet<Entity>());
tagEntityMap.put(EntityTags.LIGHT, new HashSet<Entity>());
tagEntityMap.put(EntityTags.ITEM, new HashSet<Entity>());
tagEntityMap.put(EntityTags.GRAVITY, new HashSet<Entity>());

View File

@ -32,6 +32,8 @@ public class ServerEntityUtils {
//initialize server datacell tracking of this entity
realm.initializeServerSideEntity(entity, cell);
}
//register to entity data cell mapper
realm.getEntityDataCellMapper().registerEntity(entity, cell);
//reposition entity
CollisionObjUtils.serverPositionCharacter(entity, position);
}

View File

@ -6,16 +6,25 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.idle.IdleTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.tree.ProceduralTree;
import electrosphere.game.data.foliage.type.FoliageType;
import electrosphere.game.data.foliage.type.PhysicsObject;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.server.player.Player;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.ServerEntityTagUtils;
import electrosphere.util.Utilities;
import java.util.List;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector4f;
@ -29,10 +38,15 @@ public class FoliageUtils {
* @param type The type of foliage object
* @return The entity for the foliage
*/
public static Entity spawnBasicFoliage(String type){
public static Entity spawnBasicFoliage(String type, long seed){
FoliageType rawType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getModelPath());
Entity rVal;
if(rawType.getTreeModel()!=null){
rVal = ProceduralTree.clientGenerateProceduralTree(type, 0);
} else {
rVal = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getModelPath());
}
for(String token : rawType.getTokens()){
switch(token){
@ -54,6 +68,104 @@ public class FoliageUtils {
rVal.putData(EntityDataStrings.FOLIAGE_TYPE, type);
return rVal;
}
/**
* Spawns a tree foliage on the server
* @param realm The realm to spawn on
* @param position The position of the tree
* @param type the type of tree
* @param seed the seed for the tree
* @return the tree entity
*/
public static Entity serverSpawnTreeFoliage(Realm realm, Vector3d position, String type, long seed){
FoliageType rawType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
Entity rVal = ProceduralTree.serverGenerateProceduralTree(realm, position, rawType, seed);
for(String token : rawType.getTokens()){
switch(token){
case "BLENDER_TRANSFORM":
ActorUtils.applyBlenderTransformer(rVal);
break;
case "BLENDER_ROTATION":
ActorUtils.applyBlenderRotation(rVal);
break;
case "PARTICLE_SPAWNER":
break;
}
}
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.FOLIAGE);
rVal.putData(EntityDataStrings.FOLIAGE_IS_FOLIAGE, true);
rVal.putData(EntityDataStrings.FOLIAGE_TYPE, rawType);
rVal.putData(EntityDataStrings.FOLIAGE_SEED, seed);
rVal.putData(EntityDataStrings.FOLIAGE_IS_SEEDED, true);
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
return rVal;
}
/**
* Gets the seed for a given foliage item
* @param entity The entity
* @return The seed
*/
public static long getFoliageSeed(Entity entity){
return (long)entity.getData(EntityDataStrings.FOLIAGE_SEED);
}
/**
* Gets the type of foliage
* @param entity the entity
* @return The type
*/
public static FoliageType getFoliageType(Entity entity){
return (FoliageType)entity.getData(EntityDataStrings.FOLIAGE_TYPE);
}
/**
* Gets whether the entity is foliage or not
* @param entity The entity
* @return true if is foliage, false otherwise
*/
public static boolean isFoliage(Entity entity){
return entity.getData(EntityDataStrings.FOLIAGE_IS_FOLIAGE)!=null;
}
/**
* Gets whether the entity has a foliage seed or not
* @param entity The entity
* @return true if is has seed, false otherwise
*/
public static boolean hasSeed(Entity entity){
return entity.getData(EntityDataStrings.FOLIAGE_IS_SEEDED)!=null;
}
/**
* Sends a given foliage entity to a given player
* @param player The player
* @param foliage The foliage entity
*/
public static void sendFoliageToPlayer(Player player, Entity foliage){
int id = foliage.getId();
FoliageType type = FoliageUtils.getFoliageType(foliage);
Vector3d position = EntityUtils.getPosition(foliage);
if(FoliageUtils.hasSeed(foliage)){
long seed = FoliageUtils.getFoliageSeed(foliage);
NetworkMessage message = EntityMessage.constructSpawnFoliageSeedMessage(
id,
type.getName(),
seed,
position.x,
position.y,
position.z
);
player.addMessage(message);
} else {
//still needs to be implemented with new network message
throw new UnsupportedOperationException("Tried to spawn a foliage object that doesn't have a seed.");
}
}
}

View File

@ -35,6 +35,9 @@ import electrosphere.game.data.foliage.type.TreeModel;
import electrosphere.renderer.actor.instance.InstancedActor;
import electrosphere.renderer.buffer.ShaderAttribute;
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
import electrosphere.server.datacell.Realm;
import electrosphere.server.poseactor.PoseActor;
import electrosphere.server.poseactor.PoseActorUtils;
/**
* Used for generating procedural trees
@ -146,7 +149,7 @@ public class ProceduralTree {
return trunkChild;
}
public static List<Entity> clientGenerateBranchesAlt(
private static List<Entity> clientGenerateBranchesAlt(
TreeModel type,
Entity parent,
Random rand,
@ -356,6 +359,37 @@ public class ProceduralTree {
return rVal;
}
/**
* Server side function to generate a tree
* @param type The type of tree as a string
* @param seed The seed (lol) for the tree
* @return The top level tree entity
*/
public static Entity serverGenerateProceduralTree(Realm realm, Vector3d position, FoliageType foliageType, long seed){
//call recursive branching routine to generate branches from trunk + leaf blobs
TreeModel treeModel = foliageType.getTreeModel();
//generate trunk
Entity trunkChild = EntityCreationUtils.createServerEntity(realm,position);
//attach physics
DBody rigidBody = CollisionBodyCreation.createCylinderBody(
realm.getCollisionEngine(),
treeModel.getPhysicsBody().getDimension1(),
treeModel.getPhysicsBody().getDimension2()
);
Collidable collidable = new Collidable(trunkChild, Collidable.TYPE_OBJECT);
trunkChild.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);
trunkChild.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(0,treeModel.getPhysicsBody().getOffsetY(),0));
trunkChild.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, treeModel.getPhysicsBody());
trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
return trunkChild;
}
// /**
// * Generates branches
// * @param type The type of branch

View File

@ -101,11 +101,11 @@ public class ServerWorldData {
}
public int convertRealToChunkSpace(double real){
return (int)Math.floor(real / dynamicInterpolationRatio);
return (int)Math.floor(real / ServerTerrainChunk.CHUNK_DIMENSION);
}
public float convertChunkToRealSpace(int chunk){
return chunk * dynamicInterpolationRatio;
return chunk * ServerTerrainChunk.CHUNK_DIMENSION;
}
public double getRelativeLocation(double real, int world){
@ -116,6 +116,44 @@ public class ServerWorldData {
return isArena;
}
public int convertRealToWorld(double real){
return convertRealToChunkSpace(real);
}
public double convertWorldToReal(int world){
return convertChunkToRealSpace(world);
}
public Vector3i convertRealToChunkSpace(Vector3d position){
return new Vector3i(
convertRealToChunkSpace(position.x),
convertRealToChunkSpace(position.y),
convertRealToChunkSpace(position.z)
);
}
/**
* Converts a world space vector to a real space vector
* @param position The world space vector
* @return The real space vector
*/
public Vector3d convertWorldToRealSpace(Vector3i position){
return new Vector3d(
convertWorldToReal(position.x),
convertWorldToReal(position.y),
convertWorldToReal(position.z)
);
}
public Vector3i convertRealToVoxelSpace(Vector3d position){
return new Vector3i(
(int)Math.floor(position.x - convertChunkToRealSpace(convertRealToChunkSpace(position.x))),
(int)Math.floor(position.y - convertChunkToRealSpace(convertRealToChunkSpace(position.y))),
(int)Math.floor(position.z - convertChunkToRealSpace(convertRealToChunkSpace(position.z)))
);
}
/**
* Converts a real coordinate to a world space coordinate
* @param position The real coordinate
@ -128,18 +166,5 @@ public class ServerWorldData {
convertRealToChunkSpace(position.z)
);
}
/**
* Converts a real coordinate to a voxel space coordinate, relative to the containing chunk of the real coordinate
* @param position The real coordinate
* @return The voxel space coordinate
*/
public Vector3i convertRealToVoxelSpace(Vector3d position){
return new Vector3i(
(int)Math.floor(position.x - convertChunkToRealSpace(convertRealToChunkSpace(position.x))),
(int)Math.floor(position.y - convertChunkToRealSpace(convertRealToChunkSpace(position.y))),
(int)Math.floor(position.z - convertChunkToRealSpace(convertRealToChunkSpace(position.z)))
);
}
}

View File

@ -25,7 +25,7 @@ public class LoggerInterface {
loggerFileIO = new Logger(LogLevel.WARNING);
loggerGameLogic = new Logger(LogLevel.WARNING);
loggerRenderer = new Logger(LogLevel.WARNING);
loggerEngine = new Logger(LogLevel.DEBUG);
loggerEngine = new Logger(LogLevel.WARNING);
loggerAuth = new Logger(LogLevel.WARNING);
loggerDB = new Logger(LogLevel.WARNING);
loggerStartup.INFO("Initialized loggers");

View File

@ -12,6 +12,7 @@ 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.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage;
@ -113,6 +114,13 @@ public class EntityProtocol {
break;
case SETFACING:
break;
case SPAWNFOLIAGESEED: {
LoggerInterface.loggerNetworking.DEBUG("Spawn foliage " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ());
String type = message.getcreatureTemplate();
newlySpawnedEntity = FoliageUtils.spawnBasicFoliage(type,message.getfoliageSeed());
ClientEntityUtils.initiallyPositionEntity(newlySpawnedEntity, new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()));
Globals.clientSceneWrapper.mapIdToId(newlySpawnedEntity.getId(), message.getentityID());
} break;
}
}

View File

@ -26,6 +26,7 @@ public class EntityMessage extends NetworkMessage {
SETBTREEPROPERTYSTRING,
SETBTREEPROPERTYENUM,
ATTACHENTITYTOENTITY,
SPAWNFOLIAGESEED,
}
EntityMessageType messageType;
@ -55,6 +56,7 @@ public class EntityMessage extends NetworkMessage {
float propertyValueFloat;
double propertyValueDouble;
String propertyValueString;
long foliageSeed;
EntityMessage(EntityMessageType messageType){
this.type = MessageType.ENTITY_MESSAGE;
@ -273,6 +275,14 @@ public class EntityMessage extends NetworkMessage {
this.propertyValueString = propertyValueString;
}
public long getfoliageSeed() {
return foliageSeed;
}
public void setfoliageSeed(long foliageSeed) {
this.foliageSeed = foliageSeed;
}
static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteBuffer.read(2);
}
@ -367,6 +377,8 @@ public class EntityMessage extends NetworkMessage {
}
case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY:
return EntityMessage.canParseattachEntityToEntityMessage(byteBuffer);
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED:
return EntityMessage.canParseSpawnFoliageSeedMessage(byteBuffer);
}
return false;
}
@ -921,6 +933,64 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static boolean canParseSpawnFoliageSeedMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){
return false;
}
int creatureTemplateSize = 0;
if(currentStreamLength < 10){
return false;
} else {
temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteBuffer.peek(6 + 3));
creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
}
if(currentStreamLength < 10 + creatureTemplateSize){
return false;
}
if(currentStreamLength < 18 + creatureTemplateSize){
return false;
}
if(currentStreamLength < 26 + creatureTemplateSize){
return false;
}
if(currentStreamLength < 34 + creatureTemplateSize){
return false;
}
if(currentStreamLength < 42 + creatureTemplateSize){
return false;
}
return true;
}
public static EntityMessage parseSpawnFoliageSeedMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNFOLIAGESEED);
stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setfoliageSeed(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal;
}
public static EntityMessage constructSpawnFoliageSeedMessage(int entityID,String creatureTemplate,long foliageSeed,double positionX,double positionY,double positionZ){
EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNFOLIAGESEED);
rVal.setentityID(entityID);
rVal.setcreatureTemplate(creatureTemplate);
rVal.setfoliageSeed(foliageSeed);
rVal.setpositionX(positionX);
rVal.setpositionY(positionY);
rVal.setpositionZ(positionZ);
rVal.serialize();
return rVal;
}
@Override
void serialize(){
byte[] intValues = new byte[8];
@ -1435,6 +1505,41 @@ public class EntityMessage extends NetworkMessage {
rawBytes[10+bone.length()+i] = intValues[i];
}
break;
case SPAWNFOLIAGESEED:
rawBytes = new byte[2+4+4+creatureTemplate.length()+8+8+8+8];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED;
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.serializeLongToBytes(foliageSeed);
for(int i = 0; i < 8; i++){
rawBytes[10+creatureTemplate.length()+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
for(int i = 0; i < 8; i++){
rawBytes[18+creatureTemplate.length()+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
for(int i = 0; i < 8; i++){
rawBytes[26+creatureTemplate.length()+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
for(int i = 0; i < 8; i++){
rawBytes[34+creatureTemplate.length()+i] = intValues[i];
}
break;
}
serialized = true;
}

View File

@ -131,6 +131,11 @@ SYNCHRONIZATION_MESSAGE,
rVal = EntityMessage.parseattachEntityToEntityMessage(byteBuffer);
}
break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED:
if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseSpawnFoliageSeedMessage(byteBuffer);
}
break;
}
break;
case TypeBytes.MESSAGE_TYPE_LORE:

View File

@ -35,6 +35,7 @@ Message categories
public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYSTRING = 15;
public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM = 16;
public static final byte ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY = 17;
public static final byte ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED = 18;
/*
Entity packet sizes
*/

View File

@ -164,7 +164,7 @@ public class Mesh {
Matrix4d vertexPretransform = new Matrix4d().identity();
if(metadata != null){
System.out.println("Pretransforming");
LoggerInterface.loggerRenderer.DEBUG("Pretransforming");
vertexPretransform.translationRotateScale(metadata.getOffset(), metadata.getRotation(), metadata.getScale());
}

View File

@ -3,12 +3,20 @@ package electrosphere.server.content;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.tree.ProceduralTree;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.datacell.GriddedDataCellManager;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import java.util.List;
import java.util.Random;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector3i;
@ -19,9 +27,10 @@ import org.joml.Vector3i;
public class EnvironmentGenerator {
public static void generatePlains(ServerDataCell cell, Vector3i worldPos, long randomizer){
public static void generatePlains(Realm realm, ServerDataCell cell, Vector3i worldPos, long randomizer){
Random rand = new Random(randomizer);
int targetNum = (int)(rand.nextFloat() * 10) + 10;
LoggerInterface.loggerGameLogic.DEBUG("generate plains");
for(int i = 0; i < targetNum; i++){
// Entity newTree = FoliageUtils.spawnBasicFoliage("FallOak1");
// cell.getScene().registerEntity(newTree);
@ -33,4 +42,18 @@ public class EnvironmentGenerator {
// EntityUtils.getPosition(newTree).set(posX,posY,posZ);
}
}
public static void generateForest(Realm realm, ServerDataCell cell, Vector3i worldPos, long randomizer){
Random rand = new Random(randomizer);
int targetNum = (int)(rand.nextFloat() * 5) + 5;
LoggerInterface.loggerGameLogic.DEBUG("generate forest");
for(int i = 0; i < targetNum; i++){
Vector3d position = new Vector3d(
Globals.serverWorldData.convertWorldToReal(worldPos.x) + rand.nextFloat() * 5,
0,
Globals.serverWorldData.convertWorldToReal(worldPos.z) + rand.nextFloat() * 5
);
Entity tree = FoliageUtils.serverSpawnTreeFoliage(realm, position, "oak", rand.nextLong());
}
}
}

View File

@ -3,26 +3,37 @@ package electrosphere.server.content;
import org.joml.Vector3i;
import electrosphere.engine.Globals;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.pathfinding.NavMeshUtils;
public class ServerContentManager {
private ServerContentManager(){
}
public static ServerContentManager createServerContentManager(){
return new ServerContentManager();
}
public void generateContentForDataCell(Vector3i worldPos, ServerDataCell cell){
public void generateContentForDataCell(Realm realm, Vector3i worldPos, ServerDataCell cell){
if(!Globals.serverWorldData.isArena()){ //in other words, if not arena mode
//if on disk (has already been generated)
//else create from scratch
EnvironmentGenerator.generatePlains(cell, worldPos, 0);
EnvironmentGenerator.generateForest(realm, cell, worldPos, 0);
}
cell.setNavMesh(
NavMeshUtils.createMeshFromChunk(Globals.serverTerrainManager.getChunk(
worldPos.x,
worldPos.y,
worldPos.z
),
Globals.navMeshManager.getBlockerCache().getBlocker(worldPos.x, worldPos.z))
);
//TODO: generate navmesh
// cell.setNavMesh(
// NavMeshUtils.createMeshFromChunk(Globals.serverTerrainManager.getChunk(
// worldPos.x,
// worldPos.y,
// worldPos.z
// ),
// Globals.navMeshManager.getBlockerCache().getBlocker(worldPos.x, worldPos.z))
// );
}

View File

@ -17,6 +17,7 @@ import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.player.Player;
import electrosphere.server.content.ServerContentManager;
import electrosphere.server.datacell.interfaces.DataCellManager;
import electrosphere.server.datacell.interfaces.VoxelCellManager;
import electrosphere.server.datacell.physics.PhysicsDataCell;
@ -44,14 +45,17 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
ServerTerrainManager serverTerrainManager;
//lock for terrain editing
Semaphore terrainEditLock = new Semaphore(1);
//manager for getting entities to fill in a cell
ServerContentManager serverContentManager;
/**
* Constructor
* @param parent The gridded data cell manager's parent realm
*/
public GriddedDataCellManager(Realm parent, ServerTerrainManager serverTerrainManager) {
public GriddedDataCellManager(Realm parent, ServerTerrainManager serverTerrainManager, ServerContentManager serverContentManager) {
this.parent = parent;
this.serverTerrainManager = serverTerrainManager;
this.serverContentManager = serverContentManager;
}
/**
@ -389,6 +393,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
ServerDataCell rVal = parent.createNewCell();
groundDataCells.put(getServerDataCellKey(worldPos),rVal);
cellPositionMap.put(rVal,new Vector3i(worldPos));
serverContentManager.generateContentForDataCell(parent, worldPos, rVal);
return rVal;
}
@ -450,7 +455,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
* @param cell The data cell
* @return The world position
*/
private Vector3i getCellWorldPosition(ServerDataCell cell){
public Vector3i getCellWorldPosition(ServerDataCell cell){
return cellPositionMap.get(cell);
}

View File

@ -53,7 +53,7 @@ public class RealmManager {
//create realm
Realm realm = new Realm(collisionEngine, new HitboxManager());
//create function classes
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm,Globals.serverTerrainManager);
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm,Globals.serverTerrainManager,Globals.serverContentManager);
EntityDataCellMapper entityDataCellMapper = new EntityDataCellMapper();
//init gridded manager
griddedDataCellManager.init(serverWorldData);

View File

@ -4,6 +4,7 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.Scene;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.entity.types.structure.StructureUtils;
import electrosphere.game.server.character.Character;
@ -153,6 +154,9 @@ public class ServerDataCell {
if(StructureUtils.isStructure(entity)){
StructureUtils.sendStructureToPlayer(player, entity);
}
if(FoliageUtils.isFoliage(entity)){
FoliageUtils.sendFoliageToPlayer(player, entity);
}
}

View File

@ -37,6 +37,14 @@ public interface DataCellManager {
*/
public ServerDataCell getDataCellAtPoint(Vector3d point);
/**
* Gets the world position of a given data cell
* @param cell The data cell
* @return The world position
*/
public Vector3i getCellWorldPosition(ServerDataCell cell);
/**
* Tries to create a data cell at a given real point
* @param point The real point

View File

@ -5,6 +5,7 @@ import java.util.List;
import electrosphere.engine.Globals;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.content.ServerContentManager;
import electrosphere.server.db.DatabaseUtils;
import electrosphere.server.terrain.generation.OverworldChunkGenerator;
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
@ -111,6 +112,7 @@ public class SaveUtils {
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0,new OverworldChunkGenerator());
SaveUtils.loadTerrainAndDB(currentSaveName);
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
Globals.serverContentManager = ServerContentManager.createServerContentManager();
Globals.realmManager.createGriddedRealm(Globals.serverWorldData);
return true;
}

View File

@ -60,10 +60,10 @@ public class ChunkDiskMap {
* @param saveName The save name
*/
public void init(String saveName){
System.out.println("INIT CHUNK MAP " + saveName);
LoggerInterface.loggerEngine.DEBUG("INIT CHUNK MAP " + saveName);
if(FileUtils.getSaveFile(saveName, "chunk.map").exists()){
worldPosFileMap = FileUtils.loadObjectFromSavePath(saveName, "chunk.map", Map.class);
System.out.println("POS FILE MAP: " + worldPosFileMap.keySet());
LoggerInterface.loggerEngine.DEBUG("POS FILE MAP: " + worldPosFileMap.keySet());
} else {
worldPosFileMap = new HashMap<String,String>();
}
@ -106,7 +106,7 @@ public class ChunkDiskMap {
* @return The server terrain chunk if it exists, null otherwise
*/
public ServerTerrainChunk getTerrainChunk(int worldX, int worldY, int worldZ){
System.out.println("Load chunk " + worldX + " " + worldY + " " + worldZ);
LoggerInterface.loggerEngine.INFO("Load chunk " + worldX + " " + worldY + " " + worldZ);
ServerTerrainChunk rVal = null;
if(containsTerrainAtPosition(worldX, worldY, worldZ)){
//read file