fab placement
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-04-26 21:09:54 -04:00
parent d9b7f9c25c
commit 9fe9670248
14 changed files with 274 additions and 1 deletions

View File

@ -142,6 +142,7 @@
"path" : "Models/basic/geometry/unitvector.glb"
}
},
"clientSidePrimary" : "PLACE_FAB",
"clientSideSecondary": "SELECT_FAB",
"collidable": {
"type" : "CUBE",

View File

@ -52,5 +52,11 @@ export const clientHooks: Hook[] = [
callback: (engine: Engine) => {
engine.classes.menuUtils.static.openFabSelection()
}
},
{
signal: "PLACE_FAB",
callback: (engine: Engine) => {
engine.classes.voxelUtils.static.placeFab()
}
}
]

View File

@ -18,4 +18,9 @@ export interface ClientVoxelUtils {
*/
readonly dig: () => void
/**
* Places the currently selected fab
*/
readonly placeFab: () => void
}

View File

@ -1558,6 +1558,7 @@ New block type
Fix inventory item tooltip not clearing
More item icons
Toolbar preview ui element
Fab tool can place fabs

View File

@ -9,9 +9,11 @@ import electrosphere.audio.movement.MovementAudioService.InteractionType;
import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.client.terrain.editing.TerrainEditing;
import electrosphere.collision.CollisionEngine;
import electrosphere.controls.cursor.CursorState;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
@ -134,4 +136,22 @@ public class ScriptClientVoxelUtils {
));
}
/**
* Places the currently selected fab
*/
@Export
public static void placeFab(){
if(Globals.cursorState.getSelectedFabPath() != null){
String fabPath = Globals.cursorState.getSelectedFabPath();
Vector3d fabCursorPos = EntityUtils.getPosition(CursorState.getFabCursor());
Vector3i chunkPos = Globals.clientWorldData.convertRealToWorldSpace(fabCursorPos);
Vector3i voxelPos = Globals.clientWorldData.convertRealToBlockSpace(fabCursorPos);
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestPlaceFabMessage(
chunkPos.x, chunkPos.y, chunkPos.z,
voxelPos.x, voxelPos.y, voxelPos.z,
fabPath
));
}
}
}

View File

@ -57,8 +57,8 @@ public class FabMenus {
//attach scrollable after search input for organzation purposes
fabSelectionPanelWindow.addChild(FabSelectionPanel.createFabSelectionPanel((File selectedFile) -> {
BlockFab fab = BlockFab.read(selectedFile);
LoggerInterface.loggerEngine.WARNING("" + fab.getDimensions());
Globals.cursorState.setSelectedFab(fab);
Globals.cursorState.setSelectedFabPath("./assets/Data/fab/" + selectedFile.getName());
}));
Globals.signalSystem.post(SignalType.YOGA_APPLY,fabSelectionPanelWindow);

View File

@ -86,6 +86,16 @@ public class CursorState {
*/
static Entity playerFabCursor;
/**
* The currently selected fab
*/
private BlockFab selectedFab = null;
/**
* The path for the selected fab
*/
private String selectedFabPath = null;
/**
* Creates the cursor entities
*/
@ -318,6 +328,30 @@ public class CursorState {
CursorState.makeFabVisible();
}
/**
* Gets the currently selected fab
* @return The currently selected fab
*/
public BlockFab getSelectedFab(){
return this.selectedFab;
}
/**
* Sets the selected fab path
* @param path The path
*/
public void setSelectedFabPath(String path){
this.selectedFabPath = path;
}
/**
* Gets the selected fab's path
* @return The path
*/
public String getSelectedFabPath(){
return this.selectedFabPath;
}
/**
* Gets the size of the block cursor
* @return The size of the block cursor
@ -381,5 +415,13 @@ public class CursorState {
}
}
}
/**
* Gets the fab cursor
* @return The fab cursor
*/
public static Entity getFabCursor(){
return playerFabCursor;
}
}

View File

@ -250,6 +250,11 @@ public abstract class NetworkMessage {
rVal = TerrainMessage.parseRequestEditBlockMessage(byteBuffer,pool);
}
break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTPLACEFAB:
if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parseRequestPlaceFabMessage(byteBuffer,pool);
}
break;
}
break;
case TypeBytes.MESSAGE_TYPE_SERVER:

