diff --git a/core/src/ru/mclord/classic/Event.java b/core/src/ru/mclord/classic/Event.java index 24d8012..4820abd 100644 --- a/core/src/ru/mclord/classic/Event.java +++ b/core/src/ru/mclord/classic/Event.java @@ -7,11 +7,6 @@ public abstract class Event { public Event(boolean cancellable) { this.cancellable = cancellable; - - if (cancellable) { - System.out.println(getClass() + ": cancellable events " + - "support is not implemented yet. Calling setCancelled() has no effect"); - } } /* diff --git a/core/src/ru/mclord/classic/EventManager.java b/core/src/ru/mclord/classic/EventManager.java index 259bf13..2a905d6 100644 --- a/core/src/ru/mclord/classic/EventManager.java +++ b/core/src/ru/mclord/classic/EventManager.java @@ -26,6 +26,7 @@ public synchronized void registerEventHandler( eventHandlerList.add(eventHandler); } + @SuppressWarnings("unchecked") public synchronized boolean fireEvent(T event) { Objects.requireNonNull(event); @@ -39,9 +40,28 @@ public synchronized boolean fireEvent(T event) { List> handlerList = eventHandlerMap.get(eventClass); for (EventHandler eventHandler : handlerList) { - //noinspection unchecked - McLordClassic.game().addTask(() -> - ((EventHandler) eventHandler).handleEvent(event)); + Runnable task = () -> ((EventHandler) eventHandler).handleEvent(event); + if (Helper.isOnMainThread()) { + if (event.isCancellable()) { + task.run(); + } else { + McLordClassic.game().addTask(task); + } + } else { + Object lock = McLordClassic.game().addTask(() -> + ((EventHandler) eventHandler) + .handleEvent(event), event.isCancellable()); + if (event.isCancellable()) { + try { + Helper.join(lock); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + + throw new RuntimeException(e); + } + } + } + if (event.isCancellable() && event.isCancelled()) return false; } return true; diff --git a/core/src/ru/mclord/classic/Helper.java b/core/src/ru/mclord/classic/Helper.java index ca99336..70cfa42 100644 --- a/core/src/ru/mclord/classic/Helper.java +++ b/core/src/ru/mclord/classic/Helper.java @@ -35,6 +35,20 @@ public static String getStacktrace(Throwable t) { return writer0.toString(); } + public static boolean isOnMainThread() { + return Thread.currentThread() == McLordClassic.game().mainThread; + } + + @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") + public static void join(Object lock) throws InterruptedException { + synchronized (lock) { + while (!((McLordClassic.TaskContainer) lock).finished) { + System.out.println("Oops!"); + lock.wait(); + } + } + } + public static File[] listPlugins() { File pluginsDir = new File("./plugins/"); if (!pluginsDir.isDirectory()) { diff --git a/core/src/ru/mclord/classic/InGameScreen.java b/core/src/ru/mclord/classic/InGameScreen.java index 144172c..d799a80 100644 --- a/core/src/ru/mclord/classic/InGameScreen.java +++ b/core/src/ru/mclord/classic/InGameScreen.java @@ -54,13 +54,16 @@ public void show() { modelBatch = new ModelBatch(); environment = new Environment(); - EventManager.getInstance().fireEvent(CustomizeEnvironmentEvent.create(environment)); + if (!EventManager.getInstance() + .fireEvent(CustomizeEnvironmentEvent.create(environment))) { + environment = new Environment(); + } Player player = McLordClassic.getPlayer(); camera = new PerspectiveCamera( fov, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); // camera.position.set(player.spawnLocation.x, player.spawnLocation.y, player.spawnLocation.z); - camera.position.set(0f, 0f, 0f); + camera.position.set(-1.0f, -1.0f, -1.0f); camera.near = 0.35f; // todo might be not the best value camera.far = cameraFar; camera.update(); @@ -74,7 +77,7 @@ public void show() { @Override public void render(float delta) { - cameraController.update(); + cameraController.update(delta); Helper.clearDepthRGB(17, 137, 217); diff --git a/core/src/ru/mclord/classic/McLordClassic.java b/core/src/ru/mclord/classic/McLordClassic.java index d87eaff..18b0d38 100644 --- a/core/src/ru/mclord/classic/McLordClassic.java +++ b/core/src/ru/mclord/classic/McLordClassic.java @@ -11,16 +11,24 @@ import java.util.Queue; public class McLordClassic extends Game { - private static class TaskContainer { + /* package-private */ static class TaskContainer { private final Runnable task; private final Thread thread; private final StackTraceElement[] stacktrace; + private final boolean subscribed; private final long timestamp; - - public TaskContainer(Runnable task, Thread thread, StackTraceElement[] stacktrace) { + /* package-private */ volatile boolean finished; + + public TaskContainer( + Runnable task, + Thread thread, + StackTraceElement[] stacktrace, + boolean subscribed + ) { this.task = task; this.thread = thread; this.stacktrace = stacktrace; + this.subscribed = subscribed; timestamp = System.currentTimeMillis(); } @@ -47,13 +55,14 @@ public enum GameStage { public static final boolean DEBUG = true; public static final String APP_NAME = "McLordClassic"; - public static final String VERSION = "0.1.1"; + public static final String VERSION = "0.1.2"; public static final int VERSION_CODE = 2; private static final McLordClassic INSTANCE = new McLordClassic(); + /* package-private */ final Thread mainThread; private Properties gameProperties; - private final Queue taskList = new ArrayDeque<>(); + /* package-private */ final Queue taskList = new ArrayDeque<>(); /* package-private */ GameStage stage = GameStage.INTERNAL_INITIALIZATION; /* package-private */ volatile NetworkingThread networkingThread; /* package-private */ Level level; @@ -61,6 +70,8 @@ public enum GameStage { /* package-private */ String disconnectReason; private McLordClassic() { + this.mainThread = Thread.currentThread(); + if (DEBUG) GameParameters.setupDebugProperties(); GameParameters.collectAndVerify(); @@ -99,12 +110,20 @@ public static String getProperty(String key) { } public void addTask(Runnable task) { + addTask(task, false); + } + + public Object addTask(Runnable task, boolean subscribe) { Thread currentThread = Thread.currentThread(); StackTraceElement[] stacktrace = currentThread.getStackTrace(); + TaskContainer container = new TaskContainer( + task, currentThread, stacktrace, subscribe); synchronized (taskList) { - taskList.offer(new TaskContainer(task, currentThread, stacktrace)); + taskList.offer(container); } + + return (subscribe ? container : null); } @Override @@ -127,7 +146,8 @@ public void create() { } @Override - @SuppressWarnings("SynchronizeOnNonFinalField") + @SuppressWarnings({"SynchronizeOnNonFinalField", + "SynchronizationOnLocalVariableOrMethodParameter"}) public void render() { synchronized (taskList) { int size = taskList.size(); @@ -145,15 +165,23 @@ public void render() { System.err.println("Stacktrace snapshot of " + "the thread at the moment the task was enqueued:"); container.printStackTrace(); - System.err.println("Date added: " + new Date(container.timestamp)); + System.err.println("Date added: " + (new Date(container.timestamp))); System.err.println("The game will be terminated"); System.exit(-1); } + if (container.subscribed) { + System.out.println("Attempting to notify"); + synchronized (container) { + container.finished = true; + container.notifyAll(); + } + System.out.println("Notified"); + } if (task instanceof NetworkingRunnable) { synchronized (networkingThread) { networkingThread.finishedExecuting = true; - networkingThread.notify(); + networkingThread.notifyAll(); } } } diff --git a/core/src/ru/mclord/classic/McLordFirstPersonCameraController.java b/core/src/ru/mclord/classic/McLordFirstPersonCameraController.java index c227885..6c2a2d4 100644 --- a/core/src/ru/mclord/classic/McLordFirstPersonCameraController.java +++ b/core/src/ru/mclord/classic/McLordFirstPersonCameraController.java @@ -10,14 +10,17 @@ public class McLordFirstPersonCameraController extends FirstPersonCameraControll private final Vector3 tmp = new Vector3(); private final Vector3 tmp2 = new Vector3(); private final Vector3 tmp3 = new Vector3(); - private final Vector3 lastCameraPosition; + private final boolean xRay; + private final Block[] blocks = new Block[8]; public McLordFirstPersonCameraController(Camera camera) { super(camera); + xRay = Boolean.parseBoolean(McLordClassic.getProperty("xRay")); + setDegreesPerPixel(0.08f); setVelocity(15.0f); - lastCameraPosition = new Vector3(camera.position); + autoUpdate = false; } @Override @@ -29,37 +32,55 @@ public boolean mouseMoved(int screenX, int screenY) { @Override public void update(float deltaTime) { - if (!(camera.position.x == lastCameraPosition.x && camera.position.y == lastCameraPosition.y && camera.position.z == lastCameraPosition.z)) { - int x = (int) camera.position.x; - int y = (int) camera.position.y; - int z = (int) camera.position.z; - - if (false) { - //camera is in the block - - camera.position.x = lastCameraPosition.x; - camera.position.y = lastCameraPosition.y; - camera.position.z = lastCameraPosition.z; - - return; - } - - lastCameraPosition.x = camera.position.x; - lastCameraPosition.y = camera.position.y; - lastCameraPosition.z = camera.position.z; - } + Vector3 initialCameraPosition = new Vector3(camera.position); if (Gdx.input.isKeyPressed(Input.Keys.SPACE) && !Gdx.input.isKeyPressed(Input.Keys.Q)) { tmp.set(camera.up).nor().scl(deltaTime * velocity); camera.position.add(tmp); } - if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) && !Gdx.input.isKeyPressed(Input.Keys.E)) { tmp.set(camera.up).nor().scl(-deltaTime * velocity); camera.position.add(tmp); } - super.update(deltaTime); + + fixCords(initialCameraPosition); + + camera.update(true); + } + + private void fixCords(Vector3 initialCameraPosition) { + if (xRay) return; + + // too bad, fixme at some point + int x = (int) (camera.position.x); + int y = (int) (camera.position.y); + int z = (int) (camera.position.z); + int x1 = (int) Math.ceil(camera.position.x); + int y1 = (int) Math.ceil(camera.position.y); + int z1 = (int) Math.ceil(camera.position.z); + + Level level = McLordClassic.game().level; + blocks[0] = level.getBlockDefAt(x, y, z); + blocks[1] = level.getBlockDefAt(x1, y1, z1); + blocks[2] = level.getBlockDefAt(x1, y, z); + blocks[3] = level.getBlockDefAt(x1, y1, z); + blocks[4] = level.getBlockDefAt(x, y1, z); + blocks[5] = level.getBlockDefAt(x, y1, z1); + blocks[6] = level.getBlockDefAt(x, y, z1); + blocks[7] = level.getBlockDefAt(x1, y, z1); + + if (checkInvalid()) { + camera.position.set(initialCameraPosition); + } + } + + private boolean checkInvalid() { + for (Block block : blocks) { + if (block.solidity == Block.Solidity.SOLID) return true; + } + + return false; } // thanks to https://github.com/libgdx/libgdx/issues/4023#issuecomment-211675619 diff --git a/core/src/ru/mclord/classic/TextureManager.java b/core/src/ru/mclord/classic/TextureManager.java index 8bfa73b..69fd64d 100644 --- a/core/src/ru/mclord/classic/TextureManager.java +++ b/core/src/ru/mclord/classic/TextureManager.java @@ -68,11 +68,11 @@ public void load(String path, boolean allowNet, boolean allowFileSystem) { } */ Pixmap emptyPixmap = new Pixmap(TEXTURE_SIZE, TEXTURE_SIZE, Pixmap.Format.RGBA8888); - for (int i = 0; i < TEXTURE_SIZE; i++) { - for (int j = 0; j < TEXTURE_SIZE; j++) { - emptyPixmap.drawPixel(i, j, 0x00000001); - } - } + //for (int i = 0; i < TEXTURE_SIZE; i++) { + // for (int j = 0; j < TEXTURE_SIZE; j++) { + //emptyPixmap.drawPixel(i, j, 0xFF000009); + // } + //} emptyTexture = new Texture(emptyPixmap); temporaryPixmaps[temporaryPixmaps.length - 1] = emptyPixmap; for (int i = 0; i < TEXTURE_COUNT; i++) { diff --git a/core/src/ru/mclord/classic/events/CustomizeEnvironmentEvent.java b/core/src/ru/mclord/classic/events/CustomizeEnvironmentEvent.java index 2f5737b..50f7740 100644 --- a/core/src/ru/mclord/classic/events/CustomizeEnvironmentEvent.java +++ b/core/src/ru/mclord/classic/events/CustomizeEnvironmentEvent.java @@ -7,7 +7,7 @@ public class CustomizeEnvironmentEvent extends Event { private final Environment environment; private CustomizeEnvironmentEvent(Environment environment) { - super(false); + super(true); this.environment = environment; } diff --git a/desktop/src/ru/mclord/classic/DesktopLauncher.java b/desktop/src/ru/mclord/classic/DesktopLauncher.java index 78eedfd..ec5da1a 100644 --- a/desktop/src/ru/mclord/classic/DesktopLauncher.java +++ b/desktop/src/ru/mclord/classic/DesktopLauncher.java @@ -22,6 +22,7 @@ public static void main(String[] arg) throws IOException { props.setProperty("texturePack", TextureManager.DEFAULT_TEXTURE_PACK); props.setProperty("fov", "90.0"); props.setProperty("cameraFar", "300.0"); + props.setProperty("xRay", "true"); File propertiesFile = new File("game.properties"); if (propertiesFile.exists()) {