hook up content generation to test gen realm
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
afabf5595e
commit
e12dd55703
@ -51,7 +51,20 @@
|
||||
],
|
||||
"surfaceGenerationParams": {
|
||||
"surfaceGenTag": "hills",
|
||||
"heightOffset": 10
|
||||
"heightOffset": 10,
|
||||
"floorVariants": [
|
||||
],
|
||||
"foliageDescriptions": [
|
||||
{
|
||||
"entityIDs": [
|
||||
"pine2"
|
||||
],
|
||||
"regularity": 0.6,
|
||||
"threshold": 0.05,
|
||||
"scale": 0.5,
|
||||
"priority": 1.0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -4,4 +4,5 @@
|
||||
- @subpage creaturetodo
|
||||
- @subpage creatureanimations
|
||||
- @subpage creatureideas
|
||||
- @subpage creaturemechanicsideas
|
||||
- @subpage creaturemechanicsideas
|
||||
- @subpage foliageideas
|
||||
5
docs/src/highlevel-design/creatures/foliageideas.md
Normal file
5
docs/src/highlevel-design/creatures/foliageideas.md
Normal file
@ -0,0 +1,5 @@
|
||||
@page foliageideas Foliage Ideas
|
||||
|
||||
"Tree" that shoots up a lantern at night time which sifts through the air to collect bugs for food.
|
||||
Lantern is a glowing particle.
|
||||
|
||||
@ -8,4 +8,9 @@ Another challenge to consider is creating teasers for the narrative peaks.
|
||||
IE, if your big bad is supposed to be a dark paladin, how do you tease him in the story without making it a final encounter.
|
||||
- "Visions", "Proxies", etc that aren't the real version
|
||||
- For certain types of creatures (ie dragons), you can have them fly by in a way that wouldn't be easily interacted with
|
||||
|
||||
|
||||
Yet another challenge to consider is adding blocks where side quests can become relevant
|
||||
IE, you hit a quest where you ask someone for a favor (lets say they need to repair something), you now have a timer where side quests can be introduced in the interim
|
||||
Another idea is having the quest pend on a building being constructed
|
||||
Another idea is waiting for an npc to move to a given location, ie if a character went off on another task sometime earlier in the quest and you are now waiting to regroup with them
|
||||
|
||||
|
||||
@ -941,6 +941,19 @@ Hill Gen tweaks
|
||||
(11/05/2024)
|
||||
More normals fixes for terrain
|
||||
|
||||
(11/06/2024)
|
||||
Fix server caching of terrain
|
||||
Implement server side striding of chunk data
|
||||
|
||||
(11/07/2024)
|
||||
Add quarter, eighth, and sixteenth scale chunk gen
|
||||
Add network pressure capping
|
||||
Add stratified updates that prioritize game chunks
|
||||
Add message deduplication
|
||||
Fix LOD bounding sphere calculation
|
||||
Hook up content generation to test generation realm
|
||||
Reorganize biome data
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
|
||||
@ -115,19 +115,24 @@ public class ImGuiPlayerEntity {
|
||||
//server pos
|
||||
int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId());
|
||||
Entity serverPlayerEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity);
|
||||
ImGui.text("Position (Server): " + EntityUtils.getPosition(serverPlayerEntity));
|
||||
ImGui.text("Rotation (Server): " + EntityUtils.getRotation(serverPlayerEntity));
|
||||
if(serverPlayerEntity != null){
|
||||
ImGui.text("Position (Server): " + EntityUtils.getPosition(serverPlayerEntity));
|
||||
ImGui.text("Rotation (Server): " + EntityUtils.getRotation(serverPlayerEntity));
|
||||
|
||||
//server-side physics stuff
|
||||
DBody serverBody = PhysicsEntityUtils.getDBody(serverPlayerEntity);
|
||||
if(serverBody != null){
|
||||
ImGui.text("Velocity (Server): " + serverBody.getLinearVel());
|
||||
ImGui.text("Force (Server): " + serverBody.getForce());
|
||||
ImGui.text("Move Vector (Server): " + CreatureUtils.getFacingVector(serverPlayerEntity));
|
||||
ImGui.text("Velocity (Server): " + CreatureUtils.getVelocity(serverPlayerEntity));
|
||||
//server-side physics stuff
|
||||
DBody serverBody = PhysicsEntityUtils.getDBody(serverPlayerEntity);
|
||||
if(serverBody != null){
|
||||
ImGui.text("Velocity (Server): " + serverBody.getLinearVel());
|
||||
ImGui.text("Force (Server): " + serverBody.getForce());
|
||||
ImGui.text("Move Vector (Server): " + CreatureUtils.getFacingVector(serverPlayerEntity));
|
||||
ImGui.text("Velocity (Server): " + CreatureUtils.getVelocity(serverPlayerEntity));
|
||||
}
|
||||
ImGui.text("View yaw (Server): " + ServerPlayerViewDirTree.getTree(serverPlayerEntity).getYaw());
|
||||
ImGui.text("View pitch (Server): " + ServerPlayerViewDirTree.getTree(serverPlayerEntity).getPitch());
|
||||
}
|
||||
if(Globals.server != null && Globals.server.getFirstConnection() != null && Globals.server.getFirstConnection().getPlayer() != null){
|
||||
ImGui.text("Player Object World Pos (Server): " + Globals.server.getFirstConnection().getPlayer().getWorldPos());
|
||||
}
|
||||
ImGui.text("View yaw (Server): " + ServerPlayerViewDirTree.getTree(serverPlayerEntity).getYaw());
|
||||
ImGui.text("View pitch (Server): " + ServerPlayerViewDirTree.getTree(serverPlayerEntity).getPitch());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -76,12 +76,4 @@ public class CollisionWorldData {
|
||||
}
|
||||
}
|
||||
|
||||
public float getRandomDampener(){
|
||||
if(clientWorldData != null){
|
||||
return clientWorldData.getRandomDampener();
|
||||
} else {
|
||||
return serverWorldData.getRandomDampener();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,6 +45,8 @@ public class ChunkGenerationTestLoading {
|
||||
|
||||
|
||||
String saveName = "generation_testing";
|
||||
//delete if it exists
|
||||
SaveUtils.deleteSave(saveName);
|
||||
if(!SaveUtils.getSaves().contains(saveName)){
|
||||
//
|
||||
//the juicy server GENERATION part
|
||||
|
||||
@ -8,6 +8,7 @@ import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.attach.AttachUtils;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.ServerDataCell;
|
||||
@ -57,6 +58,9 @@ public class ServerEntityUtils {
|
||||
//if server, get current server data cell
|
||||
ServerDataCell oldDataCell = realm.getDataCellManager().getDataCellAtPoint(EntityUtils.getPosition(entity));
|
||||
ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position);
|
||||
if(oldDataCell == null){
|
||||
LoggerInterface.loggerEngine.WARNING("Trying to reposition entity on server when it's former position is null!");
|
||||
}
|
||||
if(oldDataCell != newDataCell){
|
||||
if(newDataCell != null){
|
||||
ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell);
|
||||
|
||||
@ -58,7 +58,10 @@ public class SceneLoader {
|
||||
//Content manager
|
||||
//
|
||||
ServerContentManager serverContentManager = null;
|
||||
if(file.realmDescriptor.getType() == RealmDescriptor.REALM_DESCRIPTOR_PROCEDURAL){
|
||||
if(
|
||||
file.realmDescriptor.getType().matches(RealmDescriptor.REALM_DESCRIPTOR_PROCEDURAL) ||
|
||||
file.realmDescriptor.getType().matches(RealmDescriptor.REALM_DESCRIPTOR_GENERATION_TESTING)
|
||||
){
|
||||
serverContentManager = ServerContentManager.createServerContentManager(true);
|
||||
} else {
|
||||
serverContentManager = ServerContentManager.createServerContentManager(false);
|
||||
|
||||
@ -9,6 +9,7 @@ import electrosphere.game.data.creature.type.movement.EditorMovementSystem;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.ServerEntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.state.attack.ClientAttackTree;
|
||||
import electrosphere.entity.state.movement.fall.ClientFallTree;
|
||||
@ -21,6 +22,7 @@ import electrosphere.net.synchronization.annotation.SynchronizableEnum;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
|
||||
import electrosphere.renderer.anim.Animation;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
import electrosphere.util.math.SpatialMathUtils;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@ -194,6 +196,8 @@ public class ClientEditorMovementTree implements BehaviorTree {
|
||||
Vector3d facingVector = CreatureUtils.getFacingVector(parent);
|
||||
float maxNaturalVelocity = EDITOR_MAX_VELOCITY;
|
||||
|
||||
Entity serverEntity = EntityLookupUtils.getEntityById(Globals.clientSceneWrapper.mapClientToServerId(parent.getId()));
|
||||
|
||||
//
|
||||
//rotation update
|
||||
if(this.state != MovementTreeState.IDLE){
|
||||
@ -304,6 +308,9 @@ public class ClientEditorMovementTree implements BehaviorTree {
|
||||
//actually update
|
||||
rotation.set(movementQuaternion);
|
||||
position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity)));
|
||||
if(serverEntity != null){
|
||||
ServerEntityUtils.repositionEntity(serverEntity, new Vector3d(position));
|
||||
}
|
||||
|
||||
GravityUtils.clientAttemptActivateGravity(parent);
|
||||
} break;
|
||||
@ -316,6 +323,9 @@ public class ClientEditorMovementTree implements BehaviorTree {
|
||||
float velocity = this.getModifiedVelocity();
|
||||
rotation.set(movementQuaternion);
|
||||
position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity)));
|
||||
if(serverEntity != null){
|
||||
ServerEntityUtils.repositionEntity(serverEntity, new Vector3d(position));
|
||||
}
|
||||
|
||||
GravityUtils.clientAttemptActivateGravity(parent);
|
||||
} break;
|
||||
@ -334,6 +344,9 @@ public class ClientEditorMovementTree implements BehaviorTree {
|
||||
}
|
||||
rotation.set(movementQuaternion);
|
||||
position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity)));
|
||||
if(serverEntity != null){
|
||||
ServerEntityUtils.repositionEntity(serverEntity, new Vector3d(position));
|
||||
}
|
||||
|
||||
GravityUtils.clientAttemptActivateGravity(parent);
|
||||
} break;
|
||||
|
||||
@ -13,18 +13,63 @@ public class BiomeFoliageDescription {
|
||||
List<String> entityIDs;
|
||||
|
||||
/**
|
||||
* The frequency of this element in particular
|
||||
* How regular the placement of foliage is. Low values will create very uneven foliage, while high values will place them along a grid.
|
||||
*/
|
||||
Double frequency;
|
||||
Double regularity;
|
||||
|
||||
/**
|
||||
* The scale of the noise used to generate this element
|
||||
* The percentage of the ground to cover with foliage
|
||||
*/
|
||||
Double dispersion;
|
||||
Double threshold;
|
||||
|
||||
/**
|
||||
* The priority of this floor element in particular
|
||||
*/
|
||||
Double priority;
|
||||
|
||||
/**
|
||||
* The scale of the noise used to place foliage
|
||||
*/
|
||||
Double scale;
|
||||
|
||||
/**
|
||||
* Gets the entity ids for this foliage description
|
||||
* @return The list of entity ids
|
||||
*/
|
||||
public List<String> getEntityIDs(){
|
||||
return this.entityIDs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the regularity of the foliage placement
|
||||
* @return The regularity
|
||||
*/
|
||||
public Double getRegularity(){
|
||||
return regularity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the percentage of the ground to cover with foliage
|
||||
* @return The percentage of the ground to cover with foliage
|
||||
*/
|
||||
public Double getThreshold(){
|
||||
return threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the priority of this floor element in particular
|
||||
* @return The priority of this floor element in particular
|
||||
*/
|
||||
public Double getPriority(){
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scale of the noise used to place foliage
|
||||
* @return The scale of the noise used to place foliage
|
||||
*/
|
||||
public Double getScale(){
|
||||
return scale;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package electrosphere.game.data.biome;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Params for the surface generation algorithm
|
||||
*/
|
||||
@ -15,6 +17,16 @@ public class BiomeSurfaceGenerationParams {
|
||||
*/
|
||||
Float heightOffset;
|
||||
|
||||
/**
|
||||
* The different floor elements
|
||||
*/
|
||||
List<BiomeFloorElement> floorVariants;
|
||||
|
||||
/**
|
||||
* The list of foliage descriptions available to this biome type
|
||||
*/
|
||||
List<BiomeFoliageDescription> foliageDescriptions;
|
||||
|
||||
/**
|
||||
* Gets the tag for the generation algorithm for generating the surface
|
||||
* @return The tag for the generation algorithm for generating the surface
|
||||
@ -31,6 +43,22 @@ public class BiomeSurfaceGenerationParams {
|
||||
return heightOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of floor variants
|
||||
* @return The list of floor variants
|
||||
*/
|
||||
public List<BiomeFloorElement> getFloorVariants(){
|
||||
return floorVariants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of foliage descriptions
|
||||
* @return The list of foliage descriptions
|
||||
*/
|
||||
public List<BiomeFoliageDescription> getFoliageDescriptions(){
|
||||
return foliageDescriptions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ public class ServerWorldData {
|
||||
ServerTerrainManager serverTerrainManager = null;
|
||||
ServerFluidManager serverFluidManager = null;
|
||||
//TODO: Allow loading procedurally generated terrain from disk (the chunk generator is always default currently)
|
||||
serverWorldData = ServerWorldData.createFixedWorldData(new Vector3d(0),new Vector3d(16 * 4 * 4));
|
||||
serverWorldData = ServerWorldData.createFixedWorldData(new Vector3d(0),new Vector3d(TestGenerationChunkGenerator.GENERATOR_REALM_SIZE * ServerTerrainChunk.CHUNK_DIMENSION));
|
||||
serverWorldData.worldSizeDiscrete = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
||||
serverWorldData.worldSizeDiscreteVertical = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
||||
|
||||
@ -171,6 +171,10 @@ public class ServerWorldData {
|
||||
return worldMaxPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the discrete size of the world (in chunks)
|
||||
* @return The discrete size of the world (in chunks)
|
||||
*/
|
||||
public int getWorldSizeDiscrete() {
|
||||
return worldSizeDiscrete;
|
||||
}
|
||||
@ -179,10 +183,6 @@ public class ServerWorldData {
|
||||
return dynamicInterpolationRatio;
|
||||
}
|
||||
|
||||
public float getRandomDampener() {
|
||||
return randomDampener;
|
||||
}
|
||||
|
||||
public int convertRealToChunkSpace(double real){
|
||||
return (int)Math.floor(real / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
}
|
||||
|
||||
@ -13,26 +13,69 @@ import org.joml.Vector3i;
|
||||
* A client logged into the server
|
||||
*/
|
||||
public class Player {
|
||||
|
||||
ServerConnectionHandler connectionHandler;
|
||||
int id;
|
||||
|
||||
/**
|
||||
* The default server-side simulation radius in chunks
|
||||
*/
|
||||
public static final int DEFAULT_SIMULATION_RADIUS = 3;
|
||||
|
||||
/**
|
||||
* Id incrementer lock
|
||||
*/
|
||||
static Semaphore idIncrementerLock = new Semaphore(1);
|
||||
|
||||
/**
|
||||
* The actual incrementing id counter
|
||||
*/
|
||||
static int idIncrementer = 0;
|
||||
|
||||
/**
|
||||
* The corresponding connection handler
|
||||
*/
|
||||
ServerConnectionHandler connectionHandler;
|
||||
|
||||
/**
|
||||
* The id of the player
|
||||
*/
|
||||
int id;
|
||||
|
||||
/**
|
||||
* The world position of this player
|
||||
*/
|
||||
Vector3i worldPos;
|
||||
int simulationRadius = 3;
|
||||
|
||||
/**
|
||||
* The simulation radius of this player
|
||||
*/
|
||||
int simulationRadius = DEFAULT_SIMULATION_RADIUS;
|
||||
|
||||
/**
|
||||
* The player's primary entity
|
||||
*/
|
||||
Entity playerEntity;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param connectionHandler The corresponding connection
|
||||
*/
|
||||
public Player(ServerConnectionHandler connectionHandler){
|
||||
this.connectionHandler = connectionHandler;
|
||||
id = connectionHandler.getPlayerId();
|
||||
this.simulationRadius = Globals.userSettings.getGameplayPhysicsCellRadius();
|
||||
}
|
||||
|
||||
//used for when client is creating a player object for itself
|
||||
/**
|
||||
* Used when initing a local connection
|
||||
* @param id The id of the local connection
|
||||
*/
|
||||
public Player(int id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the player
|
||||
* @return The player's id
|
||||
*/
|
||||
public int getId() {
|
||||
if(connectionHandler != null){
|
||||
return this.connectionHandler.getPlayerId();
|
||||
@ -40,30 +83,58 @@ public class Player {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a message that should be sent to this player
|
||||
* @param message The message
|
||||
*/
|
||||
public void addMessage(NetworkMessage message){
|
||||
connectionHandler.addMessagetoOutgoingQueue(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world position of the player
|
||||
* @return The world position
|
||||
*/
|
||||
public Vector3i getWorldPos() {
|
||||
return worldPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world position of the player
|
||||
* @param worldPos The world position
|
||||
*/
|
||||
public void setWorldPos(Vector3i worldPos) {
|
||||
this.worldPos = worldPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the simulation radius of the player
|
||||
* @return The simulation radius
|
||||
*/
|
||||
public int getSimulationRadius() {
|
||||
return simulationRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the simulation radius of the player
|
||||
* @param simulationRadius The simulation radius
|
||||
*/
|
||||
public void setSimulationRadius(int simulationRadius) {
|
||||
this.simulationRadius = simulationRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's entity
|
||||
* @return The player's entity
|
||||
*/
|
||||
public Entity getPlayerEntity() {
|
||||
return playerEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's entity
|
||||
* @param playerEntity The player's entity
|
||||
*/
|
||||
public void setPlayerEntity(Entity playerEntity) {
|
||||
this.playerEntity = playerEntity;
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
||||
case REQUESTCHARACTERLIST:
|
||||
//TODO
|
||||
break;
|
||||
case REQUESTCREATECHARACTER:
|
||||
case REQUESTCREATECHARACTER: {
|
||||
CreatureTemplate template = Utilities.deserialize(message.getdata(), CreatureTemplate.class);
|
||||
if(template != null){
|
||||
connectionHandler.setCreatureTemplate(Utilities.deserialize(message.getdata(), CreatureTemplate.class));
|
||||
@ -36,10 +36,10 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
||||
} else {
|
||||
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterFailureMessage());
|
||||
}
|
||||
break;
|
||||
case REQUESTSPAWNCHARACTER:
|
||||
} break;
|
||||
case REQUESTSPAWNCHARACTER: {
|
||||
spawnEntityForClient(connectionHandler);
|
||||
break;
|
||||
} break;
|
||||
case RESPONSECHARACTERLIST:
|
||||
case RESPONSECREATECHARACTERSUCCESS:
|
||||
case RESPONSECREATECHARACTERFAILURE:
|
||||
|
||||
@ -292,7 +292,7 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
|
||||
TerrainMessage.constructResponseMetadataMessage(
|
||||
realm.getServerWorldData().getWorldSizeDiscrete(),
|
||||
realm.getServerWorldData().getDynamicInterpolationRatio(),
|
||||
realm.getServerWorldData().getRandomDampener(),
|
||||
0,
|
||||
(int)realm.getServerWorldData().getWorldBoundMin().x,
|
||||
(int)realm.getServerWorldData().getWorldBoundMin().z,
|
||||
(int)realm.getServerWorldData().getWorldBoundMax().x,
|
||||
|
||||
@ -68,6 +68,8 @@ public class PlayerCharacterCreation {
|
||||
int playerCharacterId = entity.getId();
|
||||
serverConnectionHandler.setPlayerEntityId(playerCharacterId);
|
||||
CreatureUtils.setControllerPlayerId(entity, serverConnectionHandler.getPlayerId());
|
||||
Player player = serverConnectionHandler.getPlayer();
|
||||
player.setPlayerEntity(entity);
|
||||
//custom player btrees
|
||||
addPlayerServerBTrees(entity);
|
||||
}
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
package electrosphere.server.content;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3i;
|
||||
|
||||
import electrosphere.entity.types.foliage.FoliageUtils;
|
||||
import electrosphere.game.data.biome.BiomeData;
|
||||
import electrosphere.game.data.biome.BiomeFoliageDescription;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.ServerDataCell;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import io.github.studiorailgun.NoiseUtils;
|
||||
|
||||
/**
|
||||
* Generates content for a given datacell
|
||||
*/
|
||||
public class ServerContentGenerator {
|
||||
|
||||
/**
|
||||
* The seed of the foliage
|
||||
*/
|
||||
public static final int FOLIAGE_SEED = 0;
|
||||
|
||||
/**
|
||||
* Generates content for a given data cell
|
||||
* @param realm The realm
|
||||
* @param cell The cell
|
||||
* @param worldPos The world position of the cell
|
||||
* @param randomizer The randomizer
|
||||
*/
|
||||
public static void generateContent(Realm realm, ServerDataCell cell, Vector3i worldPos, long randomizer){
|
||||
//verify we have everything for chunk content gen
|
||||
if(realm.getServerWorldData() == null && realm.getServerWorldData().getServerTerrainManager() == null && realm.getServerWorldData().getServerTerrainManager().getModel() == null){
|
||||
throw new Error(
|
||||
"Trying to generate content for a realm that does not have a terrain model defined!\n" +
|
||||
realm.getServerWorldData() + "\n" +
|
||||
realm.getServerWorldData().getServerTerrainManager() + "\n" +
|
||||
realm.getServerWorldData().getServerTerrainManager().getModel()
|
||||
);
|
||||
}
|
||||
|
||||
//setup
|
||||
Random random = new Random(randomizer);
|
||||
|
||||
|
||||
//generate foliage
|
||||
BiomeData biome = null;
|
||||
if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null && realm.getServerWorldData().getServerTerrainManager().getModel() != null){
|
||||
biome = realm.getServerWorldData().getServerTerrainManager().getModel().getSurfaceBiome(worldPos.x, worldPos.z);
|
||||
}
|
||||
List<BiomeFoliageDescription> foliageDescriptions = biome.getSurfaceGenerationParams().getFoliageDescriptions();
|
||||
if(foliageDescriptions != null){
|
||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
||||
double height = realm.getServerWorldData().getServerTerrainManager().getElevation(worldPos.x, worldPos.z, x, z);
|
||||
if(
|
||||
realm.getServerWorldData().convertVoxelToRealSpace(0, worldPos.y) <= height &&
|
||||
realm.getServerWorldData().convertVoxelToRealSpace(ServerTerrainChunk.CHUNK_DIMENSION, worldPos.y) > height
|
||||
){
|
||||
for(BiomeFoliageDescription foliageDescription : foliageDescriptions){
|
||||
double scale = foliageDescription.getScale();
|
||||
double regularity = foliageDescription.getRegularity();
|
||||
double threshold = foliageDescription.getThreshold();
|
||||
if(NoiseUtils.relaxedPointGen(x * scale, z * scale, regularity, threshold) > 0){
|
||||
String type = foliageDescription.getEntityIDs().get(random.nextInt(0,foliageDescription.getEntityIDs().size()));
|
||||
FoliageUtils.serverSpawnTreeFoliage(
|
||||
realm,
|
||||
new Vector3d(
|
||||
realm.getServerWorldData().convertVoxelToRealSpace(x, worldPos.x),
|
||||
height,
|
||||
realm.getServerWorldData().convertVoxelToRealSpace(z, worldPos.z)
|
||||
),
|
||||
type,
|
||||
random.nextLong()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,6 +11,7 @@ import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.ServerDataCell;
|
||||
import electrosphere.server.saves.SaveUtils;
|
||||
import electrosphere.util.FileUtils;
|
||||
import io.github.studiorailgun.HashUtils;
|
||||
|
||||
public class ServerContentManager {
|
||||
|
||||
@ -39,7 +40,7 @@ public class ServerContentManager {
|
||||
* @param worldPos The world position
|
||||
* @param cell The cell
|
||||
*/
|
||||
public void generateContentForDataCell(Realm realm, Vector3i worldPos, ServerDataCell cell, String cellKey){
|
||||
public void generateContentForDataCell(Realm realm, Vector3i worldPos, ServerDataCell cell, Long cellKey){
|
||||
String fullPath = "/content/" + cellKey + ".dat";
|
||||
if(generateContent){ //in other words, if not arena mode
|
||||
if(FileUtils.checkSavePathExists(Globals.currentSave.getName(), fullPath)){
|
||||
@ -48,8 +49,7 @@ public class ServerContentManager {
|
||||
contentRaw.hydrateRawContent(realm,cell);
|
||||
} else {
|
||||
//else create from scratch
|
||||
//UNCOMMENT THIS WHEN YOU WANT CONTENT GENERATED FOR WORLDS AGAIN
|
||||
// EnvironmentGenerator.generateForest(realm, cell, worldPos, 0);
|
||||
ServerContentGenerator.generateContent(realm, cell, worldPos, HashUtils.cantorHash(worldPos.x, worldPos.y, worldPos.z));
|
||||
}
|
||||
} else {
|
||||
//just because content wasn't generated doesn't mean there isn't data saved under that key
|
||||
@ -75,7 +75,7 @@ public class ServerContentManager {
|
||||
* @param locationKey the location key to save under
|
||||
* @param entities the list of entities to save
|
||||
*/
|
||||
public void saveContentToDisk(String locationKey, List<Entity> entities){
|
||||
public void saveContentToDisk(Long locationKey, List<Entity> entities){
|
||||
ContentSerialization serialization = ContentSerialization.constructContentSerialization(entities);
|
||||
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
|
||||
String fullPath = dirPath + "/content/" + locationKey + ".dat";
|
||||
|
||||
@ -14,11 +14,13 @@ import org.joml.Vector3i;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.threads.LabeledThread.ThreadLabel;
|
||||
import electrosphere.entity.ClientEntityUtils;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.ServerEntityUtils;
|
||||
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
|
||||
import electrosphere.game.server.world.ServerWorldData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||
import electrosphere.net.server.player.Player;
|
||||
import electrosphere.net.server.protocol.TerrainProtocol;
|
||||
@ -29,6 +31,8 @@ import electrosphere.server.datacell.physics.PhysicsDataCell;
|
||||
import electrosphere.server.fluid.manager.ServerFluidChunk;
|
||||
import electrosphere.server.fluid.manager.ServerFluidManager;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||
import electrosphere.server.terrain.models.TerrainModel;
|
||||
import io.github.studiorailgun.HashUtils;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
|
||||
/**
|
||||
@ -44,7 +48,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
/**
|
||||
* The max grid size allowed
|
||||
*/
|
||||
public static final int MAX_GRID_SIZE = 2000 * 1024;
|
||||
public static final int MAX_GRID_SIZE = TerrainModel.MAX_MACRO_DATA_SIZE * TerrainModel.DEFAULT_MACRO_DATA_SCALE * ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
|
||||
/**
|
||||
* Tracks whether this manager has been flagged to unload cells or not
|
||||
@ -52,7 +56,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
boolean unloadCells = true;
|
||||
|
||||
//these are going to be the natural ground grid of data cells, but we're going to have more than this
|
||||
Map<String,ServerDataCell> groundDataCells = new HashMap<String,ServerDataCell>();
|
||||
Map<Long,ServerDataCell> groundDataCells = new HashMap<Long,ServerDataCell>();
|
||||
Map<ServerDataCell,Vector3i> cellPositionMap = new HashMap<ServerDataCell,Vector3i>();
|
||||
//Map of server data cell to the number of frames said cell has had no players
|
||||
Map<ServerDataCell,Integer> cellPlayerlessFrameMap = new HashMap<ServerDataCell,Integer>();
|
||||
@ -77,7 +81,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
/**
|
||||
* Map of world position key -> physics cell
|
||||
*/
|
||||
Map<String,PhysicsDataCell> posPhysicsMap = new HashMap<String,PhysicsDataCell>();
|
||||
Map<Long,PhysicsDataCell> posPhysicsMap = new HashMap<Long,PhysicsDataCell>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -140,9 +144,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
loadedCellsLock.acquireUninterruptibly();
|
||||
loadedCells.add(groundDataCells.get(getServerDataCellKey(targetPos)));
|
||||
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(targetPos)),0);
|
||||
loadedCellsLock.release();
|
||||
//generate/handle content for new server data cell
|
||||
|
||||
loadedCellsLock.release();
|
||||
//add player
|
||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
}
|
||||
@ -181,11 +183,14 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
)
|
||||
){
|
||||
Vector3i targetPos = new Vector3i(x,y,z);
|
||||
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
|
||||
if(groundDataCells.get(getServerDataCellKey(targetPos)).containsPlayer(player)){
|
||||
// removals++;
|
||||
groundDataCells.get(getServerDataCellKey(targetPos)).removePlayer(player);
|
||||
}
|
||||
Long key = this.getServerDataCellKey(targetPos);
|
||||
if(
|
||||
groundDataCells.get(key) != null &&
|
||||
groundDataCells.get(key).containsPlayer(player)
|
||||
){
|
||||
// removals++;
|
||||
groundDataCells.get(key).removePlayer(player);
|
||||
this.broadcastDestructionToPlayer(player, groundDataCells.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -235,11 +240,22 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
// System.out.println("removals: " + removals + "\tadditions: " + additions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts messages to player to destroy all entities in a given cell
|
||||
* @param player The player
|
||||
* @param cell The cell
|
||||
*/
|
||||
private void broadcastDestructionToPlayer(Player player, ServerDataCell cell){
|
||||
for(Entity entity : cell.getScene().getEntityList()){
|
||||
player.addMessage(EntityMessage.constructDestroyMessage(entity.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates physics entities when new data cell being created
|
||||
*/
|
||||
private void createTerrainPhysicsEntities(Vector3i worldPos){
|
||||
String key = this.getServerDataCellKey(worldPos);
|
||||
Long key = this.getServerDataCellKey(worldPos);
|
||||
if(posPhysicsMap.containsKey(key)){
|
||||
PhysicsDataCell cell = posPhysicsMap.get(key);
|
||||
cell.retireCell();
|
||||
@ -300,13 +316,16 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
parent.deregisterCell(cell);
|
||||
loadedCells.remove(cell);
|
||||
Vector3i worldPos = getCellWorldPosition(cell);
|
||||
String key = getServerDataCellKey(worldPos);
|
||||
Long key = getServerDataCellKey(worldPos);
|
||||
groundDataCells.remove(key);
|
||||
//offload all entities in cell to chunk file
|
||||
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
|
||||
//clear all entities in cell
|
||||
for(Entity entity : cell.getScene().getEntityList()){
|
||||
ClientEntityUtils.destroyEntity(entity);
|
||||
if(ServerPlayerViewDirTree.hasTree(entity)){
|
||||
throw new Error("Trying to unload a player's entity! " + entity + " " + worldPos);
|
||||
}
|
||||
ServerEntityUtils.destroyEntity(entity);
|
||||
}
|
||||
//save terrain to disk
|
||||
serverTerrainManager.savePositionToDisk(worldPos);
|
||||
@ -334,13 +353,13 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
parent.deregisterCell(cell);
|
||||
loadedCells.remove(cell);
|
||||
Vector3i worldPos = getCellWorldPosition(cell);
|
||||
String key = getServerDataCellKey(worldPos);
|
||||
Long key = getServerDataCellKey(worldPos);
|
||||
groundDataCells.remove(key);
|
||||
//offload all entities in cell to chunk file
|
||||
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
|
||||
//clear all entities in cell
|
||||
for(Entity entity : cell.getScene().getEntityList()){
|
||||
ClientEntityUtils.destroyEntity(entity);
|
||||
ServerEntityUtils.destroyEntity(entity);
|
||||
}
|
||||
}
|
||||
this.serverTerrainManager.evictAll();
|
||||
@ -399,21 +418,25 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
worldPos.y >= 0 && worldPos.y < this.serverWorldData.getWorldSizeDiscrete() &&
|
||||
worldPos.z >= 0 && worldPos.z < this.serverWorldData.getWorldSizeDiscrete() &&
|
||||
//isn't null
|
||||
groundDataCells.get(getServerDataCellKey(worldPos)) == null
|
||||
groundDataCells.get(this.getServerDataCellKey(worldPos)) == null
|
||||
){
|
||||
//create data cell
|
||||
createServerDataCell(worldPos);
|
||||
this.createServerDataCell(worldPos);
|
||||
//generates physics for the cell in a dedicated thread then finally registers
|
||||
runPhysicsGenerationThread(worldPos);
|
||||
this.runPhysicsGenerationThread(worldPos);
|
||||
//add to loaded cells
|
||||
loadedCellsLock.acquireUninterruptibly();
|
||||
loadedCells.add(groundDataCells.get(getServerDataCellKey(worldPos)));
|
||||
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(worldPos)),0);
|
||||
loadedCells.add(groundDataCells.get(this.getServerDataCellKey(worldPos)));
|
||||
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(worldPos)),0);
|
||||
loadedCellsLock.release();
|
||||
} else {
|
||||
LoggerInterface.loggerEngine.WARNING("Trying to create data cell outside world bounds! " + worldPos);
|
||||
} else if(groundDataCells.get(this.getServerDataCellKey(worldPos)) == null) {
|
||||
LoggerInterface.loggerEngine.WARNING(
|
||||
"Trying to create data cell outside world bounds!\n" +
|
||||
worldPos + "\n" +
|
||||
this.serverWorldData.getWorldSizeDiscrete()
|
||||
);
|
||||
}
|
||||
return groundDataCells.get(getServerDataCellKey(worldPos));
|
||||
return groundDataCells.get(this.getServerDataCellKey(worldPos));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -428,9 +451,9 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
position.y >= 0 && position.y < this.serverWorldData.getWorldSizeDiscrete() &&
|
||||
position.z >= 0 && position.z < this.serverWorldData.getWorldSizeDiscrete() &&
|
||||
//isn't null
|
||||
groundDataCells.get(getServerDataCellKey(position)) != null
|
||||
groundDataCells.get(this.getServerDataCellKey(position)) != null
|
||||
){
|
||||
return groundDataCells.get(getServerDataCellKey(position));
|
||||
return groundDataCells.get(this.getServerDataCellKey(position));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -486,7 +509,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
//create physics entities
|
||||
createTerrainPhysicsEntities(worldPos);
|
||||
//set ready
|
||||
groundDataCells.get(getServerDataCellKey(worldPos)).setReady(true);
|
||||
if(groundDataCells.get(getServerDataCellKey(worldPos)) != null){
|
||||
groundDataCells.get(getServerDataCellKey(worldPos)).setReady(true);
|
||||
} else {
|
||||
LoggerInterface.loggerEngine.WARNING("Finished generating physics for server cell, but cell is null!");
|
||||
}
|
||||
}
|
||||
});
|
||||
groundDataCells.get(getServerDataCellKey(worldPos)).setReady(false);
|
||||
@ -498,8 +525,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* @param worldPos The position in world coordinates of the server data cell
|
||||
* @return The server data cell if it exists, otherwise null
|
||||
*/
|
||||
private String getServerDataCellKey(Vector3i worldPos){
|
||||
return worldPos.x + "_" + worldPos.y + "_" + worldPos.z;
|
||||
private Long getServerDataCellKey(Vector3i worldPos){
|
||||
return (long)HashUtils.cantorHash(worldPos.x, worldPos.y, worldPos.z);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -509,7 +536,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
*/
|
||||
private ServerDataCell createServerDataCell(Vector3i worldPos){
|
||||
ServerDataCell rVal = parent.createNewCell();
|
||||
String cellKey = getServerDataCellKey(worldPos);
|
||||
Long cellKey = getServerDataCellKey(worldPos);
|
||||
groundDataCells.put(cellKey,rVal);
|
||||
LoggerInterface.loggerEngine.DEBUG("Create server data cell with key " + cellKey);
|
||||
cellPositionMap.put(rVal,new Vector3i(worldPos));
|
||||
@ -648,7 +675,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
@Override
|
||||
public void save(String saveName) {
|
||||
for(ServerDataCell cell : loadedCells){
|
||||
String key = this.getServerDataCellKey(this.getCellWorldPosition(cell));
|
||||
Long key = this.getServerDataCellKey(this.getCellWorldPosition(cell));
|
||||
//offload all entities in cell to chunk file
|
||||
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
|
||||
}
|
||||
|
||||
@ -75,7 +75,9 @@ public class ServerBehaviorTreeUtils {
|
||||
Set<BehaviorTree> trees = entityBTreeMap.get(entity);
|
||||
ServerDataCell newCell = DataCellSearchUtils.getEntityDataCell(entity);
|
||||
for(BehaviorTree tree : trees){
|
||||
oldCell.getScene().deregisterBehaviorTree(tree);
|
||||
if(oldCell != null){
|
||||
oldCell.getScene().deregisterBehaviorTree(tree);
|
||||
}
|
||||
newCell.getScene().registerBehaviorTree(tree);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,6 +47,11 @@ public class DefaultChunkGenerator implements ChunkGenerator {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getElevation(int worldX, int worldZ, int chunkX, int chunkZ){
|
||||
return 0.1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(TerrainModel model) {
|
||||
//Does nothing as the arena is not based on a terrain model
|
||||
|
||||
@ -56,6 +56,12 @@ public class OverworldChunkGenerator implements ChunkGenerator {
|
||||
return returnedChunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getElevation(int worldX, int worldZ, int chunkX, int chunkZ){
|
||||
float[][] heightmap = getHeightmap(worldX, worldZ);
|
||||
return heightmap[chunkX][chunkZ];
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Sets the terrain model for the overworld algo
|
||||
|
||||
@ -74,7 +74,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
||||
//actual generation algo
|
||||
|
||||
//biome of the current chunk
|
||||
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldY, worldZ);
|
||||
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||
|
||||
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag());
|
||||
@ -126,6 +126,23 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getElevation(int worldX, int worldZ, int chunkX, int chunkZ){
|
||||
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||
|
||||
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag());
|
||||
if(heightmapGen == null){
|
||||
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
|
||||
}
|
||||
double rVal = heightmapGen.getHeight(
|
||||
this.terrainModel.getSeed(),
|
||||
this.serverWorldData.convertVoxelToRealSpace(chunkX, worldX),
|
||||
this.serverWorldData.convertVoxelToRealSpace(chunkZ, worldZ)
|
||||
);
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(TerrainModel model) {
|
||||
this.terrainModel = model;
|
||||
|
||||
@ -18,6 +18,16 @@ public interface ChunkGenerator {
|
||||
*/
|
||||
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride);
|
||||
|
||||
/**
|
||||
* Gets the elevation at a given 2d coordinate
|
||||
* @param worldX The world x coordinate
|
||||
* @param worldZ The world z coordinate
|
||||
* @param chunkX The chunk x coordinate
|
||||
* @param chunkZ The chunk z coordinate
|
||||
* @return The elevation at that specific coordinate
|
||||
*/
|
||||
public double getElevation(int worldX, int worldZ, int chunkX, int chunkZ);
|
||||
|
||||
/**
|
||||
* Sets the terrain model for the generation algorithm
|
||||
* @param model The terrain model
|
||||
|
||||
@ -181,10 +181,6 @@ public class ServerTerrainManager {
|
||||
return model.getElevationForChunk(x, y);
|
||||
}
|
||||
|
||||
public double getHeightAtPosition(double x, double y, double z){
|
||||
return y;
|
||||
}
|
||||
|
||||
public float getDiscreteValue(int x, int y){
|
||||
if(model != null){
|
||||
return model.getElevation()[x][y];
|
||||
@ -251,6 +247,21 @@ public class ServerTerrainManager {
|
||||
return returnedChunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs logic once a server chunk is available
|
||||
* @param worldX The world x position
|
||||
* @param worldZ The world z position
|
||||
* @param chunkX The chunk x position
|
||||
* @param chunkZ THe chunk z position
|
||||
* @return The ServerTerrainChunk
|
||||
*/
|
||||
public double getElevation(int worldX, int worldZ, int chunkX, int chunkZ){
|
||||
Globals.profiler.beginCpuSample("ServerTerrainManager.getChunk");
|
||||
double elevation = chunkGenerator.getElevation(worldX, worldZ, chunkX, chunkZ);
|
||||
Globals.profiler.endCpuSample();
|
||||
return elevation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs logic once a server chunk is available
|
||||
* @param worldX The world x position
|
||||
|
||||
@ -13,6 +13,11 @@ import electrosphere.util.annotation.Exclude;
|
||||
*/
|
||||
public class TerrainModel {
|
||||
|
||||
/**
|
||||
* Maximum size of the macro data
|
||||
*/
|
||||
public static final int MAX_MACRO_DATA_SIZE = 2000;
|
||||
|
||||
|
||||
/**
|
||||
* The scale of the macro data
|
||||
@ -514,11 +519,10 @@ public class TerrainModel {
|
||||
/**
|
||||
* Gets the surface biome for a given world position
|
||||
* @param worldX The world X
|
||||
* @param worldY The world Y
|
||||
* @param worldZ The world Z
|
||||
* @return The biome
|
||||
*/
|
||||
public BiomeData getSurfaceBiome(int worldX, int worldY, int worldZ){
|
||||
public BiomeData getSurfaceBiome(int worldX, int worldZ){
|
||||
int macroX = worldX / macroDataScale;
|
||||
int macroZ = worldZ / macroDataScale;
|
||||
int surfaceBiomeIndex = this.biome[macroX][macroZ];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user