variable size for block editing
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-04-25 19:48:25 -04:00
parent 7b1610d847
commit f7c6208a2a
23 changed files with 592 additions and 181 deletions

View File

@ -1535,6 +1535,7 @@ Fix macro character entities not being assigned ServerCharacterData
Audio on placing blocks Audio on placing blocks
Audio on placing/removing voxels Audio on placing/removing voxels
Debounce item usage activations Debounce item usage activations
Variable block editing size

View File

@ -5,6 +5,7 @@ import org.joml.Vector3d;
import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType; import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.client.script.ClientScriptUtils; import electrosphere.client.script.ClientScriptUtils;
import electrosphere.client.terrain.editing.BlockEditing;
import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionEngine;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
@ -148,16 +149,12 @@ public class ItemActions {
if(cursorPos == null){ if(cursorPos == null){
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE)); cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
} }
//tell the server we want the secondary hand item to START doing something
Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage( //send server message if we're not doing a block edit
"handRight", //client sends custom packets for block editing
ITEM_ACTION_CODE_SECONDARY, boolean sendServerMessage = true;
ITEM_ACTION_CODE_STATE_ON,
cursorPos.x, //do any immediate client side calculations here (ie start playing an animation until we get response from server)
cursorPos.y,
cursorPos.z
));
//TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server)
if(Globals.playerEntity != null){ if(Globals.playerEntity != null){
ClientToolbarState clientToolbarState = ClientToolbarState.getClientToolbarState(Globals.playerEntity); ClientToolbarState clientToolbarState = ClientToolbarState.getClientToolbarState(Globals.playerEntity);
Entity primaryEntity = clientToolbarState.getCurrentPrimaryItem(); Entity primaryEntity = clientToolbarState.getCurrentPrimaryItem();
@ -168,11 +165,25 @@ public class ItemActions {
} }
if(data.getSecondaryUsage() != null){ if(data.getSecondaryUsage() != null){
if(data.getSecondaryUsage().getBlockId() != null){ if(data.getSecondaryUsage().getBlockId() != null){
sendServerMessage = false;
BlockEditing.editBlock((short)(int)data.getSecondaryUsage().getBlockId(),(short)0);
Globals.virtualAudioSourceManager.createVirtualAudioSource(AssetDataStrings.INTERACT_SFX_BLOCK_PLACE, VirtualAudioSourceType.CREATURE, false); Globals.virtualAudioSourceManager.createVirtualAudioSource(AssetDataStrings.INTERACT_SFX_BLOCK_PLACE, VirtualAudioSourceType.CREATURE, false);
} }
} }
} }
} }
//send server message
if(sendServerMessage){
//tell the server we want the secondary hand item to START doing something
Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage(
"handRight",
ITEM_ACTION_CODE_SECONDARY,
ITEM_ACTION_CODE_STATE_ON,
cursorPos.x,
cursorPos.y,
cursorPos.z
));
}
} }
/** /**

View File

@ -4,6 +4,7 @@ import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i; import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkData;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
/** /**
@ -178,17 +179,39 @@ public class ClientWorldData {
*/ */
public Vector3d convertWorldToRealSpace(Vector3i position){ public Vector3d convertWorldToRealSpace(Vector3i position){
return new Vector3d( return new Vector3d(
convertWorldToReal(position.x), this.convertWorldToReal(position.x),
convertWorldToReal(position.y), this.convertWorldToReal(position.y),
convertWorldToReal(position.z) this.convertWorldToReal(position.z)
); );
} }
public Vector3i convertRealToVoxelSpace(Vector3d position){ public Vector3i convertRealToVoxelSpace(Vector3d position){
return new Vector3i( return new Vector3i(
(int)Math.floor(position.x - convertChunkToRealSpace(convertRealToChunkSpace(position.x))), (int)Math.floor(position.x - this.convertChunkToRealSpace(this.convertRealToChunkSpace(position.x))),
(int)Math.floor(position.y - convertChunkToRealSpace(convertRealToChunkSpace(position.y))), (int)Math.floor(position.y - this.convertChunkToRealSpace(this.convertRealToChunkSpace(position.y))),
(int)Math.floor(position.z - convertChunkToRealSpace(convertRealToChunkSpace(position.z))) (int)Math.floor(position.z - this.convertChunkToRealSpace(this.convertRealToChunkSpace(position.z)))
);
}
/**
* Converts a real position to a block position
* @param real The real position
* @return The closest block position
*/
public int convertRealToLocalBlockSpace(double real){
return (int)Math.floor(real * BlockChunkData.BLOCKS_PER_UNIT_DISTANCE % BlockChunkData.CHUNK_DATA_WIDTH);
}
/**
* Converts the position to a block-space position
* @param position The real-space position
* @return The nearest block-space position
*/
public Vector3i convertRealToBlockSpace(Vector3d position){
return new Vector3i(
this.convertRealToLocalBlockSpace(position.x),
this.convertRealToLocalBlockSpace(position.y),
this.convertRealToLocalBlockSpace(position.z)
); );
} }

View File

@ -12,6 +12,7 @@ import electrosphere.collision.CollisionEngine;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
/** /**
@ -116,4 +117,21 @@ public class ScriptClientVoxelUtils {
} }
} }
/**
* Requests a block edit from the client
* @param chunkPos The position of the chunk to edit
* @param blockPos The position of the block to edit
* @param blockType The type of block
* @param blockMetadata The metadata of the block
* @param size The size of the blocks to edit
*/
@Export
public static void clientRequestEditBlock(Vector3i chunkPos, Vector3i blockPos, short blockType, short blockMetadata, int size){
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestEditBlockMessage(
chunkPos.x, chunkPos.y, chunkPos.z,
blockPos.x, blockPos.y, blockPos.z,
blockType, blockMetadata, size
));
}
} }

View File

