fixes and cursor work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-04-27 17:25:39 -04:00
parent 8859b639ca
commit c96c07334a
8 changed files with 74 additions and 61 deletions

View File

@ -1569,6 +1569,10 @@ Fix block meshgen
(04/27/2025)
Fab cursor rotation + actually place rotated fab
Fix terrain and blocks not saving/loading to/from disk
Fix swapping to/from editor entity in main game mode
Block cursor work
ChunkDiskMap code org
Filter procedural worlds out of level select menu

View File

@ -4,7 +4,6 @@ import org.joml.Vector3i;
import electrosphere.client.script.ScriptClientVoxelUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.EntityUtils;
/**
* Utilities for editing blocks
@ -17,9 +16,9 @@ public class BlockEditing {
* @param metadata The metadata of the block
*/
public static void editBlock(short type, short metadata){
Vector3i cornerVoxel = Globals.cursorState.getBlockCornerVoxelPos();
Vector3i cornerVoxel = Globals.clientWorldData.convertRealToBlockSpace(Globals.cursorState.getBlockCursorPos());
int blockSize = Globals.cursorState.getBlockSize();
Vector3i chunkPos = Globals.clientWorldData.convertRealToWorldSpace(EntityUtils.getPosition(Globals.playerBlockCursor));
Vector3i chunkPos = Globals.clientWorldData.convertRealToWorldSpace(Globals.cursorState.getBlockCursorPos());
ScriptClientVoxelUtils.clientRequestEditBlock(chunkPos, cornerVoxel, type, metadata, blockSize);
}
@ -27,9 +26,9 @@ public class BlockEditing {
* Destroy blocks
*/
public static void destroyBlock(){
Vector3i cornerVoxel = Globals.cursorState.getBlockCornerVoxelPos();
Vector3i cornerVoxel = Globals.clientWorldData.convertRealToBlockSpace(Globals.cursorState.getBlockCursorPos());
int blockSize = Globals.cursorState.getBlockSize();
Vector3i chunkPos = Globals.clientWorldData.convertRealToWorldSpace(EntityUtils.getPosition(Globals.playerBlockCursor));
Vector3i chunkPos = Globals.clientWorldData.convertRealToWorldSpace(Globals.cursorState.getBlockCursorPos());
ScriptClientVoxelUtils.clientRequestEditBlock(chunkPos, cornerVoxel, (short)0, (short)0, blockSize);
}

View File

@ -16,7 +16,6 @@ import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkCache;
import electrosphere.client.block.BlockChunkData;
import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.cache.ClientTerrainCache;
import electrosphere.client.terrain.cells.ClientDrawCellManager;
@ -39,13 +38,15 @@ import electrosphere.util.math.HashUtils;
*/
public class ClientTerrainManager {
//queues messages from server
List<TerrainMessage> messageQueue = new LinkedList<TerrainMessage>();
/**
* queues messages from server
*/
private List<TerrainMessage> messageQueue = new LinkedList<TerrainMessage>();
/**
* Locks the terrain manager (eg if adding message from network)
*/
static Semaphore lock = new Semaphore(1);
private static Semaphore lock = new Semaphore(1);
/**
* Maximum concurrent terrain requests
@ -57,10 +58,14 @@ public class ClientTerrainManager {
*/
public static final int FAILED_REQUEST_THRESHOLD = 500;
//The interpolation ratio of terrain
/**
* The interpolation ratio of terrain
*/
public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
//caches chunks from server
/**
* caches chunks from server
*/
static final int CACHE_SIZE = 2500 + (int)(ClientDrawCellManager.FULL_RES_DIST * 10) + (int)(ClientDrawCellManager.HALF_RES_DIST * 10);
/**
@ -71,37 +76,32 @@ public class ClientTerrainManager {
/**
* used for caching the macro values
*/
ClientTerrainCache terrainCache;
private ClientTerrainCache terrainCache;
/**
* Caches block data
*/
BlockChunkCache blockCache;
/**
* The world data for the client
*/
ClientWorldData clientWorldData;
private BlockChunkCache blockCache;
/**
* The queue of terrain chunk data to be buffered to gpu
*/
static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new LinkedList<TerrainChunkGenQueueItem>();
private static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new LinkedList<TerrainChunkGenQueueItem>();
/**
* Tracks what outgoing requests are currently active
*/
Map<Long,Integer> requestedMap = new HashMap<Long,Integer>();
private Map<Long,Integer> requestedMap = new HashMap<Long,Integer>();
/**
* Tracks what outgoing block requests are currently active
*/
Map<Long,Integer> requestedBlockMap = new HashMap<Long,Integer>();
private Map<Long,Integer> requestedBlockMap = new HashMap<Long,Integer>();
/**
* Used to clear the request map
*/
List<Long> toClearFailedRequests = new LinkedList<Long>();
private List<Long> toClearFailedRequests = new LinkedList<Long>();
/**
* Constructor

View File

@ -1,6 +1,7 @@
package electrosphere.client.ui.menu.mainmenu;
import java.util.List;
import java.util.stream.Collectors;
import electrosphere.client.ui.components.InputMacros;
import electrosphere.client.ui.components.VoxelSelectionPanel;
@ -114,7 +115,9 @@ public class MenuGeneratorsLevelEditor {
existingLevelColumn.setAlignContent(YogaAlignment.Start);
rVal.addChild(existingLevelColumn);
List<String> saveNames = SaveUtils.getSaves();
List<String> saveNames = SaveUtils.getSaves().stream().filter((String saveName) -> {
return !SaveUtils.isProcedural(saveName);
}).collect(Collectors.toList());
for(String saveName : saveNames){
//delete level button

View File

@ -4,7 +4,6 @@ import java.util.Arrays;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkData;
import electrosphere.client.entity.camera.CameraEntityUtils;
@ -249,20 +248,21 @@ public class CursorState {
double y = 0;
double z = 0;
double sizeMult = BlockChunkData.BLOCK_SIZE_MULTIPLIER * blockSize;
if(input.x % sizeMult > sizeMult / 2.0){
x = input.x - input.x % sizeMult + sizeMult + sizeMult / 2.0;
double alignMult = BlockChunkData.BLOCK_SIZE_MULTIPLIER;
if(input.x % alignMult > alignMult / 2.0){
x = input.x - input.x % alignMult + alignMult + sizeMult / 2.0;
} else {
x = input.x - input.x % sizeMult + sizeMult / 2.0;
x = input.x - input.x % alignMult + sizeMult / 2.0;
}
if(input.y % sizeMult > sizeMult / 2.0){
y = input.y - input.y % sizeMult + sizeMult + sizeMult / 2.0;
if(input.y % alignMult > alignMult / 2.0){
y = input.y - input.y % alignMult + alignMult + sizeMult / 2.0;
} else {
y = input.y - input.y % sizeMult + sizeMult / 2.0;
y = input.y - input.y % alignMult + sizeMult / 2.0;
}
if(input.z % sizeMult > sizeMult / 2.0){
z = input.z - input.z % sizeMult + sizeMult + sizeMult / 2.0;
if(input.z % alignMult > alignMult / 2.0){
z = input.z - input.z % alignMult + alignMult + sizeMult / 2.0;
} else {
z = input.z - input.z % sizeMult + sizeMult / 2.0;
z = input.z - input.z % alignMult + sizeMult / 2.0;
}
return new Vector3d(x,y,z);
}
@ -276,36 +276,33 @@ public class CursorState {
double x = 0;
double y = 0;
double z = 0;
double sizeMult = BlockChunkData.BLOCK_SIZE_MULTIPLIER * blockSize;
if(input.x % sizeMult > sizeMult / 2.0){
x = input.x - input.x % sizeMult + sizeMult;
double alignMult = BlockChunkData.BLOCK_SIZE_MULTIPLIER;
if(input.x % alignMult > alignMult / 2.0){
x = input.x - input.x % alignMult + alignMult;
} else {
x = input.x - input.x % sizeMult;
x = input.x - input.x % alignMult;
}
if(input.y % sizeMult > sizeMult / 2.0){
y = input.y - input.y % sizeMult + sizeMult;
if(input.y % alignMult > alignMult / 2.0){
y = input.y - input.y % alignMult + alignMult;
} else {
y = input.y - input.y % sizeMult;
y = input.y - input.y % alignMult;
}
if(input.z % sizeMult > sizeMult / 2.0){
z = input.z - input.z % sizeMult + sizeMult;
if(input.z % alignMult > alignMult / 2.0){
z = input.z - input.z % alignMult + alignMult;
} else {
z = input.z - input.z % sizeMult;
z = input.z - input.z % alignMult;
}
return new Vector3d(x,y,z);
}
/**
* Gets the voxel space position of the corner of the block cursor
* @return The voxel space position
* Gets the block cursor position
* @return The block cursor position
*/
public Vector3i getBlockCornerVoxelPos(){
if(Globals.playerBlockCursor == null){
throw new Error("Block cursor is null!");
}
Vector3d realPos = EntityUtils.getPosition(Globals.playerBlockCursor);
Vector3d clamped = this.clampPositionToBlockCorner(realPos);
return Globals.clientWorldData.convertRealToBlockSpace(clamped);
public Vector3d getBlockCursorPos(){
double sizeMult = BlockChunkData.BLOCK_SIZE_MULTIPLIER * blockSize;
Vector3d posRaw = new Vector3d(EntityUtils.getPosition(Globals.playerBlockCursor)).sub(sizeMult/2.0,sizeMult/2.0,sizeMult/2.0);
return posRaw;
}
/**

View File

@ -96,7 +96,7 @@ public class ClientToolbarState implements BehaviorTree {
if(targetPoint.getEquipClassWhitelist() != null && !targetPoint.getEquipClassWhitelist().contains(equipItemClass)){
targetPoint = equipInventoryState.getEquipPointFromSlot(toolbarData.getCombinedSlot());
}
equippedEntity = toEquip;
equippedEntity = toEquip;
//
//visual transforms

View File

@ -117,7 +117,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
*/
static Entity swapPlayerCharacter(ServerConnectionHandler connectionHandler){
//change the connection handler's creature template
if(connectionHandler.getCurrentCreatureTemplate().getCreatureType().matches(LoadingUtils.EDITOR_RACE_NAME)){
if(connectionHandler.getCurrentCreatureTemplate() != null && connectionHandler.getCurrentCreatureTemplate().getCreatureType().matches(LoadingUtils.EDITOR_RACE_NAME)){
//solve what race to pick
String race = LoadingUtils.EDITOR_RACE_NAME;
List<String> races = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces();
@ -173,7 +173,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
Player player = connectionHandler.getPlayer();
Entity playerEntity = player.getPlayerEntity();
Vector3d position = EntityUtils.getPosition(playerEntity);
Globals.realmManager.getEntityRealm(playerEntity).registerSpawnPoint(position);;
Globals.realmManager.getEntityRealm(playerEntity).registerSpawnPoint(position);
Globals.realmManager.getEntityRealm(playerEntity).getSpawnPoint().set(position);
ServerEntityUtils.destroyEntity(playerEntity);

View File

@ -26,6 +26,16 @@ import electrosphere.util.annotation.Exclude;
*/
public class ChunkDiskMap {
/**
* Name of the map file
*/
static final String MAP_FILE_NAME = "voxelchunk.json";
/**
* The directory that stores the voxel data files
*/
static final String VOXEL_DATA_DIR = "/terrain";
/**
* The map of world position+chunk type to the file that actually houses that information
*/
@ -73,15 +83,15 @@ public class ChunkDiskMap {
public static ChunkDiskMap init(String saveName){
ChunkDiskMap rVal = null;
LoggerInterface.loggerEngine.DEBUG("INIT CHUNK MAP " + saveName);
if(FileUtils.getSaveFile(saveName, "chunk.map").exists()){
rVal = FileUtils.loadObjectFromSavePath(saveName, "chunk.map", ChunkDiskMap.class);
if(FileUtils.getSaveFile(saveName, MAP_FILE_NAME).exists()){
rVal = FileUtils.loadObjectFromSavePath(saveName, MAP_FILE_NAME, ChunkDiskMap.class);
LoggerInterface.loggerEngine.DEBUG("POS FILE MAP: " + rVal.worldPosFileMap.keySet());
//make sure the subfolder for chunk files exists
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
if(!Files.exists(new File(dirPath + "/terrain").toPath())){
if(!Files.exists(new File(dirPath + VOXEL_DATA_DIR).toPath())){
try {
Files.createDirectories(new File(dirPath + "/terrain").toPath());
Files.createDirectories(new File(dirPath + VOXEL_DATA_DIR).toPath());
} catch (IOException e) {
LoggerInterface.loggerFileIO.ERROR(e);
}
@ -104,7 +114,7 @@ public class ChunkDiskMap {
* Saves the disk map to disk
*/
public void save(){
FileUtils.serializeObjectToSavePath(Globals.currentSave.getName(), "chunk.map", this);
FileUtils.serializeObjectToSavePath(Globals.currentSave.getName(), MAP_FILE_NAME, this);
}
/**
@ -213,7 +223,7 @@ public class ChunkDiskMap {
if(worldPosFileMap.containsKey(chunkKey)){
fileName = worldPosFileMap.get(chunkKey);
} else {
fileName = "/terrain/" + chunkKey + ".dat";
fileName = VOXEL_DATA_DIR + "/" + chunkKey + ".dat";
}
//generate binary for the file
float[][][] weights = terrainChunk.getWeights();