Added GUI components for gun ammo, and rifle sound.
This commit is contained in:
parent
b88150fd3e
commit
219ccd94db
|
@ -8,6 +8,8 @@ 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;
|
||||||
|
import nl.andrewl.aos2_client.sound.SoundManager;
|
||||||
|
import nl.andrewl.aos2_client.sound.SoundSource;
|
||||||
import nl.andrewl.aos_core.config.Config;
|
import nl.andrewl.aos_core.config.Config;
|
||||||
import nl.andrewl.aos_core.model.Player;
|
import nl.andrewl.aos_core.model.Player;
|
||||||
import nl.andrewl.aos_core.model.Team;
|
import nl.andrewl.aos_core.model.Team;
|
||||||
|
@ -34,6 +36,8 @@ public class Client implements Runnable {
|
||||||
private final CommunicationHandler communicationHandler;
|
private final CommunicationHandler communicationHandler;
|
||||||
private final InputHandler inputHandler;
|
private final InputHandler inputHandler;
|
||||||
private GameRenderer gameRenderer;
|
private GameRenderer gameRenderer;
|
||||||
|
private SoundManager soundManager;
|
||||||
|
private SoundSource playerSource;
|
||||||
private long lastPlayerUpdate = 0;
|
private long lastPlayerUpdate = 0;
|
||||||
|
|
||||||
private ClientWorld world;
|
private ClientWorld world;
|
||||||
|
@ -81,6 +85,9 @@ public class Client implements Runnable {
|
||||||
new PlayerInputKeyCallback(inputHandler),
|
new PlayerInputKeyCallback(inputHandler),
|
||||||
new PlayerInputMouseClickCallback(inputHandler)
|
new PlayerInputMouseClickCallback(inputHandler)
|
||||||
);
|
);
|
||||||
|
soundManager = new SoundManager();
|
||||||
|
soundManager.load("rifle", "sound/m1garand-shot1.wav");
|
||||||
|
playerSource = new SoundSource();
|
||||||
|
|
||||||
long lastFrameAt = System.currentTimeMillis();
|
long lastFrameAt = System.currentTimeMillis();
|
||||||
while (!gameRenderer.windowShouldClose()) {
|
while (!gameRenderer.windowShouldClose()) {
|
||||||
|
@ -113,6 +120,7 @@ public class Client implements Runnable {
|
||||||
if (gameRenderer != null) {
|
if (gameRenderer != null) {
|
||||||
gameRenderer.getCamera().setToPlayer(myPlayer);
|
gameRenderer.getCamera().setToPlayer(myPlayer);
|
||||||
}
|
}
|
||||||
|
soundManager.updateListener(myPlayer.getPosition(), myPlayer.getVelocity());
|
||||||
lastPlayerUpdate = playerUpdate.timestamp();
|
lastPlayerUpdate = playerUpdate.timestamp();
|
||||||
} else {
|
} else {
|
||||||
OtherPlayer p = players.get(playerUpdate.clientId());
|
OtherPlayer p = players.get(playerUpdate.clientId());
|
||||||
|
@ -141,6 +149,8 @@ public class Client implements Runnable {
|
||||||
players.put(op.getId(), op);
|
players.put(op.getId(), op);
|
||||||
} else if (msg instanceof PlayerLeaveMessage leaveMessage) {
|
} else if (msg instanceof PlayerLeaveMessage leaveMessage) {
|
||||||
players.remove(leaveMessage.id());
|
players.remove(leaveMessage.id());
|
||||||
|
} else if (msg instanceof SoundMessage soundMessage) {
|
||||||
|
playerSource.play(soundManager.getSoundBuffer(soundMessage.name()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class InputHandler {
|
||||||
glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS,
|
glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS,
|
||||||
glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS,
|
glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS,
|
||||||
glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS,
|
glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS,
|
||||||
|
glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS,
|
||||||
selectedInventoryIndex
|
selectedInventoryIndex
|
||||||
);
|
);
|
||||||
if (!currentInputState.equals(lastInputState)) {
|
if (!currentInputState.equals(lastInputState)) {
|
||||||
|
|
|
@ -8,6 +8,8 @@ import nl.andrewl.aos2_client.render.gui.GUIRenderer;
|
||||||
import nl.andrewl.aos2_client.render.gui.GUITexture;
|
import nl.andrewl.aos2_client.render.gui.GUITexture;
|
||||||
import nl.andrewl.aos2_client.render.model.Model;
|
import nl.andrewl.aos2_client.render.model.Model;
|
||||||
import nl.andrewl.aos_core.model.item.BlockItemStack;
|
import nl.andrewl.aos_core.model.item.BlockItemStack;
|
||||||
|
import nl.andrewl.aos_core.model.item.Gun;
|
||||||
|
import nl.andrewl.aos_core.model.item.GunItemStack;
|
||||||
import nl.andrewl.aos_core.model.item.ItemTypes;
|
import nl.andrewl.aos_core.model.item.ItemTypes;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
@ -44,6 +46,11 @@ public class GameRenderer {
|
||||||
private Model rifleModel;
|
private Model rifleModel;
|
||||||
private Model blockModel;
|
private Model blockModel;
|
||||||
|
|
||||||
|
// Standard GUI textures.
|
||||||
|
private GUITexture crosshairTexture;
|
||||||
|
private GUITexture clipTexture;
|
||||||
|
private GUITexture bulletTexture;
|
||||||
|
|
||||||
private long windowHandle;
|
private long windowHandle;
|
||||||
private int screenWidth = 800;
|
private int screenWidth = 800;
|
||||||
private int screenHeight = 600;
|
private int screenHeight = 600;
|
||||||
|
@ -110,17 +117,16 @@ public class GameRenderer {
|
||||||
|
|
||||||
this.chunkRenderer = new ChunkRenderer();
|
this.chunkRenderer = new ChunkRenderer();
|
||||||
log.debug("Initialized chunk renderer.");
|
log.debug("Initialized chunk renderer.");
|
||||||
|
|
||||||
this.guiRenderer = new GUIRenderer();
|
this.guiRenderer = new GUIRenderer();
|
||||||
// TODO: More organized way to load textures for GUI.
|
crosshairTexture = new GUITexture("gui/crosshair.png");
|
||||||
try {
|
clipTexture = new GUITexture("gui/clip.png");
|
||||||
var crosshairTexture = new GUITexture("gui/crosshair.png");
|
bulletTexture = new GUITexture("gui/bullet.png");
|
||||||
float size = 32;
|
guiRenderer.addTexture("crosshair", crosshairTexture);
|
||||||
crosshairTexture.getScale().set(size / screenWidth, size / screenHeight);
|
guiRenderer.addTexture("clip", clipTexture);
|
||||||
guiRenderer.addTexture(crosshairTexture);
|
guiRenderer.addTexture("bullet", bulletTexture);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
log.debug("Initialized GUI renderer.");
|
log.debug("Initialized GUI renderer.");
|
||||||
|
|
||||||
this.modelRenderer = new ModelRenderer();
|
this.modelRenderer = new ModelRenderer();
|
||||||
try {
|
try {
|
||||||
playerModel = new Model("model/player_simple.obj", "model/simple_player.png");
|
playerModel = new Model("model/player_simple.obj", "model/simple_player.png");
|
||||||
|
@ -212,7 +218,32 @@ public class GameRenderer {
|
||||||
|
|
||||||
modelRenderer.end();
|
modelRenderer.end();
|
||||||
|
|
||||||
guiRenderer.draw();
|
// GUI rendering
|
||||||
|
guiRenderer.start();
|
||||||
|
guiRenderer.draw(crosshairTexture, crosshairTexture.getIdealScaleX(32, screenWidth), crosshairTexture.getIdealScaleY(32, screenHeight), 0, 0);
|
||||||
|
// If we're holding a gun, draw clip and bullet graphics.
|
||||||
|
if (client.getMyPlayer().getInventory().getSelectedItemStack().getType() instanceof Gun) {
|
||||||
|
GunItemStack stack = (GunItemStack) client.getMyPlayer().getInventory().getSelectedItemStack();
|
||||||
|
for (int i = 0; i < stack.getClipCount(); i++) {
|
||||||
|
guiRenderer.draw(
|
||||||
|
clipTexture,
|
||||||
|
clipTexture.getIdealScaleX(64, screenWidth),
|
||||||
|
clipTexture.getIdealScaleY(clipTexture.getIdealHeight(64), screenHeight),
|
||||||
|
0.90f,
|
||||||
|
-0.90f + (i * 0.15f)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < stack.getBulletCount(); i++) {
|
||||||
|
guiRenderer.draw(
|
||||||
|
bulletTexture,
|
||||||
|
bulletTexture.getIdealScaleX(16, screenWidth),
|
||||||
|
bulletTexture.getIdealScaleY(bulletTexture.getIdealHeight(16), screenHeight),
|
||||||
|
0.80f - (i * 0.05f),
|
||||||
|
-0.90f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guiRenderer.end();
|
||||||
|
|
||||||
glfwSwapBuffers(windowHandle);
|
glfwSwapBuffers(windowHandle);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
|
@ -5,8 +5,8 @@ import org.joml.Matrix4f;
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
||||||
|
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL46.*;
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
@ -19,9 +19,10 @@ public class GUIRenderer {
|
||||||
private final int vertexCount;
|
private final int vertexCount;
|
||||||
private final ShaderProgram shaderProgram;
|
private final ShaderProgram shaderProgram;
|
||||||
private final int transformUniformLocation;
|
private final int transformUniformLocation;
|
||||||
|
private final Matrix4f transformMatrix;
|
||||||
|
private final float[] transformMatrixData;
|
||||||
|
|
||||||
|
private final Map<String, GUITexture> textures = new HashMap<>();
|
||||||
private final List<GUITexture> guiTextures = new ArrayList<>();
|
|
||||||
|
|
||||||
public GUIRenderer() {
|
public GUIRenderer() {
|
||||||
vaoId = glGenVertexArrays();
|
vaoId = glGenVertexArrays();
|
||||||
|
@ -47,38 +48,52 @@ public class GUIRenderer {
|
||||||
.build();
|
.build();
|
||||||
transformUniformLocation = shaderProgram.getUniform("transform");
|
transformUniformLocation = shaderProgram.getUniform("transform");
|
||||||
shaderProgram.bindAttribute(0, "position");
|
shaderProgram.bindAttribute(0, "position");
|
||||||
|
this.transformMatrix = new Matrix4f();
|
||||||
|
this.transformMatrixData = new float[16];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTexture(GUITexture texture) {
|
public void loadTexture(String name, String resource) {
|
||||||
guiTextures.add(texture);
|
textures.put(name, new GUITexture(resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw() {
|
public void addTexture(String name, GUITexture texture) {
|
||||||
|
textures.put(name, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
shaderProgram.use();
|
shaderProgram.use();
|
||||||
glBindVertexArray(vaoId);
|
glBindVertexArray(vaoId);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
for (var texture : guiTextures) {
|
}
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
Matrix4f transform = new Matrix4f()
|
public void draw(String name, float scaleX, float scaleY, float x, float y) {
|
||||||
.translate(texture.getPosition().x, texture.getPosition().y, 0)
|
draw(textures.get(name), scaleX, scaleY, x, y);
|
||||||
.scale(texture.getScale().x, texture.getScale().y, 1);
|
}
|
||||||
float[] transformData = new float[16];
|
|
||||||
transform.get(transformData);
|
public void draw(GUITexture texture, float scaleX, float scaleY, float x, float y) {
|
||||||
glUniformMatrix4fv(transformUniformLocation, false, transformData);
|
glActiveTexture(0);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.getTextureId());
|
transformMatrix.identity()
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount);
|
.translate(x, y, 0)
|
||||||
}
|
.scale(scaleX, scaleY, 1)
|
||||||
|
.get(transformMatrixData);
|
||||||
|
glUniformMatrix4fv(transformUniformLocation, false, transformMatrixData);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture.getTextureId());
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void end() {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDisableVertexAttribArray(0);
|
glDisableVertexAttribArray(0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
shaderProgram.stopUsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void free() {
|
public void free() {
|
||||||
for (var tex : guiTextures) tex.free();
|
for (var tex : textures.values()) tex.free();
|
||||||
glDeleteBuffers(vboId);
|
glDeleteBuffers(vboId);
|
||||||
glDeleteVertexArrays(vaoId);
|
glDeleteVertexArrays(vaoId);
|
||||||
shaderProgram.free();
|
shaderProgram.free();
|
||||||
|
|
|
@ -2,7 +2,6 @@ package nl.andrewl.aos2_client.render.gui;
|
||||||
|
|
||||||
import nl.andrewl.aos_core.ImageUtils;
|
import nl.andrewl.aos_core.ImageUtils;
|
||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
@ -10,14 +9,21 @@ import java.io.IOException;
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL46.*;
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a texture loaded onto the GPU.
|
||||||
|
*/
|
||||||
public class GUITexture {
|
public class GUITexture {
|
||||||
private final int textureId;
|
private final int textureId;
|
||||||
|
/**
|
||||||
|
* The original image's width.
|
||||||
|
*/
|
||||||
private final int width;
|
private final int width;
|
||||||
|
/**
|
||||||
|
* The original image's height.
|
||||||
|
*/
|
||||||
private final int height;
|
private final int height;
|
||||||
private final Vector2f position = new Vector2f(0, 0);
|
|
||||||
private final Vector2f scale = new Vector2f(1, 1);
|
|
||||||
|
|
||||||
public GUITexture(String location) throws IOException {
|
public GUITexture(String location) {
|
||||||
try (var in = GUITexture.class.getClassLoader().getResourceAsStream(location)) {
|
try (var in = GUITexture.class.getClassLoader().getResourceAsStream(location)) {
|
||||||
if (in == null) throw new IOException("Couldn't load texture image from " + location);
|
if (in == null) throw new IOException("Couldn't load texture image from " + location);
|
||||||
BufferedImage img = ImageIO.read(in);
|
BufferedImage img = ImageIO.read(in);
|
||||||
|
@ -31,21 +37,43 @@ public class GUITexture {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
var buf = ImageUtils.decodePng(img);
|
var buf = ImageUtils.decodePng(img);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed to load GUI texture.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAspectRatio() {
|
||||||
|
return (float) width / height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getIdealHeight(float width) {
|
||||||
|
return width / getAspectRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getIdealWidth(float height) {
|
||||||
|
return height * getAspectRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getIdealScaleX(float desiredWidth, float screenWidth) {
|
||||||
|
return desiredWidth / screenWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getIdealScaleY(float desiredHeight, float screenHeight) {
|
||||||
|
return desiredHeight / screenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
public int getTextureId() {
|
public int getTextureId() {
|
||||||
return textureId;
|
return textureId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2f getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2f getScale() {
|
|
||||||
return scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void free() {
|
public void free() {
|
||||||
glDeleteTextures(textureId);
|
glDeleteTextures(textureId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package nl.andrewl.aos2_client.sound;
|
||||||
|
|
||||||
|
import nl.andrewl.aos2_client.model.ClientPlayer;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
import org.lwjgl.openal.AL;
|
||||||
|
import org.lwjgl.openal.ALC;
|
||||||
|
import org.lwjgl.openal.ALCCapabilities;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.lwjgl.openal.ALC10.*;
|
||||||
|
import static org.lwjgl.openal.AL10.*;
|
||||||
|
|
||||||
|
public class SoundManager {
|
||||||
|
private final long alContext;
|
||||||
|
private final Map<String, Integer> audioBuffers = new HashMap<>();
|
||||||
|
|
||||||
|
public SoundManager() {
|
||||||
|
long device = alcOpenDevice((ByteBuffer) null);
|
||||||
|
ALCCapabilities capabilities = ALC.createCapabilities(device);
|
||||||
|
alContext = alcCreateContext(device, (IntBuffer) null);
|
||||||
|
alcMakeContextCurrent(alContext);
|
||||||
|
AL.createCapabilities(capabilities);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String name, String resource) {
|
||||||
|
int bufferId = alGenBuffers();
|
||||||
|
audioBuffers.put(name, bufferId);
|
||||||
|
WaveData waveData = WaveData.create(resource);
|
||||||
|
alBufferData(bufferId, waveData.format, waveData.data, waveData.samplerate);
|
||||||
|
waveData.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateListener(Vector3f position, Vector3f velocity) {
|
||||||
|
alListener3f(AL_POSITION, position.x(), position.y(), position.z());
|
||||||
|
alListener3f(AL_VELOCITY, velocity.x(), velocity.y(), velocity.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSoundBuffer(String name) {
|
||||||
|
return audioBuffers.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void free() {
|
||||||
|
for (var bufferId : audioBuffers.values()) {
|
||||||
|
alDeleteBuffers(bufferId);
|
||||||
|
}
|
||||||
|
alcDestroyContext(alContext);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package nl.andrewl.aos2_client.sound;
|
||||||
|
|
||||||
|
import static org.lwjgl.openal.AL10.*;
|
||||||
|
|
||||||
|
public class SoundSource {
|
||||||
|
private final int sourceId;
|
||||||
|
|
||||||
|
public SoundSource() {
|
||||||
|
sourceId = alGenSources();
|
||||||
|
alSourcef(sourceId, AL_GAIN, 1);
|
||||||
|
alSourcef(sourceId, AL_PITCH, 1);
|
||||||
|
alSource3f(sourceId, AL_POSITION, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void play(int bufferId) {
|
||||||
|
alSourcei(sourceId, AL_BUFFER, bufferId);
|
||||||
|
alSourcePlay(sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void free() {
|
||||||
|
alDeleteSources(sourceId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package nl.andrewl.aos2_client.sound;
|
||||||
|
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.openal.AL10;
|
||||||
|
|
||||||
|
import javax.sound.sampled.AudioFormat;
|
||||||
|
import javax.sound.sampled.AudioInputStream;
|
||||||
|
import javax.sound.sampled.AudioSystem;
|
||||||
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class WaveData {
|
||||||
|
|
||||||
|
final int format;
|
||||||
|
final int samplerate;
|
||||||
|
final int totalBytes;
|
||||||
|
final int bytesPerFrame;
|
||||||
|
final ByteBuffer data;
|
||||||
|
|
||||||
|
private final AudioInputStream audioStream;
|
||||||
|
private final byte[] dataArray;
|
||||||
|
|
||||||
|
private WaveData(AudioInputStream stream) {
|
||||||
|
this.audioStream = stream;
|
||||||
|
AudioFormat audioFormat = stream.getFormat();
|
||||||
|
format = getOpenAlFormat(audioFormat.getChannels(), audioFormat.getSampleSizeInBits());
|
||||||
|
this.samplerate = (int) audioFormat.getSampleRate();
|
||||||
|
this.bytesPerFrame = audioFormat.getFrameSize();
|
||||||
|
this.totalBytes = (int) (stream.getFrameLength() * bytesPerFrame);
|
||||||
|
this.data = BufferUtils.createByteBuffer(totalBytes);
|
||||||
|
this.dataArray = new byte[totalBytes];
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void dispose() {
|
||||||
|
try {
|
||||||
|
audioStream.close();
|
||||||
|
data.clear();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuffer loadData() {
|
||||||
|
try {
|
||||||
|
int bytesRead = audioStream.read(dataArray, 0, totalBytes);
|
||||||
|
data.clear();
|
||||||
|
data.put(dataArray, 0, bytesRead);
|
||||||
|
data.flip();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.err.println("Couldn't read bytes from audio stream!");
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static WaveData create(String file){
|
||||||
|
InputStream stream = WaveData.class.getClassLoader().getResourceAsStream(file);
|
||||||
|
if (stream == null) {
|
||||||
|
System.err.println("Couldn't find file: " + file);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
InputStream bufferedInput = new BufferedInputStream(stream);
|
||||||
|
AudioInputStream audioStream;
|
||||||
|
try {
|
||||||
|
audioStream = AudioSystem.getAudioInputStream(bufferedInput);
|
||||||
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return new WaveData(audioStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static int getOpenAlFormat(int channels, int bitsPerSample) {
|
||||||
|
if (channels == 1) {
|
||||||
|
return bitsPerSample == 8 ? AL10.AL_FORMAT_MONO8 : AL10.AL_FORMAT_MONO16;
|
||||||
|
} else {
|
||||||
|
return bitsPerSample == 8 ? AL10.AL_FORMAT_STEREO8 : AL10.AL_FORMAT_STEREO16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
@ -42,6 +42,7 @@ public final class Net {
|
||||||
serializer.registerTypeSerializer(13, new InventorySerializer());
|
serializer.registerTypeSerializer(13, new InventorySerializer());
|
||||||
serializer.registerTypeSerializer(14, new ItemStackSerializer());
|
serializer.registerTypeSerializer(14, new ItemStackSerializer());
|
||||||
serializer.registerType(15, InventorySelectedStackMessage.class);
|
serializer.registerType(15, InventorySelectedStackMessage.class);
|
||||||
|
serializer.registerType(16, SoundMessage.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExtendedDataInputStream getInputStream(InputStream in) {
|
public static ExtendedDataInputStream getInputStream(InputStream in) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ public class Gun extends Item {
|
||||||
private final float reloadTime;
|
private final float reloadTime;
|
||||||
private final float baseDamage;
|
private final float baseDamage;
|
||||||
private final float recoil;
|
private final float recoil;
|
||||||
|
private boolean automatic;
|
||||||
|
|
||||||
public Gun(
|
public Gun(
|
||||||
int id,
|
int id,
|
||||||
|
@ -25,7 +26,8 @@ public class Gun extends Item {
|
||||||
float shotCooldownTime,
|
float shotCooldownTime,
|
||||||
float reloadTime,
|
float reloadTime,
|
||||||
float baseDamage,
|
float baseDamage,
|
||||||
float recoil
|
float recoil,
|
||||||
|
boolean automatic
|
||||||
) {
|
) {
|
||||||
super(id, name, 1);
|
super(id, name, 1);
|
||||||
this.maxClipCount = maxClipCount;
|
this.maxClipCount = maxClipCount;
|
||||||
|
@ -36,6 +38,7 @@ public class Gun extends Item {
|
||||||
this.reloadTime = reloadTime;
|
this.reloadTime = reloadTime;
|
||||||
this.baseDamage = baseDamage;
|
this.baseDamage = baseDamage;
|
||||||
this.recoil = recoil;
|
this.recoil = recoil;
|
||||||
|
this.automatic = automatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxClipCount() {
|
public int getMaxClipCount() {
|
||||||
|
@ -69,4 +72,8 @@ public class Gun extends Item {
|
||||||
public float getRecoil() {
|
public float getRecoil() {
|
||||||
return recoil;
|
return recoil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAutomatic() {
|
||||||
|
return automatic;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@ public class Rifle extends Gun {
|
||||||
0.8f,
|
0.8f,
|
||||||
2.5f,
|
2.5f,
|
||||||
80f,
|
80f,
|
||||||
50f
|
50f,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,6 @@ public record ClientInputState(
|
||||||
// Interaction
|
// Interaction
|
||||||
boolean hitting, // Usually a "left-click" action.
|
boolean hitting, // Usually a "left-click" action.
|
||||||
boolean interacting, // Usually a "right-click" action.
|
boolean interacting, // Usually a "right-click" action.
|
||||||
|
boolean reloading, // Usually the "R" key.
|
||||||
int selectedInventoryIndex // The selected index in the player's inventory.
|
int selectedInventoryIndex // The selected index in the player's inventory.
|
||||||
) implements Message {}
|
) implements Message {}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package nl.andrewl.aos_core.net.client;
|
||||||
|
|
||||||
|
import nl.andrewl.record_net.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message that indicates that a sound has been emitted somewhere in the
|
||||||
|
* world, and that clients may need to play the sound.
|
||||||
|
*/
|
||||||
|
public record SoundMessage(
|
||||||
|
String name,
|
||||||
|
float px, float py, float pz
|
||||||
|
) implements Message {}
|
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,79 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||||
|
sodipodi:docname="bullet.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.49497475"
|
||||||
|
inkscape:cx="1025.0529"
|
||||||
|
inkscape:cy="684.95586"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1049"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
id="g827"
|
||||||
|
transform="translate(7.4821434,33.262203)"
|
||||||
|
inkscape:export-xdpi="20.76"
|
||||||
|
inkscape:export-ydpi="20.76">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path821"
|
||||||
|
d="m 60.476187,95.538688 c 0,-54.617567 37.041667,-82.587796 37.041667,-82.587796 0,0 37.041666,27.970235 37.041666,82.587796"
|
||||||
|
style="fill:#c48916;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<rect
|
||||||
|
ry="2.6458333"
|
||||||
|
rx="2.6458333"
|
||||||
|
y="95.538689"
|
||||||
|
x="60.476189"
|
||||||
|
height="119.86935"
|
||||||
|
width="74.083336"
|
||||||
|
id="rect815"
|
||||||
|
style="fill:#383736;fill-opacity:1;stroke:#7c7c7c;stroke-width:4.23333311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,135 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||||
|
sodipodi:docname="clip.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.49497475"
|
||||||
|
inkscape:cx="379.84557"
|
||||||
|
inkscape:cy="674.60205"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1049"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#383736;fill-opacity:1;stroke:#7c7c7c;stroke-width:8.46666622;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect867"
|
||||||
|
width="156.86011"
|
||||||
|
height="110.36904"
|
||||||
|
x="20.788689"
|
||||||
|
y="116.32738"
|
||||||
|
rx="2.6458333"
|
||||||
|
ry="2.6458333"
|
||||||
|
inkscape:export-xdpi="19.67"
|
||||||
|
inkscape:export-ydpi="19.67" />
|
||||||
|
<g
|
||||||
|
id="g873"
|
||||||
|
transform="translate(7.5595238,-2.2339507)"
|
||||||
|
inkscape:export-xdpi="19.67"
|
||||||
|
inkscape:export-ydpi="19.67">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path821"
|
||||||
|
d="m 64.335157,155.54667 c 10.862887,-10.86289 23.793101,-9.05867 23.793101,-9.05867 0,0 1.804217,12.93021 -9.058669,23.7931"
|
||||||
|
style="fill:#c48916;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<rect
|
||||||
|
transform="rotate(45)"
|
||||||
|
ry="0.74420118"
|
||||||
|
rx="0.74420118"
|
||||||
|
y="64.496277"
|
||||||
|
x="155.47993"
|
||||||
|
height="33.716"
|
||||||
|
width="20.837635"
|
||||||
|
id="rect815"
|
||||||
|
style="fill:#b63417;fill-opacity:1;stroke:#7c7c7c;stroke-width:4.23333311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g879"
|
||||||
|
transform="translate(33.450892,-2.2339507)"
|
||||||
|
inkscape:export-xdpi="19.67"
|
||||||
|
inkscape:export-ydpi="19.67">
|
||||||
|
<path
|
||||||
|
style="fill:#c48916;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 64.335157,155.54667 c 10.862887,-10.86289 23.793101,-9.05867 23.793101,-9.05867 0,0 1.804217,12.93021 -9.058669,23.7931"
|
||||||
|
id="path875"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
<rect
|
||||||
|
style="fill:#b63417;fill-opacity:1;stroke:#7c7c7c;stroke-width:4.23333311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect877"
|
||||||
|
width="20.837635"
|
||||||
|
height="33.716"
|
||||||
|
x="155.47993"
|
||||||
|
y="64.496277"
|
||||||
|
rx="0.74420118"
|
||||||
|
ry="0.74420118"
|
||||||
|
transform="rotate(45)" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(59.342262,-2.2339507)"
|
||||||
|
id="g885"
|
||||||
|
inkscape:export-xdpi="19.67"
|
||||||
|
inkscape:export-ydpi="19.67">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path881"
|
||||||
|
d="m 64.335157,155.54667 c 10.862887,-10.86289 23.793101,-9.05867 23.793101,-9.05867 0,0 1.804217,12.93021 -9.058669,23.7931"
|
||||||
|
style="fill:#c48916;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<rect
|
||||||
|
transform="rotate(45)"
|
||||||
|
ry="0.74420118"
|
||||||
|
rx="0.74420118"
|
||||||
|
y="64.496277"
|
||||||
|
x="155.47993"
|
||||||
|
height="33.716"
|
||||||
|
width="20.837635"
|
||||||
|
id="rect883"
|
||||||
|
style="fill:#b63417;fill-opacity:1;stroke:#7c7c7c;stroke-width:4.23333311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.9 KiB |
|
@ -3,12 +3,12 @@ package nl.andrewl.aos2_server.logic;
|
||||||
import nl.andrewl.aos2_server.Server;
|
import nl.andrewl.aos2_server.Server;
|
||||||
import nl.andrewl.aos2_server.ServerPlayer;
|
import nl.andrewl.aos2_server.ServerPlayer;
|
||||||
import nl.andrewl.aos2_server.config.ServerConfig;
|
import nl.andrewl.aos2_server.config.ServerConfig;
|
||||||
import nl.andrewl.aos_core.model.item.BlockItemStack;
|
import nl.andrewl.aos_core.model.item.*;
|
||||||
import nl.andrewl.aos_core.model.item.ItemTypes;
|
|
||||||
import nl.andrewl.aos_core.model.world.World;
|
import nl.andrewl.aos_core.model.world.World;
|
||||||
import nl.andrewl.aos_core.net.client.ClientInputState;
|
import nl.andrewl.aos_core.net.client.ClientInputState;
|
||||||
import nl.andrewl.aos_core.net.client.InventorySelectedStackMessage;
|
import nl.andrewl.aos_core.net.client.InventorySelectedStackMessage;
|
||||||
import nl.andrewl.aos_core.net.client.ItemStackMessage;
|
import nl.andrewl.aos_core.net.client.ItemStackMessage;
|
||||||
|
import nl.andrewl.aos_core.net.client.SoundMessage;
|
||||||
import nl.andrewl.aos_core.net.world.ChunkUpdateMessage;
|
import nl.andrewl.aos_core.net.world.ChunkUpdateMessage;
|
||||||
import org.joml.Math;
|
import org.joml.Math;
|
||||||
import org.joml.Vector2i;
|
import org.joml.Vector2i;
|
||||||
|
@ -30,6 +30,11 @@ public class PlayerActionManager {
|
||||||
private long lastBlockRemovedAt = 0;
|
private long lastBlockRemovedAt = 0;
|
||||||
private long lastBlockPlacedAt = 0;
|
private long lastBlockPlacedAt = 0;
|
||||||
|
|
||||||
|
private long gunLastShotAt = 0;
|
||||||
|
private boolean gunNeedsReCock = false;
|
||||||
|
private boolean gunReloading = false;
|
||||||
|
private long gunReloadingStartedAt = 0;
|
||||||
|
|
||||||
private boolean updated = false;
|
private boolean updated = false;
|
||||||
|
|
||||||
public PlayerActionManager(ServerPlayer player) {
|
public PlayerActionManager(ServerPlayer player) {
|
||||||
|
@ -38,7 +43,7 @@ public class PlayerActionManager {
|
||||||
player.getId(),
|
player.getId(),
|
||||||
false, false, false, false,
|
false, false, false, false,
|
||||||
false, false, false,
|
false, false, false,
|
||||||
false, false,
|
false, false, false,
|
||||||
player.getInventory().getSelectedIndex()
|
player.getInventory().getSelectedIndex()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -67,8 +72,15 @@ public class PlayerActionManager {
|
||||||
updated = true; // Tell everyone else that this player's selected item has changed.
|
updated = true; // Tell everyone else that this player's selected item has changed.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.getInventory().getSelectedItemStack().getType().equals(ItemTypes.BLOCK)) {
|
ItemStack selectedStack = player.getInventory().getSelectedItemStack();
|
||||||
tickBlockAction(now, server, world);
|
if (selectedStack instanceof BlockItemStack b) {
|
||||||
|
tickBlockAction(now, server, world, b);
|
||||||
|
} else if (selectedStack instanceof GunItemStack g) {
|
||||||
|
try {
|
||||||
|
tickGunAction(now, server, world, g);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("bleh");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.isCrouching() != lastInputState.crouching()) {
|
if (player.isCrouching() != lastInputState.crouching()) {
|
||||||
|
@ -79,8 +91,52 @@ public class PlayerActionManager {
|
||||||
tickMovement(dt, world, server.getConfig().physics);
|
tickMovement(dt, world, server.getConfig().physics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickBlockAction(long now, Server server, World world) {
|
private void tickGunAction(long now, Server server, World world, GunItemStack g) {
|
||||||
BlockItemStack stack = (BlockItemStack) player.getInventory().getSelectedItemStack();
|
Gun gun = (Gun) g.getType();
|
||||||
|
if (// Check to see if the player is shooting.
|
||||||
|
lastInputState.hitting() &&
|
||||||
|
g.getBulletCount() > 0 &&
|
||||||
|
!gunReloading &&
|
||||||
|
now - gunLastShotAt > gun.getShotCooldownTime() * 1000 &&
|
||||||
|
(gun.isAutomatic() || !gunNeedsReCock)
|
||||||
|
) {
|
||||||
|
// TODO: trace a ray from gun to see if players intersect with it.
|
||||||
|
g.setBulletCount(g.getBulletCount() - 1);
|
||||||
|
gunLastShotAt = now;
|
||||||
|
if (!gun.isAutomatic()) {
|
||||||
|
gunNeedsReCock = true;
|
||||||
|
}
|
||||||
|
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new ItemStackMessage(player.getInventory()));
|
||||||
|
server.getPlayerManager().broadcastUdpMessage(new SoundMessage("rifle", player.getPosition().x(), player.getPosition().y(), player.getPosition().z()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (// Check to see if the player is reloading.
|
||||||
|
lastInputState.reloading() &&
|
||||||
|
!gunReloading &&
|
||||||
|
g.getClipCount() > 0
|
||||||
|
) {
|
||||||
|
g.setClipCount(g.getClipCount() - 1);
|
||||||
|
gunReloadingStartedAt = now;
|
||||||
|
gunReloading = true;
|
||||||
|
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new ItemStackMessage(player.getInventory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (// Check to see if reloading is done.
|
||||||
|
gunReloading &&
|
||||||
|
now - gunReloadingStartedAt > gun.getReloadTime() * 1000
|
||||||
|
) {
|
||||||
|
g.setBulletCount(gun.getMaxBulletCount());
|
||||||
|
gunReloading = false;
|
||||||
|
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new ItemStackMessage(player.getInventory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the player released the trigger, for non-automatic weapons.
|
||||||
|
if (!gun.isAutomatic() && gunNeedsReCock && !lastInputState.hitting()) {
|
||||||
|
gunNeedsReCock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickBlockAction(long now, Server server, World world, BlockItemStack stack) {
|
||||||
// Check for breaking blocks.
|
// Check for breaking blocks.
|
||||||
if (
|
if (
|
||||||
lastInputState.hitting() &&
|
lastInputState.hitting() &&
|
||||||
|
|
Loading…
Reference in New Issue