View File

@ -29,6 +29,7 @@ public class TerrainMessage extends NetworkMessage {
SENDFLUIDDATA,
UPDATEFLUIDDATA,
REQUESTEDITBLOCK,
REQUESTPLACEFAB,
}
/**
@ -62,6 +63,7 @@ public class TerrainMessage extends NetworkMessage {
int blockType;
int blockMetadata;
int blockEditSize;
String fabPath;
/**
* Constructor
@ -461,6 +463,20 @@ public class TerrainMessage extends NetworkMessage {
this.blockEditSize = blockEditSize;
}
/**
* Gets fabPath
*/
public String getfabPath() {
return fabPath;
}
/**
* Sets fabPath
*/
public void setfabPath(String fabPath) {
this.fabPath = fabPath;
}
/**
* Removes the packet header from the buffer
* @param byteBuffer The buffer
@ -565,6 +581,8 @@ public class TerrainMessage extends NetworkMessage {
} else {
return false;
}
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTPLACEFAB:
return TerrainMessage.canParseRequestPlaceFabMessage(byteBuffer);
}
return false;
}
@ -1262,9 +1280,83 @@ public class TerrainMessage extends NetworkMessage {
return rVal;
}
/**
* Checks if a message of type RequestPlaceFab can be parsed from the byte stream
*/
public static boolean canParseRequestPlaceFabMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){
return false;
}
if(currentStreamLength < 10){
return false;
}
if(currentStreamLength < 14){
return false;
}
if(currentStreamLength < 18){
return false;
}
if(currentStreamLength < 22){
return false;
}
if(currentStreamLength < 26){
return false;
}
int fabPathSize = 0;
if(currentStreamLength < 30){
return false;
} else {
temporaryByteQueue.add(byteBuffer.peek(26 + 0));
temporaryByteQueue.add(byteBuffer.peek(26 + 1));
temporaryByteQueue.add(byteBuffer.peek(26 + 2));
temporaryByteQueue.add(byteBuffer.peek(26 + 3));
fabPathSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
}
if(currentStreamLength < 30 + fabPathSize){
return false;
}
return true;
}
/**
* Parses a message of type RequestPlaceFab
*/
public static TerrainMessage parseRequestPlaceFabMessage(CircularByteBuffer byteBuffer, MessagePool pool){
TerrainMessage rVal = (TerrainMessage)pool.get(MessageType.TERRAIN_MESSAGE);
rVal.messageType = TerrainMessageType.REQUESTPLACEFAB;
TerrainMessage.stripPacketHeader(byteBuffer);
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setworldZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setvoxelX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setvoxelY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setvoxelZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setfabPath(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal;
}
/**
* Constructs a message of type RequestPlaceFab
*/
public static TerrainMessage constructRequestPlaceFabMessage(int worldX,int worldY,int worldZ,int voxelX,int voxelY,int voxelZ,String fabPath){
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.REQUESTPLACEFAB);
rVal.setworldX(worldX);
rVal.setworldY(worldY);
rVal.setworldZ(worldZ);
rVal.setvoxelX(voxelX);
rVal.setvoxelY(voxelY);
rVal.setvoxelZ(voxelZ);
rVal.setfabPath(fabPath);
rVal.serialize();
return rVal;
}
@Override
void serialize(){
byte[] intValues = new byte[8];
byte[] stringBytes;
switch(this.messageType){
case REQUESTMETADATA:
rawBytes = new byte[2];
@ -1769,6 +1861,45 @@ public class TerrainMessage extends NetworkMessage {
rawBytes[34+i] = intValues[i];
}
break;
case REQUESTPLACEFAB:
rawBytes = new byte[2+4+4+4+4+4+4+4+fabPath.length()];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
//entity messaage header
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTPLACEFAB;
intValues = ByteStreamUtils.serializeIntToBytes(worldX);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(worldY);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(worldZ);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(voxelX);
for(int i = 0; i < 4; i++){
rawBytes[14+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(voxelY);
for(int i = 0; i < 4; i++){
rawBytes[18+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(voxelZ);
for(int i = 0; i < 4; i++){
rawBytes[22+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(fabPath.length());
for(int i = 0; i < 4; i++){
rawBytes[26+i] = intValues[i];
}
stringBytes = fabPath.getBytes();
for(int i = 0; i < fabPath.length(); i++){
rawBytes[30+i] = stringBytes[i];
}
break;
}
serialized = true;
}

View File

@ -85,6 +85,7 @@ public class TypeBytes {
public static final byte TERRAIN_MESSAGE_TYPE_SENDFLUIDDATA = 15;
public static final byte TERRAIN_MESSAGE_TYPE_UPDATEFLUIDDATA = 16;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTEDITBLOCK = 17;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTPLACEFAB = 18;
/*
Terrain packet sizes
*/

View File

@ -92,6 +92,13 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
Vector3i blockPos = new Vector3i(message.getvoxelX(),message.getvoxelY(),message.getvoxelZ());
ServerBlockEditing.editBlockArea(playerRealm, worldPos, blockPos, (short)message.getblockType(), (short)message.getblockMetadata(), message.getblockEditSize());
} break;
case REQUESTPLACEFAB: {
Vector3i worldPos = new Vector3i(message.getworldX(),message.getworldY(),message.getworldZ());
Vector3i blockPos = new Vector3i(message.getvoxelX(),message.getvoxelY(),message.getvoxelZ());
Entity targetEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
Realm playerRealm = Globals.realmManager.getEntityRealm(targetEntity);
ServerBlockEditing.placeBlockFab(playerRealm, worldPos, blockPos, message.getfabPath());
} break;
//all ignored message types
case UPDATEFLUIDDATA:
case RESPONSEMETADATA:

View File

@ -1,6 +1,7 @@
package electrosphere.net.synchronization.client;
import electrosphere.util.Utilities;
import electrosphere.entity.state.item.ClientChargeState;
import electrosphere.entity.state.movement.editor.ClientEditorMovementTree;
import electrosphere.entity.state.equip.ClientToolbarState;

View File

@ -1,9 +1,12 @@
package electrosphere.server.physics.block.editing;
import java.io.File;
import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkData;
import electrosphere.controls.cursor.CursorState;
import electrosphere.game.data.block.BlockFab;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.interfaces.VoxelCellManager;
@ -69,4 +72,37 @@ public class ServerBlockEditing {
}
}
/**
* Places a block fab
* @param realm The realm
* @param chunkPos The chunk position
* @param voxelPos The voxel position
* @param fabPath The fab
*/
public static void placeBlockFab(Realm realm, Vector3i chunkPos, Vector3i voxelPos, String fabPath){
BlockFab fab = BlockFab.read(new File(fabPath));
Vector3i dims = fab.getDimensions();
Vector3i currChunkPos = new Vector3i();
Vector3i currVoxelPos = new Vector3i();
VoxelCellManager voxelCellManager = (VoxelCellManager) realm.getDataCellManager();
for(int x = 0; x < dims.x; x++){
for(int y = 0; y < dims.y; y++){
for(int z = 0; z < dims.z; z++){
currVoxelPos.set(voxelPos).add(x,y,z);
currChunkPos.set(chunkPos).add(
currVoxelPos.x / BlockChunkData.CHUNK_DATA_WIDTH,
currVoxelPos.y / BlockChunkData.CHUNK_DATA_WIDTH,
currVoxelPos.z / BlockChunkData.CHUNK_DATA_WIDTH
);
currVoxelPos.set(
currVoxelPos.x % BlockChunkData.CHUNK_DATA_WIDTH,
currVoxelPos.y % BlockChunkData.CHUNK_DATA_WIDTH,
currVoxelPos.z % BlockChunkData.CHUNK_DATA_WIDTH
);
voxelCellManager.editBlock(currChunkPos, currVoxelPos, fab.getType(x, y, z), (short)0);
}
}
}
}
}

View File

@ -128,6 +128,10 @@
{
"name" : "blockEditSize",
"type" : "FIXED_INT"
},
{
"name" : "fabPath",
"type" : "VAR_STRING"
}
],
"messageTypes" : [
@ -330,6 +334,19 @@
"blockMetadata",
"blockEditSize"
]
},
{
"messageName" : "RequestPlaceFab",
"description" : "Requests that a fab be placed",
"data" : [
"worldX",
"worldY",
"worldZ",
"voxelX",
"voxelY",
"voxelZ",
"fabPath"
]
}
]
}