Added better block color picking, smg and flag models, and implemented gun accuracy.
This commit is contained in:
parent
cefaeae5f6
commit
0f31f32607
|
@ -1,10 +1,7 @@
|
||||||
package nl.andrewl.aos2_client;
|
package nl.andrewl.aos2_client;
|
||||||
|
|
||||||
import nl.andrewl.aos2_client.config.ClientConfig;
|
import nl.andrewl.aos2_client.config.ClientConfig;
|
||||||
import nl.andrewl.aos2_client.control.InputHandler;
|
import nl.andrewl.aos2_client.control.*;
|
||||||
import nl.andrewl.aos2_client.control.PlayerInputKeyCallback;
|
|
||||||
import nl.andrewl.aos2_client.control.PlayerInputMouseClickCallback;
|
|
||||||
import nl.andrewl.aos2_client.control.PlayerViewCursorCallback;
|
|
||||||
import nl.andrewl.aos2_client.model.ClientPlayer;
|
import nl.andrewl.aos2_client.model.ClientPlayer;
|
||||||
import nl.andrewl.aos2_client.model.OtherPlayer;
|
import nl.andrewl.aos2_client.model.OtherPlayer;
|
||||||
import nl.andrewl.aos2_client.render.GameRenderer;
|
import nl.andrewl.aos2_client.render.GameRenderer;
|
||||||
|
@ -84,7 +81,8 @@ public class Client implements Runnable {
|
||||||
gameRenderer.setupWindow(
|
gameRenderer.setupWindow(
|
||||||
new PlayerViewCursorCallback(config.input, this, gameRenderer.getCamera(), communicationHandler),
|
new PlayerViewCursorCallback(config.input, this, gameRenderer.getCamera(), communicationHandler),
|
||||||
new PlayerInputKeyCallback(inputHandler),
|
new PlayerInputKeyCallback(inputHandler),
|
||||||
new PlayerInputMouseClickCallback(inputHandler)
|
new PlayerInputMouseClickCallback(inputHandler),
|
||||||
|
new PlayerInputMouseScrollCallback(this, communicationHandler)
|
||||||
);
|
);
|
||||||
soundManager = new SoundManager();
|
soundManager = new SoundManager();
|
||||||
log.debug("Sound system initialized.");
|
log.debug("Sound system initialized.");
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class ClientConfig {
|
||||||
|
|
||||||
public static class DisplayConfig {
|
public static class DisplayConfig {
|
||||||
public boolean fullscreen = false;
|
public boolean fullscreen = false;
|
||||||
public boolean captureCursor = true;
|
public boolean captureCursor = false;
|
||||||
public float fov = 70;
|
public float fov = 70;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package nl.andrewl.aos2_client.control;
|
package nl.andrewl.aos2_client.control;
|
||||||
|
|
||||||
import nl.andrewl.aos2_client.CommunicationHandler;
|
|
||||||
import nl.andrewl.aos_core.net.client.ClientInputState;
|
|
||||||
import nl.andrewl.aos2_client.Client;
|
import nl.andrewl.aos2_client.Client;
|
||||||
|
import nl.andrewl.aos2_client.CommunicationHandler;
|
||||||
|
import nl.andrewl.aos2_client.model.ClientPlayer;
|
||||||
|
import nl.andrewl.aos_core.model.item.BlockItemStack;
|
||||||
|
import nl.andrewl.aos_core.model.world.Hit;
|
||||||
|
import nl.andrewl.aos_core.net.client.BlockColorMessage;
|
||||||
|
import nl.andrewl.aos_core.net.client.ClientInputState;
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
@ -46,5 +50,19 @@ public class InputHandler {
|
||||||
comm.sendDatagramPacket(currentInputState);
|
comm.sendDatagramPacket(currentInputState);
|
||||||
lastInputState = currentInputState;
|
lastInputState = currentInputState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientPlayer player = client.getMyPlayer();
|
||||||
|
|
||||||
|
// Check for "pick block" functionality.
|
||||||
|
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_3) == GLFW_PRESS && player.getInventory().getSelectedItemStack() instanceof BlockItemStack stack) {
|
||||||
|
Hit hit = client.getWorld().getLookingAtPos(player.getEyePosition(), player.getViewVector(), 50);
|
||||||
|
if (hit != null) {
|
||||||
|
byte selectedBlock = client.getWorld().getBlockAt(hit.pos().x, hit.pos().y, hit.pos().z);
|
||||||
|
if (selectedBlock > 0) {
|
||||||
|
stack.setSelectedValue(selectedBlock);
|
||||||
|
comm.sendDatagramPacket(new BlockColorMessage(player.getId(), selectedBlock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package nl.andrewl.aos2_client.control;
|
||||||
|
|
||||||
|
import nl.andrewl.aos2_client.Client;
|
||||||
|
import nl.andrewl.aos2_client.CommunicationHandler;
|
||||||
|
import nl.andrewl.aos_core.model.item.BlockItemStack;
|
||||||
|
import nl.andrewl.aos_core.net.client.BlockColorMessage;
|
||||||
|
import org.lwjgl.glfw.GLFWScrollCallbackI;
|
||||||
|
|
||||||
|
public class PlayerInputMouseScrollCallback implements GLFWScrollCallbackI {
|
||||||
|
private final Client client;
|
||||||
|
private final CommunicationHandler comm;
|
||||||
|
|
||||||
|
public PlayerInputMouseScrollCallback(Client client, CommunicationHandler comm) {
|
||||||
|
this.client = client;
|
||||||
|
this.comm = comm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(long window, double xoffset, double yoffset) {
|
||||||
|
System.out.println(yoffset);
|
||||||
|
if (client.getMyPlayer().getInventory().getSelectedItemStack() instanceof BlockItemStack stack) {
|
||||||
|
if (yoffset < 0) {
|
||||||
|
stack.setSelectedValue((byte) (stack.getSelectedValue() - 1));
|
||||||
|
} else if (yoffset > 0) {
|
||||||
|
stack.setSelectedValue((byte) (stack.getSelectedValue() + 1));
|
||||||
|
}
|
||||||
|
comm.sendDatagramPacket(new BlockColorMessage(client.getMyPlayer().getId(), stack.getSelectedValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,7 +77,8 @@ public class GameRenderer {
|
||||||
public void setupWindow(
|
public void setupWindow(
|
||||||
GLFWCursorPosCallbackI viewCursorCallback,
|
GLFWCursorPosCallbackI viewCursorCallback,
|
||||||
GLFWKeyCallbackI inputKeyCallback,
|
GLFWKeyCallbackI inputKeyCallback,
|
||||||
GLFWMouseButtonCallbackI mouseButtonCallback
|
GLFWMouseButtonCallbackI mouseButtonCallback,
|
||||||
|
GLFWScrollCallbackI scrollCallback
|
||||||
) {
|
) {
|
||||||
GLFWErrorCallback.createPrint(System.err).set();
|
GLFWErrorCallback.createPrint(System.err).set();
|
||||||
if (!glfwInit()) throw new IllegalStateException("Could not initialize GLFW.");
|
if (!glfwInit()) throw new IllegalStateException("Could not initialize GLFW.");
|
||||||
|
@ -105,6 +106,7 @@ public class GameRenderer {
|
||||||
glfwSetKeyCallback(windowHandle, inputKeyCallback);
|
glfwSetKeyCallback(windowHandle, inputKeyCallback);
|
||||||
glfwSetCursorPosCallback(windowHandle, viewCursorCallback);
|
glfwSetCursorPosCallback(windowHandle, viewCursorCallback);
|
||||||
glfwSetMouseButtonCallback(windowHandle, mouseButtonCallback);
|
glfwSetMouseButtonCallback(windowHandle, mouseButtonCallback);
|
||||||
|
glfwSetScrollCallback(windowHandle, scrollCallback);
|
||||||
if (config.captureCursor) {
|
if (config.captureCursor) {
|
||||||
glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ public final class Net {
|
||||||
serializer.registerType(16, SoundMessage.class);
|
serializer.registerType(16, SoundMessage.class);
|
||||||
serializer.registerType(17, ProjectileMessage.class);
|
serializer.registerType(17, ProjectileMessage.class);
|
||||||
serializer.registerType(18, ClientHealthMessage.class);
|
serializer.registerType(18, ClientHealthMessage.class);
|
||||||
|
serializer.registerType(19, BlockColorMessage.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExtendedDataInputStream getInputStream(InputStream in) {
|
public static ExtendedDataInputStream getInputStream(InputStream in) {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package nl.andrewl.aos_core.net.client;
|
||||||
|
|
||||||
|
import nl.andrewl.record_net.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message that's sent when a client is holding a block item stack, and
|
||||||
|
* selects a different color. It's also sent to other clients to tell them that
|
||||||
|
* the player with the given id has selected a different block color.
|
||||||
|
*/
|
||||||
|
public record BlockColorMessage(
|
||||||
|
int clientId,
|
||||||
|
byte block
|
||||||
|
) implements Message {}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,7 @@ import nl.andrewl.aos2_server.model.ServerProjectile;
|
||||||
import nl.andrewl.aos_core.Directions;
|
import nl.andrewl.aos_core.Directions;
|
||||||
import nl.andrewl.aos_core.model.Player;
|
import nl.andrewl.aos_core.model.Player;
|
||||||
import nl.andrewl.aos_core.model.Projectile;
|
import nl.andrewl.aos_core.model.Projectile;
|
||||||
|
import nl.andrewl.aos_core.model.item.Gun;
|
||||||
import nl.andrewl.aos_core.model.world.Hit;
|
import nl.andrewl.aos_core.model.world.Hit;
|
||||||
import nl.andrewl.aos_core.net.client.ClientHealthMessage;
|
import nl.andrewl.aos_core.net.client.ClientHealthMessage;
|
||||||
import nl.andrewl.aos_core.net.client.SoundMessage;
|
import nl.andrewl.aos_core.net.client.SoundMessage;
|
||||||
|
@ -12,10 +13,7 @@ import nl.andrewl.aos_core.net.world.ChunkUpdateMessage;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,18 +34,30 @@ public class ProjectileManager {
|
||||||
this.removalQueue = new LinkedList<>();
|
this.removalQueue = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void spawnBullet(ServerPlayer player) {
|
public void spawnBullet(ServerPlayer player, Gun gun) {
|
||||||
int id = nextProjectileId++;
|
int id = nextProjectileId++;
|
||||||
if (nextProjectileId == Integer.MAX_VALUE) nextProjectileId = 1;
|
if (nextProjectileId == Integer.MAX_VALUE) nextProjectileId = 1;
|
||||||
|
Random rand = ThreadLocalRandom.current();
|
||||||
|
|
||||||
Vector3f pos = new Vector3f();
|
Vector3f pos = new Vector3f();
|
||||||
Matrix4f bulletTransform = new Matrix4f()
|
Matrix4f bulletTransform = new Matrix4f()
|
||||||
.translate(player.getEyePosition())
|
.translate(player.getEyePosition())
|
||||||
.rotate(player.getOrientation().x + (float) Math.PI, Directions.UPf)
|
.rotate(player.getOrientation().x + (float) Math.PI, Directions.UPf)
|
||||||
.translate(-0.35f, -0.4f, 0.35f);
|
.translate(-0.35f, -0.4f, 0.35f);
|
||||||
bulletTransform.transformPosition(pos);
|
bulletTransform.transformPosition(pos);
|
||||||
Vector3f vel = new Vector3f(player.getViewVector()).normalize()
|
|
||||||
|
Vector3f direction = new Vector3f(player.getViewVector()).normalize();
|
||||||
|
float accuracy = gun.getAccuracy();
|
||||||
|
accuracy -= server.getConfig().actions.movementAccuracyDecreaseFactor * player.getVelocity().length();
|
||||||
|
float perturbationFactor = (1 - accuracy) / 8;
|
||||||
|
direction.x += rand.nextGaussian(0, perturbationFactor);
|
||||||
|
direction.y += rand.nextGaussian(0, perturbationFactor);
|
||||||
|
direction.z += rand.nextGaussian(0, perturbationFactor);
|
||||||
|
|
||||||
|
Vector3f vel = new Vector3f(direction).normalize()
|
||||||
.mul(200 * MOVEMENT_FACTOR)
|
.mul(200 * MOVEMENT_FACTOR)
|
||||||
.add(player.getVelocity());
|
.add(player.getVelocity());
|
||||||
|
|
||||||
ServerProjectile bullet = new ServerProjectile(id, pos, vel, Projectile.Type.BULLET, player);
|
ServerProjectile bullet = new ServerProjectile(id, pos, vel, Projectile.Type.BULLET, player);
|
||||||
projectiles.put(bullet.getId(), bullet);
|
projectiles.put(bullet.getId(), bullet);
|
||||||
server.getPlayerManager().broadcastUdpMessage(bullet.toMessage(false));
|
server.getPlayerManager().broadcastUdpMessage(bullet.toMessage(false));
|
||||||
|
|
|
@ -5,9 +5,11 @@ import nl.andrewl.aos2_server.config.ServerConfig;
|
||||||
import nl.andrewl.aos2_server.logic.WorldUpdater;
|
import nl.andrewl.aos2_server.logic.WorldUpdater;
|
||||||
import nl.andrewl.aos2_server.model.ServerPlayer;
|
import nl.andrewl.aos2_server.model.ServerPlayer;
|
||||||
import nl.andrewl.aos_core.config.Config;
|
import nl.andrewl.aos_core.config.Config;
|
||||||
|
import nl.andrewl.aos_core.model.item.BlockItemStack;
|
||||||
import nl.andrewl.aos_core.model.world.World;
|
import nl.andrewl.aos_core.model.world.World;
|
||||||
import nl.andrewl.aos_core.model.world.Worlds;
|
import nl.andrewl.aos_core.model.world.Worlds;
|
||||||
import nl.andrewl.aos_core.net.UdpReceiver;
|
import nl.andrewl.aos_core.net.UdpReceiver;
|
||||||
|
import nl.andrewl.aos_core.net.client.BlockColorMessage;
|
||||||
import nl.andrewl.aos_core.net.client.ClientInputState;
|
import nl.andrewl.aos_core.net.client.ClientInputState;
|
||||||
import nl.andrewl.aos_core.net.client.ClientOrientationState;
|
import nl.andrewl.aos_core.net.client.ClientOrientationState;
|
||||||
import nl.andrewl.aos_core.net.connect.DatagramInit;
|
import nl.andrewl.aos_core.net.connect.DatagramInit;
|
||||||
|
@ -103,6 +105,12 @@ public class Server implements Runnable {
|
||||||
player.setOrientation(orientationState.x(), orientationState.y());
|
player.setOrientation(orientationState.x(), orientationState.y());
|
||||||
playerManager.broadcastUdpMessageToAllBut(player.getUpdateMessage(now), player);
|
playerManager.broadcastUdpMessageToAllBut(player.getUpdateMessage(now), player);
|
||||||
}
|
}
|
||||||
|
} else if (msg instanceof BlockColorMessage blockColorMessage) {
|
||||||
|
ServerPlayer player = playerManager.getPlayer(blockColorMessage.clientId());
|
||||||
|
if (player != null && player.getInventory().getSelectedItemStack() instanceof BlockItemStack stack) {
|
||||||
|
stack.setSelectedValue(blockColorMessage.block());
|
||||||
|
playerManager.broadcastUdpMessageToAllBut(blockColorMessage, player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,12 @@ public class ServerConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ActionsConfig {
|
public static class ActionsConfig {
|
||||||
public float blockRemoveCooldown = 0.25f;
|
public float blockBreakCooldown = 0.25f;
|
||||||
public float blockPlaceCooldown = 0.1f;
|
public float blockPlaceCooldown = 0.1f;
|
||||||
|
public float blockBreakReach = 5;
|
||||||
|
public float blockPlaceReach = 5;
|
||||||
public float resupplyCooldown = 30;
|
public float resupplyCooldown = 30;
|
||||||
public float resupplyRadius = 3;
|
public float resupplyRadius = 3;
|
||||||
|
public float movementAccuracyDecreaseFactor = 0.01f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ public class PlayerActionManager {
|
||||||
now - gunLastShotAt > gun.getShotCooldownTime() * 1000 &&
|
now - gunLastShotAt > gun.getShotCooldownTime() * 1000 &&
|
||||||
(gun.isAutomatic() || !gunNeedsReCock)
|
(gun.isAutomatic() || !gunNeedsReCock)
|
||||||
) {
|
) {
|
||||||
server.getProjectileManager().spawnBullet(player);
|
server.getProjectileManager().spawnBullet(player, gun);
|
||||||
g.setBulletCount(g.getBulletCount() - 1);
|
g.setBulletCount(g.getBulletCount() - 1);
|
||||||
gunLastShotAt = now;
|
gunLastShotAt = now;
|
||||||
if (!gun.isAutomatic()) {
|
if (!gun.isAutomatic()) {
|
||||||
|
@ -159,9 +159,9 @@ public class PlayerActionManager {
|
||||||
if (
|
if (
|
||||||
lastInputState.hitting() &&
|
lastInputState.hitting() &&
|
||||||
stack.getAmount() < stack.getType().getMaxAmount() &&
|
stack.getAmount() < stack.getType().getMaxAmount() &&
|
||||||
now - lastBlockRemovedAt > server.getConfig().actions.blockRemoveCooldown * 1000
|
now - lastBlockRemovedAt > server.getConfig().actions.blockBreakCooldown * 1000
|
||||||
) {
|
) {
|
||||||
var hit = world.getLookingAtPos(player.getEyePosition(), player.getViewVector(), 10);
|
var hit = world.getLookingAtPos(player.getEyePosition(), player.getViewVector(), server.getConfig().actions.blockBreakReach);
|
||||||
if (hit != null) {
|
if (hit != null) {
|
||||||
world.setBlockAt(hit.pos().x, hit.pos().y, hit.pos().z, (byte) 0);
|
world.setBlockAt(hit.pos().x, hit.pos().y, hit.pos().z, (byte) 0);
|
||||||
lastBlockRemovedAt = now;
|
lastBlockRemovedAt = now;
|
||||||
|
@ -177,7 +177,7 @@ public class PlayerActionManager {
|
||||||
stack.getAmount() > 0 &&
|
stack.getAmount() > 0 &&
|
||||||
now - lastBlockPlacedAt > server.getConfig().actions.blockPlaceCooldown * 1000
|
now - lastBlockPlacedAt > server.getConfig().actions.blockPlaceCooldown * 1000
|
||||||
) {
|
) {
|
||||||
var hit = world.getLookingAtPos(player.getEyePosition(), player.getViewVector(), 10);
|
var hit = world.getLookingAtPos(player.getEyePosition(), player.getViewVector(), server.getConfig().actions.blockPlaceReach);
|
||||||
if (hit != null) {
|
if (hit != null) {
|
||||||
Vector3i placePos = new Vector3i(hit.pos());
|
Vector3i placePos = new Vector3i(hit.pos());
|
||||||
placePos.add(hit.norm());
|
placePos.add(hit.norm());
|
||||||
|
|
Loading…
Reference in New Issue