diff --git a/app/engine/engine.js b/app/engine/engine.js
index a0bea16..9da1c8b 100644
--- a/app/engine/engine.js
+++ b/app/engine/engine.js
@@ -39,6 +39,18 @@ export default class Engine {
incomingActions = [];
+ connections = [];
+
+ connectedPlayers = new Map();
+
+ ecses = {};
+
+ frame = 0;
+
+ last = Date.now();
+
+ server;
+
constructor(Server) {
const ecs = new this.constructor.Ecs();
const layerSize = {x: Math.ceil(RESOLUTION.x / 4), y: Math.ceil(RESOLUTION.y / 4)};
@@ -68,10 +80,6 @@ export default class Engine {
this.ecses = {
1: ecs,
};
- this.connections = [];
- this.connectedPlayers = new Map();
- this.frame = 0;
- this.last = Date.now();
class SilphiusServer extends Server {
accept(connection, packed) {
super.accept(connection, decode(packed));
diff --git a/app/hooks/use-packet.js b/app/hooks/use-packet.js
index e717fb4..a5ebecc 100644
--- a/app/hooks/use-packet.js
+++ b/app/hooks/use-packet.js
@@ -5,9 +5,12 @@ import ClientContext from '@/context/client.js';
export default function usePacket(type, fn, dependencies) {
const client = useContext(ClientContext);
useEffect(() => {
+ if (!client) {
+ return;
+ }
client.addPacketListener(type, fn);
return () => {
client.removePacketListener(type, fn);
};
- }, dependencies);
+ }, [client, ...dependencies]);
}
\ No newline at end of file
diff --git a/app/net/client/prediction.js b/app/net/client/prediction.js
index 0403e05..1621b98 100644
--- a/app/net/client/prediction.js
+++ b/app/net/client/prediction.js
@@ -15,21 +15,20 @@ onmessage = async (event) => {
}
socket = new WebSocket(url.href);
socket.binaryType = 'arraybuffer';
- const {promise, resolve, reject} = Promise.withResolvers();
+ const {promise, resolve} = Promise.withResolvers();
socket.addEventListener('open', resolve);
- socket.addEventListener('error', reject);
+ socket.addEventListener('error', () => {
+ postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
+ close();
+ });
await promise;
socket.removeEventListener('open', resolve);
- socket.removeEventListener('error', reject);
socket.addEventListener('message', onMessage);
socket.addEventListener('close', () => {
- postMessage(encode({type: 'ConnectionAborted'}));
- close();
- });
- socket.addEventListener('error', () => {
- postMessage(encode({type: 'ConnectionAborted'}));
+ postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
close();
});
+ postMessage(encode({type: 'ConnectionStatus', payload: 'connected'}));
connected = true;
return;
}
diff --git a/app/net/client/remote.js b/app/net/client/remote.js
index 662acc4..2010988 100644
--- a/app/net/client/remote.js
+++ b/app/net/client/remote.js
@@ -1,4 +1,5 @@
import {CLIENT_PREDICTION} from '@/constants.js';
+import {encode} from '@/packets/index.js';
import Client from './client.js';
@@ -30,12 +31,21 @@ export default class RemoteClient extends Client {
}
this.socket = new WebSocket(url.href);
this.socket.binaryType = 'arraybuffer';
- this.socket.onmessage = (event) => {
+ const onMessage = (event) => {
this.accept(event.data);
- };
- await new Promise((resolve) => {
- this.socket.onopen = resolve;
+ }
+ const {promise, resolve} = Promise.withResolvers();
+ this.socket.addEventListener('open', resolve);
+ this.socket.addEventListener('error', () => {
+ this.accept(encode({type: 'ConnectionStatus', payload: 'aborted'}));
});
+ await promise;
+ this.socket.removeEventListener('open', resolve);
+ this.socket.addEventListener('message', onMessage);
+ this.socket.addEventListener('close', () => {
+ this.accept(encode({type: 'ConnectionStatus', payload: 'aborted'}));
+ });
+ this.accept(encode({type: 'ConnectionStatus', payload: 'connected'}));
}
}
disconnect() {
diff --git a/app/net/server/worker.js b/app/net/server/worker.js
index dbf0757..d953825 100644
--- a/app/net/server/worker.js
+++ b/app/net/server/worker.js
@@ -1,4 +1,5 @@
-import Engine from '@/engine/engine.js';
+import Engine from '../../engine/engine.js';
+import {encode} from '@/packets/index.js';
import Server from './server.js';
@@ -16,4 +17,10 @@ onmessage = (event) => {
await engine.load();
engine.start();
await engine.connectPlayer(undefined);
+ postMessage(encode({type: 'ConnectionStatus', payload: 'connected'}));
})();
+
+import.meta.hot.accept('../../engine/engine.js', () => {
+ postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
+ close();
+});
diff --git a/app/packets/connection-aborted.js b/app/packets/connection-aborted.js
deleted file mode 100644
index d92794a..0000000
--- a/app/packets/connection-aborted.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Packet from '@/net/packet.js';
-
-export default class ConnectionAborted extends Packet {}
diff --git a/app/packets/connection-status.js b/app/packets/connection-status.js
new file mode 100644
index 0000000..2d4596e
--- /dev/null
+++ b/app/packets/connection-status.js
@@ -0,0 +1,3 @@
+import Packet from '@/net/packet.js';
+
+export default class ConnectionStatus extends Packet {}
diff --git a/app/react-components/ecs.jsx b/app/react-components/ecs.jsx
index 764c69d..712bb5d 100644
--- a/app/react-components/ecs.jsx
+++ b/app/react-components/ecs.jsx
@@ -1,7 +1,7 @@
import {Container} from '@pixi/react';
import {useState} from 'react';
-import {RESOLUTION} from '@/constants.js'
+import {RESOLUTION} from '@/constants.js';
import Ecs from '@/engine/ecs.js';
import usePacket from '@/hooks/use-packet.js';
@@ -25,9 +25,7 @@ export default function EcsComponent() {
else {
updatedEntities[id] = ecs.get(id);
if (updatedEntities[id].MainEntity) {
- if (!mainEntity) {
- setMainEntity(ecs.get(id));
- }
+ setMainEntity(ecs.get(id));
}
}
}
diff --git a/app/react-components/ui.jsx b/app/react-components/ui.jsx
index d781fac..fa4083a 100644
--- a/app/react-components/ui.jsx
+++ b/app/react-components/ui.jsx
@@ -1,4 +1,4 @@
-import {useContext, useEffect} from 'react';
+import {useContext, useEffect, useState} from 'react';
import addKeyListener from '@/add-key-listener.js';
import {ACTION_MAP, RESOLUTION} from '@/constants.js';
@@ -20,6 +20,21 @@ const KEY_MAP = {
export default function Ui({disconnected}) {
// Key input.
const client = useContext(ClientContext);
+ const [showDisconnected, setShowDisconnected] = useState(false);
+ useEffect(() => {
+ let handle;
+ if (disconnected) {
+ handle = setTimeout(() => {
+ setShowDisconnected(true);
+ }, 200);
+ }
+ else {
+ setShowDisconnected(false)
+ }
+ return () => {
+ clearTimeout(handle);
+ };
+ }, [disconnected]);
useEffect(() => {
return addKeyListener(document.body, ({type, payload}) => {
if (type in KEY_MAP && payload in ACTION_MAP) {
@@ -44,7 +59,7 @@ export default function Ui({disconnected}) {