diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java index cb578d9..1df46cf 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java @@ -91,5 +91,14 @@ public class EntityAnchor implements Anchor { public Collection getCameraModes() { return modes; } + + public EntityData getEntity() { + return entity; + } + + @Override + public String toString() { + return "Anchor for entity " + entity; + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java index b25eaa5..82fcc1d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java @@ -214,6 +214,9 @@ public class LayerWorld extends Layer { if (ClientState.getInstance().getLocalPlayer().getEntity() == entity && tmp_testControls.isFlying()) { return; } + if (entity.getId().equals("Test:NoclipCamera")) { + return; + } Vec3 gravitationalAcceleration = Vectors.grab3(); gm.getGravity(entity.getPosition(), gravitationalAcceleration); diff --git a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java index 9b97e40..be85416 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java @@ -105,6 +105,9 @@ public class Collider { // For every pair of colls for (int i = 0; i < colls.size(); ++i) { Collideable a = colls.get(i); + if (a.getCollisionModel() == null) { + continue; + } tuneWorldCollisionHelper(a, tickLength, world, workspace); @@ -115,6 +118,10 @@ public class Collider { for (int j = i + 1; j < colls.size(); ++j) { Collideable b = colls.get(j); + if (b.getCollisionModel() == null) { + continue; + } + Collision collision = getCollision(a, b, tickLength, workspace); result = workspace.updateLatestCollision(result, collision); } diff --git a/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java b/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java index 2feb7e6..3b78898 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java @@ -235,7 +235,7 @@ public abstract class StatefulObject extends Namespaced implements Encodable { StatefulObject statefulObj = (StatefulObject) obj; - if (statefulObj.getId().equals(this.getId())) + if (!statefulObj.getId().equals(this.getId())) return false; return true; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java index bc00974..599893e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java @@ -379,5 +379,15 @@ public class EntityData extends StatefulObject implements Collideable, EntityGen super.read(input, context); } + + @Override + public boolean equals(Object obj) { + return this == obj; + } + + @Override + public int hashCode() { + return Long.hashCode(entityId); + } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java index f0414bc..a7d5f0d 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java +++ b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java @@ -18,26 +18,20 @@ package ru.windcorp.progressia.test; -import glm.Glm; -import glm.mat._4.Mat4; -import glm.vec._3.Vec3; import org.lwjgl.glfw.GLFW; import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; -import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent; import ru.windcorp.progressia.client.graphics.world.LocalPlayer; import ru.windcorp.progressia.client.localization.Localizer; -import ru.windcorp.progressia.common.util.Matrices; -import ru.windcorp.progressia.common.util.VectorUtil; -import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.tile.TileData; +import ru.windcorp.progressia.test.controls.CameraControls; import ru.windcorp.progressia.test.controls.MovementControls; public class TestPlayerControls { @@ -49,6 +43,7 @@ public class TestPlayerControls { } private final MovementControls movementControls = new MovementControls(); + private final CameraControls cameraControls = new CameraControls(); private int selectedBlock = 0; private int selectedTile = 0; @@ -66,7 +61,8 @@ public class TestPlayerControls { private void reset() { movementControls.reset(); - + cameraControls.reset(); + debugLayer = null; selectedBlock = 0; selectedTile = 0; @@ -79,6 +75,7 @@ public class TestPlayerControls { public void registerControls() { movementControls.registerControls(); + cameraControls.registerControls(); } public void handleInput(InputEvent event) { @@ -86,9 +83,6 @@ public class TestPlayerControls { if (onKeyEvent((KeyEvent) event)) { event.consume(); } - } else if (event instanceof CursorMoveEvent) { - onMouseMoved((CursorMoveEvent) event); - event.consume(); } } @@ -112,10 +106,6 @@ public class TestPlayerControls { handleDebugLayerSwitch(); break; - case GLFW.GLFW_KEY_F5: - handleCameraMode(); - break; - case GLFW.GLFW_KEY_L: handleLanguageSwitch(); break; @@ -143,16 +133,6 @@ public class TestPlayerControls { } } - private void handleCameraMode() { - if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { - return; - } - - if (ClientState.getInstance().getCamera().hasAnchor()) { - ClientState.getInstance().getCamera().selectNextMode(); - } - } - private void handleLanguageSwitch() { Localizer localizer = Localizer.getInstance(); if (localizer.getLanguage().equals("ru-RU")) { @@ -162,43 +142,6 @@ public class TestPlayerControls { } } - private void onMouseMoved(CursorMoveEvent event) { - if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { - return; - } - - final double yawScale = -0.002f; - final double pitchScale = -yawScale; - final double pitchExtremum = Math.PI/2 * 0.95f; - - double yawChange = event.getChangeX() * yawScale; - double pitchChange = event.getChangeY() * pitchScale; - - EntityData player = getEntity(); - - double startPitch = player.getPitch(); - double endPitch = startPitch + pitchChange; - endPitch = Glm.clamp(endPitch, -pitchExtremum, +pitchExtremum); - pitchChange = endPitch - startPitch; - - Mat4 mat = Matrices.grab4(); - Vec3 lookingAt = Vectors.grab3(); - Vec3 rightVector = Vectors.grab3(); - - rightVector.set(player.getLookingAt()).cross(player.getUpVector()).normalize(); - - mat.identity() - .rotate((float) yawChange, player.getUpVector()) - .rotate((float) pitchChange, rightVector); - - VectorUtil.applyMat4(player.getLookingAt(), mat, lookingAt); - player.setLookingAt(lookingAt); - - Vectors.release(rightVector); - Vectors.release(lookingAt); - Matrices.release(mat); - } - public void switchPlacingMode() { isBlockSelected = !isBlockSelected; } diff --git a/src/main/java/ru/windcorp/progressia/test/controls/CameraControls.java b/src/main/java/ru/windcorp/progressia/test/controls/CameraControls.java new file mode 100644 index 0000000..0214170 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/controls/CameraControls.java @@ -0,0 +1,130 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.test.controls; + +import glm.Glm; +import glm.mat._4.Mat4; +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.ClientState; +import ru.windcorp.progressia.client.comms.controls.ControlTriggerRegistry; +import ru.windcorp.progressia.client.comms.controls.ControlTriggers; +import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; +import ru.windcorp.progressia.client.graphics.input.KeyEvent; +import ru.windcorp.progressia.client.graphics.input.KeyMatcher; +import ru.windcorp.progressia.client.graphics.world.Camera; +import ru.windcorp.progressia.client.graphics.world.EntityAnchor; +import ru.windcorp.progressia.common.util.Matrices; +import ru.windcorp.progressia.common.util.VectorUtil; +import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.entity.EntityData; + +public class CameraControls { + + { + reset(); + } + + public void reset() { + // No instance fields; futureproofing + } + + public void registerControls() { + ControlTriggerRegistry triggers = ControlTriggerRegistry.getInstance(); + + triggers.register( + ControlTriggers.localOf( + "Test:TurnCameraWithCursor", + CursorMoveEvent.class, + this::turnCameraWithCursor + ) + ); + + triggers.register( + ControlTriggers.localOf( + "Test:SwitchCameraMode", + KeyEvent.class, + this::switchCameraMode, + new KeyMatcher("F5")::matches + ) + ); + + NoclipCamera.register(); + + triggers.register( + ControlTriggers.localOf( + "Test:ToggleNoclip", + KeyEvent.class, + NoclipCamera::toggleNoclip, + new KeyMatcher("V")::matches + ) + ); + } + + private void turnCameraWithCursor(CursorMoveEvent event) { + if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { + return; + } + + Camera.Anchor cameraAnchor = ClientState.getInstance().getCamera().getAnchor(); + if (!(cameraAnchor instanceof EntityAnchor)) { + return; + } + + EntityData player = ((EntityAnchor) cameraAnchor).getEntity(); + + final double yawScale = -0.002f; + final double pitchScale = -yawScale; + final double pitchExtremum = Math.PI / 2 * 0.995f; + + double yawChange = event.getChangeX() * yawScale; + double pitchChange = event.getChangeY() * pitchScale; + + double startPitch = player.getPitch(); + double endPitch = startPitch + pitchChange; + endPitch = Glm.clamp(endPitch, -pitchExtremum, +pitchExtremum); + pitchChange = endPitch - startPitch; + + Mat4 mat = Matrices.grab4(); + Vec3 lookingAt = Vectors.grab3(); + Vec3 rightVector = Vectors.grab3(); + + rightVector.set(player.getLookingAt()).cross(player.getUpVector()).normalize(); + + mat.identity() + .rotate((float) yawChange, player.getUpVector()) + .rotate((float) pitchChange, rightVector); + + VectorUtil.applyMat4(player.getLookingAt(), mat, lookingAt); + player.setLookingAt(lookingAt); + + Vectors.release(rightVector); + Vectors.release(lookingAt); + Matrices.release(mat); + } + + private void switchCameraMode() { + if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { + return; + } + + if (ClientState.getInstance().getCamera().hasAnchor()) { + ClientState.getInstance().getCamera().selectNextMode(); + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java b/src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java index 14f6207..0019ec4 100644 --- a/src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java +++ b/src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java @@ -28,6 +28,8 @@ import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; import ru.windcorp.progressia.client.graphics.backend.InputTracker; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.KeyMatcher; +import ru.windcorp.progressia.client.graphics.world.Camera; +import ru.windcorp.progressia.client.graphics.world.EntityAnchor; import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.world.entity.EntityData; @@ -96,8 +98,15 @@ public class MovementControls { return; } - EntityData player = ClientState.getInstance().getLocalPlayer().getEntity(); - assert player != null; + Camera.Anchor cameraAnchor = ClientState.getInstance().getCamera().getAnchor(); + if (!(cameraAnchor instanceof EntityAnchor)) { + return; + } + + EntityData player = ((EntityAnchor) cameraAnchor).getEntity(); + + boolean isFlying = this.isFlying || player.getId().equals("Test:NoclipCamera"); + boolean isSprinting = this.isSprinting || player.getId().equals("Test:NoclipCamera"); final float speed, authority; @@ -110,7 +119,7 @@ public class MovementControls { } Mat3 movementTransform = getMovementTransform(player, null); - Vec3 desiredVelocity = getDesiredVelocity(movementTransform, speed); + Vec3 desiredVelocity = getDesiredVelocity(movementTransform, speed, isFlying); Vec3 newVelocity = getNewVelocity(desiredVelocity, player.getVelocity(), authority, player.getUpVector()); player.getVelocity().set(newVelocity); @@ -144,7 +153,7 @@ public class MovementControls { //@formatter:on } - private Vec3 getDesiredVelocity(Mat3 movementTransform, float speed) { + private Vec3 getDesiredVelocity(Mat3 movementTransform, float speed, boolean isFlying) { int forward = 0; int right = 0; int up = 0; diff --git a/src/main/java/ru/windcorp/progressia/test/controls/NoclipCamera.java b/src/main/java/ru/windcorp/progressia/test/controls/NoclipCamera.java new file mode 100644 index 0000000..751cf8a --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/controls/NoclipCamera.java @@ -0,0 +1,99 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.test.controls; + +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.ClientState; +import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; +import ru.windcorp.progressia.client.graphics.world.Camera; +import ru.windcorp.progressia.client.graphics.world.EntityAnchor; +import ru.windcorp.progressia.client.world.WorldRender; +import ru.windcorp.progressia.client.world.entity.EntityRender; +import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; +import ru.windcorp.progressia.client.world.entity.EntityRenderable; +import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; + +public class NoclipCamera { + + private static class NoclipEntityRender extends EntityRender { + + public NoclipEntityRender() { + super("Test:NoclipCamera"); + } + + @Override + public EntityRenderable createRenderable(EntityData entity) { + return new NoclipEntityRenderable(entity); + } + + } + + private static class NoclipEntityRenderable extends EntityRenderable { + + public NoclipEntityRenderable(EntityData data) { + super(data); + } + + @Override + protected void doRender(ShapeRenderHelper renderer) { + // Do nothing + } + + } + + public static void register() { + EntityDataRegistry.getInstance().register("Test:NoclipCamera"); + EntityRenderRegistry.getInstance().register(new NoclipEntityRender()); + } + + public static void toggleNoclip() { + if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { + return; + } + + Camera camera = ClientState.getInstance().getCamera(); + WorldRender world = ClientState.getInstance().getWorld(); + EntityData player = ClientState.getInstance().getLocalPlayer().getEntity(); + + List existingCameras = world.getData().getEntities().stream().filter(e -> e.getId().equals("Test:NoclipCamera")).collect(Collectors.toList()); + if (!existingCameras.isEmpty()) { + existingCameras.forEach(world.getData()::removeEntity); + camera.setAnchor(new EntityAnchor(world.getEntityRenderable(player))); + return; + } + + EntityData noclipCamera = EntityDataRegistry.getInstance().create("Test:NoclipCamera"); + + noclipCamera.setLookingAt(player.getLookingAt()); + noclipCamera.setUpVector(player.getUpVector()); + noclipCamera.setPosition(player.getPosition()); + noclipCamera.setVelocity(player.getVelocity()); + noclipCamera.setEntityId(new Random().nextLong()); + + player.setVelocity(new Vec3(0)); + + world.getData().addEntity(noclipCamera); + camera.setAnchor(new EntityAnchor(world.getEntityRenderable(noclipCamera))); + } + +}