fab placement
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
d9b7f9c25c
commit
9fe9670248
@ -142,6 +142,7 @@
|
||||
"path" : "Models/basic/geometry/unitvector.glb"
|
||||
}
|
||||
},
|
||||
"clientSidePrimary" : "PLACE_FAB",
|
||||
"clientSideSecondary": "SELECT_FAB",
|
||||
"collidable": {
|
||||
"type" : "CUBE",
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -18,4 +18,9 @@ export interface ClientVoxelUtils {
|
||||
*/
|
||||
readonly dig: () => void
|
||||
|
||||
/**
|
||||
* Places the currently selected fab
|
||||
*/
|
||||
readonly placeFab: () => void
|
||||
|
||||
}
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user