@ -0,0 +1,26 @@
package electrosphere.client.terrain.editing;
import org.joml.Vector3i;
import electrosphere.client.script.ScriptClientVoxelUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.EntityUtils;
/**
* Utilities for editing blocks
*/
public class BlockEditing {
/**
* Edit blocks
* @param type The type of block
* @param metadata The metadata of the block
*/
public static void editBlock(short type, short metadata){
Vector3i cornerVoxel = Globals.cursorState.getBlockCornerVoxelPos();
int blockSize = Globals.cursorState.getBlockSize();
Vector3i chunkPos = Globals.clientWorldData.convertRealToWorldSpace(EntityUtils.getPosition(Globals.playerBlockCursor));
ScriptClientVoxelUtils.clientRequestEditBlock(chunkPos, cornerVoxel, type, metadata, blockSize);
}
}

View File

@ -5,9 +5,7 @@ import org.joml.Vector3d;
import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.client.entity.crosshair.Crosshair; import electrosphere.client.entity.crosshair.Crosshair;
import electrosphere.collision.CollisionEngine;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.ui.events.MouseEvent; import electrosphere.renderer.ui.events.MouseEvent;
@ -18,29 +16,59 @@ import electrosphere.util.math.SpatialMathUtils;
*/ */
public class CameraHandler { public class CameraHandler {
//The first person camera perspective /**
* The first person camera perspective
*/
public static final int CAMERA_PERSPECTIVE_FIRST = 1; public static final int CAMERA_PERSPECTIVE_FIRST = 1;
//The third person camera perspective
/**
* The third person camera perspective
*/
public static final int CAMERA_PERSPECTIVE_THIRD = 3; public static final int CAMERA_PERSPECTIVE_THIRD = 3;
//the horizontal mouse sensitivity /**
* the horizontal mouse sensitivity
*/
float mouseSensitivityHorizontal = .1f; float mouseSensitivityHorizontal = .1f;
//the vertical mouse sensitivity
/**
* the vertical mouse sensitivity
*/
float mouseSensitivityVertical = .08f; float mouseSensitivityVertical = .08f;
//the speed of the freecam
/**
* the speed of the freecam
*/
float cameraSpeed; float cameraSpeed;
//the current yaw
/**
* the current yaw
*/
float yaw = 150; float yaw = 150;
//the current pitch
/**
* the current pitch
*/
float pitch = 50; float pitch = 50;
//the camera's rotation vector
/**
* the camera's rotation vector
*/
Vector3d cameraRotationVector = new Vector3d(); Vector3d cameraRotationVector = new Vector3d();
//the radial offset of the camera
/**
* the radial offset of the camera
*/
Vector3d radialOffset = new Vector3d(0,1,0); Vector3d radialOffset = new Vector3d(0,1,0);
//if set to true, the camera will track the player's entity
/**
* if set to true, the camera will track the player's entity
*/
boolean trackPlayerEntity = true; boolean trackPlayerEntity = true;
//sets whether the camera handler should update the player's camera or not /**
* sets whether the camera handler should update the player's camera or not
*/
boolean update = true; boolean update = true;
/** /**
@ -138,37 +166,12 @@ public class CameraHandler {
Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera); Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera);
//update the cursor on client side //update the cursor on client side
this.updatePlayerCursor(); Globals.cursorState.updatePlayerCursor();
} }
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }
/**
* Updates the position of the player's in world cursor
*/
private void updatePlayerCursor(){
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
Entity camera = Globals.playerCamera;
if(
collisionEngine != null &&
camera != null &&
Globals.playerCursor != null
){
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
Vector3d cursorPos = collisionEngine.rayCastPosition(centerPos, new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
if(cursorPos == null){
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
}
EntityUtils.getPosition(Globals.playerCursor).set(cursorPos);
//clamp block cursor to nearest voxel
cursorPos.set(PlayerCursor.clampPositionToNearestBlock(cursorPos));
EntityUtils.getPosition(Globals.playerBlockCursor).set(cursorPos);
}
}
/** /**
* Gets the yaw of the camera handler * Gets the yaw of the camera handler
* @return the yaw * @return the yaw

View File

@ -5,15 +5,23 @@ import org.lwjgl.glfw.GLFWKeyCallbackI;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
/**
* Callback that is invoked on key input received by GLFW
*/
public class ControlCallback implements GLFWKeyCallbackI { public class ControlCallback implements GLFWKeyCallbackI {
/**
* The size of the key state tracking array
*/
static final short KEY_VALUE_ARRAY_SIZE = 512; static final short KEY_VALUE_ARRAY_SIZE = 512;
/**
* Array that tracks the state of keys
*/
boolean[] keyValues = new boolean[KEY_VALUE_ARRAY_SIZE]; boolean[] keyValues = new boolean[KEY_VALUE_ARRAY_SIZE];
@Override @Override
public void invoke(long window, int key, int scancode, int action, int mods){ public void invoke(long window, int key, int scancode, int action, int mods){
if(key >= 0 && key < KEY_VALUE_ARRAY_SIZE){ if(key >= 0 && key < KEY_VALUE_ARRAY_SIZE){
if(action == GLFW.GLFW_PRESS || action == GLFW.GLFW_REPEAT){ if(action == GLFW.GLFW_PRESS || action == GLFW.GLFW_REPEAT){
keyValues[key] = true; keyValues[key] = true;
@ -21,18 +29,12 @@ public class ControlCallback implements GLFWKeyCallbackI {
keyValues[key] = false; keyValues[key] = false;
} }
} }
// if(key == GLFW.GLFW_KEY_D){
// System.out.println("[D]Action: " + action + " keyValues: " + keyValues[key]);
// }
// if(key == GLFW.GLFW_KEY_W){
// System.out.println("[W]Action: " + action + " keyValues: " + keyValues[key]);
// }
} }
/** /**
* !!!WARNING!!!, will silently fail if opengl elementsn ot defined or keycode is outside of key value array size or is not in main rendering thread * !!!WARNING!!!, will silently fail if opengl elementsn ot defined or keycode is outside of key value array size or is not in main rendering thread
* @param keycode * @param keycode The keycode to check
* @return * @return true if it is pressed, false otherwise
*/ */
public boolean getKey(int keycode){ public boolean getKey(int keycode){
if(keycode >= 0 && keycode < KEY_VALUE_ARRAY_SIZE){ if(keycode >= 0 && keycode < KEY_VALUE_ARRAY_SIZE){

View File

@ -116,7 +116,7 @@ public class ControlHandler {
/** /**
* Constructor * Constructor
*/ */
ControlHandler(){ private ControlHandler(){
controls = new HashMap<String, Control>(); controls = new HashMap<String, Control>();
} }
@ -375,25 +375,25 @@ public class ControlHandler {
} }
//set to menu state if a menu is open, otherwise use the hinted control scheme //set to menu state if a menu is open, otherwise use the hinted control scheme
if(onlyInventoryMenusOpen()){ if(this.onlyInventoryMenusOpen()){
setHandlerState(ControlsState.INVENTORY); this.setHandlerState(ControlsState.INVENTORY);
} else if(hasControlBlockingMenuOpen()){ } else if(this.hasControlBlockingMenuOpen()){
setHandlerState(ControlsState.IN_GAME_MAIN_MENU); this.setHandlerState(ControlsState.IN_GAME_MAIN_MENU);
} else { } else {
setHandlerState(properState); this.setHandlerState(properState);
} }
//checks if the current handler state should have mouse enabled or not //checks if the current handler state should have mouse enabled or not
if(Arrays.binarySearch(mouseEnabledStates,getHandlerState()) >= 0){ if(Arrays.binarySearch(mouseEnabledStates,getHandlerState()) >= 0){
showMouse(); this.showMouse();
} else { } else {
hideMouse(); this.hideMouse();
} }
} }
/** /**
* Transfers the mouse position from the glfw buffer to variables stored inside the control handler * Transfers the mouse position from the glfw buffer to variables stored inside the control handler
*/ */
void getMousePositionInBuffer(){ private void getMousePositionInBuffer(){
//only if not headless, gather position //only if not headless, gather position
if(!Globals.HEADLESS){ if(!Globals.HEADLESS){
glfwGetCursorPos(Globals.window, this.mouseState.getMouseBufferX(), this.mouseState.getMouseBufferY()); glfwGetCursorPos(Globals.window, this.mouseState.getMouseBufferX(), this.mouseState.getMouseBufferY());
@ -404,7 +404,7 @@ public class ControlHandler {
* Checks if the mouse button 1 is currently pressed * Checks if the mouse button 1 is currently pressed
* @return true if pressed, false otherwise * @return true if pressed, false otherwise
*/ */
boolean getButton1Raw(){ private boolean getButton1Raw(){
if(Globals.HEADLESS){ if(Globals.HEADLESS){
return false; return false;
} else { } else {
@ -416,7 +416,7 @@ public class ControlHandler {
* Checks if the mouse button 2 is currently pressed * Checks if the mouse button 2 is currently pressed
* @return true if pressed, false otherwise * @return true if pressed, false otherwise
*/ */
boolean getButton2Raw(){ private boolean getButton2Raw(){
if(Globals.HEADLESS){ if(Globals.HEADLESS){
return false; return false;
} else { } else {

View File

@ -1,49 +0,0 @@
package electrosphere.controls;
import org.joml.Vector3d;
import electrosphere.client.block.BlockChunkData;
/**
* Utilities for dealing with cursors
*/
public class PlayerCursor {
/**
* Token for displaying cursor
*/
public static final String CURSOR_TOKEN = "CURSOR";
/**
* Token for displaying block cursor
*/
public static final String CURSOR_BLOCK_TOKEN = "CURSOR_BLOCK";
/**
* Clamps a real position to the nearest block
* @param input The input real position
* @return The real position clamped to the nearest block
*/
public static Vector3d clampPositionToNearestBlock(Vector3d input){
double x = 0;
double y = 0;
double z = 0;
if(input.x % BlockChunkData.BLOCK_SIZE_MULTIPLIER > BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0){
x = input.x - input.x % 0.25 + BlockChunkData.BLOCK_SIZE_MULTIPLIER + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0;
} else {
x = input.x - input.x % 0.25 + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0;
}
if(input.y % BlockChunkData.BLOCK_SIZE_MULTIPLIER > BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0){
y = input.y - input.y % 0.25 + BlockChunkData.BLOCK_SIZE_MULTIPLIER + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0;
} else {
y = input.y - input.y % 0.25 + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0;
}
if(input.z % BlockChunkData.BLOCK_SIZE_MULTIPLIER > BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0){
z = input.z - input.z % 0.25 + BlockChunkData.BLOCK_SIZE_MULTIPLIER + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0;
} else {
z = input.z - input.z % 0.25 + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0;
}
return new Vector3d(x,y,z);
}
}

View File

@ -1,5 +1,7 @@
package electrosphere.controls.categories; package electrosphere.controls.categories;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_CONTROL;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -26,6 +28,7 @@ import electrosphere.engine.Globals;
import electrosphere.engine.Main; import electrosphere.engine.Main;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityTags;
import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.equip.ClientEquipState; import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.equip.ClientToolbarState; import electrosphere.entity.state.equip.ClientToolbarState;
@ -597,6 +600,16 @@ public class ControlCategoryMainGame {
*/ */
mainGameControlList.add(controlMap.get(TOOLBAR_SCROLL)); mainGameControlList.add(controlMap.get(TOOLBAR_SCROLL));
controlMap.get(TOOLBAR_SCROLL).setOnScroll(new Control.ScrollCallback() {public void execute(MouseState mouseState, ScrollEvent scrollEvent){ controlMap.get(TOOLBAR_SCROLL).setOnScroll(new Control.ScrollCallback() {public void execute(MouseState mouseState, ScrollEvent scrollEvent){
boolean handled = false;
if(Globals.controlCallback.getKey(GLFW_KEY_LEFT_CONTROL)){
//if the block cursor is visible, capture this input and instead modify block cursor
if(Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE).contains(Globals.playerBlockCursor)){
Globals.cursorState.updateCursorSize(scrollEvent);
handled = true;
}
}
if(!handled){
if(Globals.playerEntity != null && ClientToolbarState.getClientToolbarState(Globals.playerEntity) != null){ if(Globals.playerEntity != null && ClientToolbarState.getClientToolbarState(Globals.playerEntity) != null){
ClientToolbarState clientToolbarState = ClientToolbarState.getClientToolbarState(Globals.playerEntity); ClientToolbarState clientToolbarState = ClientToolbarState.getClientToolbarState(Globals.playerEntity);
if(scrollEvent.getScrollAmount() > 0){ if(scrollEvent.getScrollAmount() > 0){
@ -605,6 +618,7 @@ public class ControlCategoryMainGame {
clientToolbarState.attemptChangeSelection(clientToolbarState.getSelectedSlot() + 1); clientToolbarState.attemptChangeSelection(clientToolbarState.getSelectedSlot() + 1);
} }
} }
}
}}); }});
/* /*

View File

@ -0,0 +1,223 @@
package electrosphere.controls.cursor;
import java.util.Arrays;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkData;
import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.collision.CollisionEngine;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.DrawableUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorTextureMask;
import electrosphere.renderer.ui.events.ScrollEvent;
/**
* Tracking for the cursor state
*/
public class CursorState {
/**
* Token for displaying cursor
*/
public static final String CURSOR_TOKEN = "CURSOR";
/**
* Token for displaying block cursor
*/
public static final String CURSOR_BLOCK_TOKEN = "CURSOR_BLOCK";
/**
* Minimum size of the block cursor
*/
public static final int MIN_BLOCK_SIZE = 1;
/**
* Maximum size of the block cursor
*/
public static final int MAX_BLOCK_SIZE = 4;
/**
* The scale multiplier for scaling the block cursor
*/
private static final float BLOCK_CURSOR_SCALE_MULTIPLIER = 0.2f;
/**
* Size of blocks to edit
*/
private int blockSize = MIN_BLOCK_SIZE;
/**
* Creates the cursor entities
*/
public static void createCursorEntities(){
//player's cursor
Globals.playerCursor = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(Globals.playerCursor, AssetDataStrings.UNITSPHERE);
Actor cursorActor = EntityUtils.getActor(Globals.playerCursor);
cursorActor.addTextureMask(new ActorTextureMask("sphere", Arrays.asList(new String[]{"Textures/transparent_red.png"})));
DrawableUtils.makeEntityTransparent(Globals.playerCursor);
EntityUtils.getScale(Globals.playerCursor).set(0.2f);
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerCursor, EntityTags.DRAWABLE);
//player's block cursor
Globals.playerBlockCursor = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(Globals.playerBlockCursor, AssetDataStrings.UNITCUBE);
Actor blockCursorActor = EntityUtils.getActor(Globals.playerBlockCursor);
blockCursorActor.addTextureMask(new ActorTextureMask("cube", Arrays.asList(new String[]{"Textures/transparent_red.png"})));
DrawableUtils.makeEntityTransparent(Globals.playerBlockCursor);
EntityUtils.getScale(Globals.playerBlockCursor).set(BLOCK_CURSOR_SCALE_MULTIPLIER);
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerBlockCursor, EntityTags.DRAWABLE);
}
/**
* Updates the position of the player's in world cursor
*/
public void updatePlayerCursor(){
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
Entity camera = Globals.playerCamera;
if(
collisionEngine != null &&
camera != null &&
Globals.playerCursor != null
){
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
Vector3d cursorPos = collisionEngine.rayCastPosition(centerPos, new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
if(cursorPos == null){
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
}
EntityUtils.getPosition(Globals.playerCursor).set(cursorPos);
//clamp block cursor to nearest voxel
cursorPos.set(this.clampPositionToNearestBlock(cursorPos));
EntityUtils.getPosition(Globals.playerBlockCursor).set(cursorPos);
}
}
/**
* Makes the real position cursor visible
*/
public static void makeRealVisible(){
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerBlockCursor, EntityTags.DRAWABLE);
Globals.clientSceneWrapper.getScene().registerEntityToTag(Globals.playerCursor, EntityTags.DRAWABLE);
}
/**
* Makes the block position cursor visible
*/
public static void makeBlockVisible(){
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerCursor, EntityTags.DRAWABLE);
Globals.clientSceneWrapper.getScene().registerEntityToTag(Globals.playerBlockCursor, EntityTags.DRAWABLE);
}
/**
* Hides the cursor
*/
public static void hide(){
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerCursor, EntityTags.DRAWABLE);
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerBlockCursor, EntityTags.DRAWABLE);
}
/**
* Clamps a real position to the nearest block
* @param input The input real position
* @return The real position clamped to the nearest block
*/
public Vector3d clampPositionToNearestBlock(Vector3d input){
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 + sizeMult / 2.0;
} else {
x = input.x - input.x % sizeMult + sizeMult / 2.0;
}
if(input.y % sizeMult > sizeMult / 2.0){
y = input.y - input.y % sizeMult + sizeMult + sizeMult / 2.0;
} else {
y = input.y - input.y % sizeMult + sizeMult / 2.0;
}
if(input.z % sizeMult > sizeMult / 2.0){
z = input.z - input.z % sizeMult + sizeMult + sizeMult / 2.0;
} else {
z = input.z - input.z % sizeMult + sizeMult / 2.0;
}
return new Vector3d(x,y,z);
}
/**
* Clamps a real position to the corner of the block cursor
* @param input The input real position
* @return The corner position
*/
public Vector3d clampPositionToBlockCorner(Vector3d input){
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;
} else {
x = input.x - input.x % sizeMult;
}
if(input.y % sizeMult > sizeMult / 2.0){
y = input.y - input.y % sizeMult + sizeMult;
} else {
y = input.y - input.y % sizeMult;
}
if(input.z % sizeMult > sizeMult / 2.0){
z = input.z - input.z % sizeMult + sizeMult;
} else {
z = input.z - input.z % sizeMult;
}
return new Vector3d(x,y,z);
}
/**
* Gets the voxel space position of the corner of the block cursor
* @return The voxel space 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);
}
/**
* Updates the cursor size
* @param scrollEvent The scroll event
*/
public void updateCursorSize(ScrollEvent scrollEvent){
if(scrollEvent.getScrollAmount() > 0){
if(this.blockSize < MAX_BLOCK_SIZE){
this.blockSize = this.blockSize * 2;
}
} else {
if(this.blockSize > MIN_BLOCK_SIZE){
this.blockSize = this.blockSize / 2;
}
}
EntityUtils.getScale(Globals.playerBlockCursor).set(BLOCK_CURSOR_SCALE_MULTIPLIER * this.blockSize);
}
/**
* Gets the size of the block cursor
* @return The size of the block cursor
*/
public int getBlockSize(){
return blockSize;
}
}

View File

@ -36,6 +36,7 @@ import electrosphere.controls.ControlCallback;
import electrosphere.controls.ControlHandler; import electrosphere.controls.ControlHandler;
import electrosphere.controls.MouseCallback; import electrosphere.controls.MouseCallback;
import electrosphere.controls.ScrollCallback; import electrosphere.controls.ScrollCallback;
import electrosphere.controls.cursor.CursorState;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.engine.assetmanager.AssetManager; import electrosphere.engine.assetmanager.AssetManager;
import electrosphere.engine.loadingthreads.InitialAssetLoading; import electrosphere.engine.loadingthreads.InitialAssetLoading;
@ -203,6 +204,7 @@ public class Globals {
public static ControlCallback controlCallback = new ControlCallback(); public static ControlCallback controlCallback = new ControlCallback();
public static MouseCallback mouseCallback = new MouseCallback(); public static MouseCallback mouseCallback = new MouseCallback();
public static ScrollCallback scrollCallback = new ScrollCallback(); public static ScrollCallback scrollCallback = new ScrollCallback();
public static CursorState cursorState = new CursorState();
// //

View File

@ -1,6 +1,5 @@
package electrosphere.engine.loadingthreads; package electrosphere.engine.loadingthreads;
import java.util.Arrays;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.joml.Vector3d; import org.joml.Vector3d;
@ -18,22 +17,19 @@ import electrosphere.client.ui.menu.WindowStrings;
import electrosphere.client.ui.menu.WindowUtils; import electrosphere.client.ui.menu.WindowUtils;
import electrosphere.client.ui.menu.mainmenu.MenuCharacterCreation; import electrosphere.client.ui.menu.mainmenu.MenuCharacterCreation;
import electrosphere.controls.ControlHandler; import electrosphere.controls.ControlHandler;
import electrosphere.controls.cursor.CursorState;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.engine.signal.Signal.SignalType; import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.engine.threads.LabeledThread.ThreadLabel; import electrosphere.engine.threads.LabeledThread.ThreadLabel;
import electrosphere.entity.DrawableUtils; import electrosphere.entity.DrawableUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.NetUtils; import electrosphere.net.NetUtils;
import electrosphere.net.client.ClientNetworking; import electrosphere.net.client.ClientNetworking;
import electrosphere.net.parser.net.message.CharacterMessage; import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.LoreMessage; import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorTextureMask;
public class ClientLoading { public class ClientLoading {
@ -296,23 +292,7 @@ public class ClientLoading {
// Globals.clientScene.registerBehaviorTree(new ApplyRotationTree(cloudRing,new Quaterniond().rotationZ(0.0001))); // Globals.clientScene.registerBehaviorTree(new ApplyRotationTree(cloudRing,new Quaterniond().rotationZ(0.0001)));
// Globals.assetManager.queueOverrideMeshShader("Models/environment/cloudRing.fbx", "Sphere", "Shaders/skysphere/skysphere.vs", "Shaders/skysphere/skysphere.fs"); // Globals.assetManager.queueOverrideMeshShader("Models/environment/cloudRing.fbx", "Sphere", "Shaders/skysphere/skysphere.vs", "Shaders/skysphere/skysphere.fs");
//player's cursor CursorState.createCursorEntities();
Globals.playerCursor = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(Globals.playerCursor, AssetDataStrings.UNITSPHERE);
Actor cursorActor = EntityUtils.getActor(Globals.playerCursor);
cursorActor.addTextureMask(new ActorTextureMask("sphere", Arrays.asList(new String[]{"Textures/transparent_red.png"})));
DrawableUtils.makeEntityTransparent(Globals.playerCursor);
EntityUtils.getScale(Globals.playerCursor).set(0.2f);
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerCursor, EntityTags.DRAWABLE);
//player's block cursor
Globals.playerBlockCursor = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(Globals.playerBlockCursor, AssetDataStrings.UNITCUBE);
Actor blockCursorActor = EntityUtils.getActor(Globals.playerBlockCursor);
blockCursorActor.addTextureMask(new ActorTextureMask("cube", Arrays.asList(new String[]{"Textures/transparent_red.png"})));
DrawableUtils.makeEntityTransparent(Globals.playerBlockCursor);
EntityUtils.getScale(Globals.playerBlockCursor).set(0.2f);
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerBlockCursor, EntityTags.DRAWABLE);
//cloud object //cloud object
// Entity cloudEnt = EntityCreationUtils.createClientSpatialEntity(); // Entity cloudEnt = EntityCreationUtils.createClientSpatialEntity();

View File

@ -18,7 +18,7 @@ import electrosphere.game.data.item.Item;
import java.util.List; import java.util.List;
import electrosphere.collision.PhysicsEntityUtils; import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.controls.PlayerCursor; import electrosphere.controls.cursor.CursorState;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
@ -177,12 +177,11 @@ public class ClientToolbarState implements BehaviorTree {
if(targetPoint != null && parent == Globals.playerEntity){ if(targetPoint != null && parent == Globals.playerEntity){
Item itemData = Globals.gameConfigCurrent.getItemMap().getItem(toEquip); Item itemData = Globals.gameConfigCurrent.getItemMap().getItem(toEquip);
if(Globals.playerCursor != null && Globals.playerBlockCursor != null){ if(Globals.playerCursor != null && Globals.playerBlockCursor != null){
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerCursor, EntityTags.DRAWABLE); CursorState.hide();
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerBlockCursor, EntityTags.DRAWABLE); if(itemData.getTokens().contains(CursorState.CURSOR_TOKEN)){
if(itemData.getTokens().contains(PlayerCursor.CURSOR_TOKEN)){ CursorState.makeRealVisible();
Globals.clientSceneWrapper.getScene().registerEntityToTag(Globals.playerCursor, EntityTags.DRAWABLE); } else if(itemData.getTokens().contains(CursorState.CURSOR_BLOCK_TOKEN)) {
} else if(itemData.getTokens().contains(PlayerCursor.CURSOR_BLOCK_TOKEN)) { CursorState.makeBlockVisible();
Globals.clientSceneWrapper.getScene().registerEntityToTag(Globals.playerBlockCursor, EntityTags.DRAWABLE);
} }
} }
} }

View File

@ -6,7 +6,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import electrosphere.controls.PlayerCursor; import electrosphere.controls.cursor.CursorState;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.game.data.block.BlockType; import electrosphere.game.data.block.BlockType;
@ -149,12 +149,13 @@ public class Item extends CommonEntityType {
//set usage //set usage
ItemUsage usage = new ItemUsage(); ItemUsage usage = new ItemUsage();
usage.setBlockId(blockType.getId()); usage.setBlockId(blockType.getId());
usage.setOnlyOnMouseDown(true);
rVal.setSecondaryUsage(usage); rVal.setSecondaryUsage(usage);
//attach common tokens //attach common tokens
List<String> tokens = new LinkedList<String>(Arrays.asList(DEFAULT_TOKENS)); List<String> tokens = new LinkedList<String>(Arrays.asList(DEFAULT_TOKENS));
tokens.add(PlayerCursor.CURSOR_BLOCK_TOKEN); tokens.add(CursorState.CURSOR_BLOCK_TOKEN);
rVal.setTokens(tokens); rVal.setTokens(tokens);
return rVal; return rVal;

View File

@ -238,9 +238,9 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
case UPDATEFLUIDDATA: { case UPDATEFLUIDDATA: {
Globals.clientFluidManager.attachFluidMessage(message); Globals.clientFluidManager.attachFluidMessage(message);
} break; } break;
default: default: {
LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype()); LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype());
break; } break;
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }

View File

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

View File

@ -28,6 +28,7 @@ public class TerrainMessage extends NetworkMessage {
REQUESTFLUIDDATA, REQUESTFLUIDDATA,
SENDFLUIDDATA, SENDFLUIDDATA,
UPDATEFLUIDDATA, UPDATEFLUIDDATA,
REQUESTEDITBLOCK,
} }
/** /**
@ -60,6 +61,7 @@ public class TerrainMessage extends NetworkMessage {
int terrainValue; int terrainValue;
int blockType; int blockType;
int blockMetadata; int blockMetadata;
int blockEditSize;
/** /**
* Constructor * Constructor
@ -445,6 +447,20 @@ public class TerrainMessage extends NetworkMessage {
this.blockMetadata = blockMetadata; this.blockMetadata = blockMetadata;
} }
/**
* Gets blockEditSize
*/
public int getblockEditSize() {
return blockEditSize;
}
/**
* Sets blockEditSize
*/
public void setblockEditSize(int blockEditSize) {
this.blockEditSize = blockEditSize;
}
/** /**
* Removes the packet header from the buffer * Removes the packet header from the buffer
* @param byteBuffer The buffer * @param byteBuffer The buffer
@ -543,6 +559,12 @@ public class TerrainMessage extends NetworkMessage {
return TerrainMessage.canParsesendFluidDataMessage(byteBuffer); return TerrainMessage.canParsesendFluidDataMessage(byteBuffer);
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEFLUIDDATA: case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEFLUIDDATA:
return TerrainMessage.canParseupdateFluidDataMessage(byteBuffer); return TerrainMessage.canParseupdateFluidDataMessage(byteBuffer);
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTEDITBLOCK:
if(byteBuffer.getRemaining() >= TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTEDITBLOCK_SIZE){
return true;
} else {
return false;
}
} }
return false; return false;
} }
@ -1203,6 +1225,43 @@ public class TerrainMessage extends NetworkMessage {
return rVal; return rVal;
} }
/**
* Parses a message of type RequestEditBlock
*/
public static TerrainMessage parseRequestEditBlockMessage(CircularByteBuffer byteBuffer, MessagePool pool){
TerrainMessage rVal = (TerrainMessage)pool.get(MessageType.TERRAIN_MESSAGE);
rVal.messageType = TerrainMessageType.REQUESTEDITBLOCK;
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.setblockType(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setblockMetadata(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setblockEditSize(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal;
}
/**
* Constructs a message of type RequestEditBlock
*/
public static TerrainMessage constructRequestEditBlockMessage(int worldX,int worldY,int worldZ,int voxelX,int voxelY,int voxelZ,int blockType,int blockMetadata,int blockEditSize){
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.REQUESTEDITBLOCK);
rVal.setworldX(worldX);
rVal.setworldY(worldY);
rVal.setworldZ(worldZ);
rVal.setvoxelX(voxelX);
rVal.setvoxelY(voxelY);
rVal.setvoxelZ(voxelZ);
rVal.setblockType(blockType);
rVal.setblockMetadata(blockMetadata);
rVal.setblockEditSize(blockEditSize);
rVal.serialize();
return rVal;
}
@Override @Override
void serialize(){ void serialize(){
byte[] intValues = new byte[8]; byte[] intValues = new byte[8];
@ -1667,6 +1726,49 @@ public class TerrainMessage extends NetworkMessage {
rawBytes[18+i] = chunkData[i]; rawBytes[18+i] = chunkData[i];
} }
break; break;
case REQUESTEDITBLOCK:
rawBytes = new byte[2+4+4+4+4+4+4+4+4+4];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
//entity messaage header
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTEDITBLOCK;
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(blockType);
for(int i = 0; i < 4; i++){
rawBytes[26+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(blockMetadata);
for(int i = 0; i < 4; i++){
rawBytes[30+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(blockEditSize);
for(int i = 0; i < 4; i++){
rawBytes[34+i] = intValues[i];
}
break;
} }
serialized = true; serialized = true;
} }

View File

@ -84,6 +84,7 @@ public class TypeBytes {
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTFLUIDDATA = 14; public static final byte TERRAIN_MESSAGE_TYPE_REQUESTFLUIDDATA = 14;
public static final byte TERRAIN_MESSAGE_TYPE_SENDFLUIDDATA = 15; 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_UPDATEFLUIDDATA = 16;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTEDITBLOCK = 17;
/* /*
Terrain packet sizes Terrain packet sizes
*/ */
@ -99,6 +100,7 @@ public class TypeBytes {
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTREDUCEDBLOCKDATA_SIZE = 18; public static final byte TERRAIN_MESSAGE_TYPE_REQUESTREDUCEDBLOCKDATA_SIZE = 18;
public static final byte TERRAIN_MESSAGE_TYPE_UPDATEBLOCK_SIZE = 34; public static final byte TERRAIN_MESSAGE_TYPE_UPDATEBLOCK_SIZE = 34;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTFLUIDDATA_SIZE = 14; public static final byte TERRAIN_MESSAGE_TYPE_REQUESTFLUIDDATA_SIZE = 14;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTEDITBLOCK_SIZE = 38;
/* /*
Server subcategories Server subcategories

View File

@ -7,10 +7,12 @@ import java.nio.ShortBuffer;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkData; import electrosphere.client.block.BlockChunkData;
import electrosphere.client.terrain.cache.ChunkData; import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
@ -18,6 +20,8 @@ import electrosphere.net.server.player.Player;
import electrosphere.net.template.ServerProtocolTemplate; import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerWorldData; import electrosphere.server.datacell.ServerWorldData;
import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.physics.block.editing.ServerBlockEditing;
import electrosphere.server.physics.fluid.manager.ServerFluidChunk; import electrosphere.server.physics.fluid.manager.ServerFluidChunk;
import electrosphere.server.physics.terrain.editing.TerrainEditing; import electrosphere.server.physics.terrain.editing.TerrainEditing;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
@ -80,6 +84,14 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
message.getworldX(), message.getworldY(), message.getworldZ() message.getworldX(), message.getworldY(), message.getworldZ()
); );
} break; } break;
case REQUESTEDITBLOCK: {
LoggerInterface.loggerNetworking.DEBUG("(Server) Received request to edit block at " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
Entity targetEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
Realm playerRealm = Globals.realmManager.getEntityRealm(targetEntity);
Vector3i worldPos = new Vector3i(message.getworldX(),message.getworldY(),message.getworldZ());
Vector3i blockPos = new Vector3i(message.getvoxelX(),message.getvoxelY(),message.getvoxelZ());
ServerBlockEditing.editBlockArea(playerRealm, worldPos, blockPos, (short)message.getblockType(), (short)message.getblockMetadata(), message.getblockEditSize());
} break;
//all ignored message types //all ignored message types
case UPDATEFLUIDDATA: case UPDATEFLUIDDATA:
case RESPONSEMETADATA: case RESPONSEMETADATA:

View File

@ -52,6 +52,9 @@ import electrosphere.renderer.pipelines.debug.DebugContentPipeline;
import electrosphere.renderer.shader.VisualShader; import electrosphere.renderer.shader.VisualShader;
import electrosphere.renderer.texture.Texture; import electrosphere.renderer.texture.Texture;
/**
* The main object for the rendering engine
*/
public class RenderingEngine { public class RenderingEngine {
@ -139,10 +142,9 @@ public class RenderingEngine {
*/ */
public static VisualShader compositeAnimeOutline; public static VisualShader compositeAnimeOutline;
/**
// public static boolean renderHitboxes = false; * The light manager for the rendering engine
// public static boolean renderPhysics = false; */
LightManager lightManager; LightManager lightManager;
public static int outputFramebuffer = 0; public static int outputFramebuffer = 0;
@ -178,7 +180,9 @@ public class RenderingEngine {
RenderScreenPipeline renderScreenPipeline = new RenderScreenPipeline(); RenderScreenPipeline renderScreenPipeline = new RenderScreenPipeline();
ImGuiPipeline imGuiPipeline; ImGuiPipeline imGuiPipeline;
/**
* Initializes the opengl context
*/
public void createOpenglContext(){ public void createOpenglContext(){
LoggerInterface.loggerRenderer.INFO("Create OpenGL Context"); LoggerInterface.loggerRenderer.INFO("Create OpenGL Context");
@ -306,16 +310,11 @@ public class RenderingEngine {
GL45.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); GL45.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL45.glClear(GL45.GL_COLOR_BUFFER_BIT | GL45.GL_DEPTH_BUFFER_BIT); GL45.glClear(GL45.GL_COLOR_BUFFER_BIT | GL45.GL_DEPTH_BUFFER_BIT);
// //Hide the cursor and capture it
// glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
//init screen rendering quadrant //init screen rendering quadrant
screenTextureVAO = createScreenTextureVAO(); screenTextureVAO = createScreenTextureVAO();
// initScreenTextureShaderProgram();
screenTextureShaders = VisualShader.loadSpecificShader("/Shaders/core/screentexture/simple1/simple1.vs", "/Shaders/core/screentexture/simple1/simple1.fs"); screenTextureShaders = VisualShader.loadSpecificShader("/Shaders/core/screentexture/simple1/simple1.vs", "/Shaders/core/screentexture/simple1/simple1.fs");
// screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.vs", "/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.fs");
//default framebuffer //default framebuffer
defaultFramebuffer = new Framebuffer(GL_DEFAULT_FRAMEBUFFER); defaultFramebuffer = new Framebuffer(GL_DEFAULT_FRAMEBUFFER);
@ -354,7 +353,6 @@ public class RenderingEngine {
} }
Texture lightBufferDepthTexture = lightDepthBuffer.getDepthTexture(); Texture lightBufferDepthTexture = lightDepthBuffer.getDepthTexture();
RenderingEngine.lightBufferDepthTexture = lightBufferDepthTexture; RenderingEngine.lightBufferDepthTexture = lightBufferDepthTexture;
// glEnable(GL_CULL_FACE); // enabled for shadow mapping
// //
//create volume depth framebuffer/shader for volumetric rendering //create volume depth framebuffer/shader for volumetric rendering
@ -372,11 +370,6 @@ public class RenderingEngine {
// //
//Game normals //Game normals
// //
/*
gameImageNormalsTexture;
static Framebuffer gameImageNormalsFramebuffer;
static ShaderProgram renderNormalsShader;
*/
try { try {
gameImageNormalsTexture = FramebufferUtils.generateScreenTextureColorAlpha(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY()); gameImageNormalsTexture = FramebufferUtils.generateScreenTextureColorAlpha(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
Texture gameImageNormalsDepthTexture = FramebufferUtils.generateScreenTextureDepth(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY()); Texture gameImageNormalsDepthTexture = FramebufferUtils.generateScreenTextureDepth(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
@ -409,7 +402,6 @@ public class RenderingEngine {
try { try {
normalsOutlineTexture = FramebufferUtils.generateScreenTextureColorAlpha(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY()); normalsOutlineTexture = FramebufferUtils.generateScreenTextureColorAlpha(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
normalsOutlineFrambuffer = FramebufferUtils.generateScreenTextureFramebuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), normalsOutlineTexture); normalsOutlineFrambuffer = FramebufferUtils.generateScreenTextureFramebuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), normalsOutlineTexture);
// normalsOutlineShader = ShaderProgram.loadSpecificShader("Shaders/anime/outlineNormals.vs", "Shaders/anime/outlineNormals.fs");
Globals.assetManager.addShaderToQueue("Shaders/core/anime/outlineNormals.vs", "Shaders/core/anime/outlineNormals.fs"); Globals.assetManager.addShaderToQueue("Shaders/core/anime/outlineNormals.vs", "Shaders/core/anime/outlineNormals.fs");
} catch(Exception e){ } catch(Exception e){
LoggerInterface.loggerRenderer.ERROR(e); LoggerInterface.loggerRenderer.ERROR(e);

View File

@ -3,6 +3,7 @@ package electrosphere.server.physics.block.editing;
import org.joml.Vector3i; import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkData; import electrosphere.client.block.BlockChunkData;
import electrosphere.controls.cursor.CursorState;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.interfaces.VoxelCellManager; import electrosphere.server.datacell.interfaces.VoxelCellManager;
@ -44,4 +45,28 @@ public class ServerBlockEditing {
} }
} }
/**
* Performs a series of block edits on an area of blocks. Basically has a sphere around the provided position that it attempts to add value to
* @param realm The realm to modify in
* @param worldPos The world position
* @param voxelPos The block position within the chunk at the world position
* @param type The new type of block
* @param metadata The new metadata for the block
* @param size The size of the area to edit
*/
public static void editBlockArea(Realm realm, Vector3i worldPos, Vector3i voxelPos, short type, short metadata, int size){
if(size < CursorState.MIN_BLOCK_SIZE || size > CursorState.MAX_BLOCK_SIZE){
throw new Error("Size out of bounds: " + size);
}
Vector3i pos = new Vector3i();
for(int x = 0; x < size; x++){
for(int y = 0; y < size; y++){
for(int z = 0; z < size; z++){
pos = new Vector3i(voxelPos).add(x,y,z);
ServerBlockEditing.editBlockChunk(realm, worldPos, pos, type, metadata);
}
}
}
}
} }

View File

@ -124,6 +124,10 @@
{ {
"name" : "blockMetadata", "name" : "blockMetadata",
"type" : "FIXED_INT" "type" : "FIXED_INT"
},
{
"name" : "blockEditSize",
"type" : "FIXED_INT"
} }
], ],
"messageTypes" : [ "messageTypes" : [
@ -311,6 +315,21 @@
"worldZ", "worldZ",
"chunkData" "chunkData"
] ]
},
{
"messageName" : "RequestEditBlock",
"description" : "Requests that a block be edited on the server",
"data" : [
"worldX",
"worldY",
"worldZ",
"voxelX",
"voxelY",
"voxelZ",
"blockType",
"blockMetadata",
"blockEditSize"
]
} }
] ]
} }