snakeia-server 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.drone.yml +1 -1
- package/GameEngineMultithreading.js +18 -14
- package/GameEngineMultithreadingController.js +104 -92
- package/README.md +12 -6
- package/config/default.json +1 -1
- package/package.json +1 -1
package/.drone.yml
CHANGED
|
@@ -115,7 +115,7 @@ if(!isMainThread) {
|
|
|
115
115
|
if(!game) {
|
|
116
116
|
try {
|
|
117
117
|
game = new GameEngine(grid, snakes, data.speed, data.enablePause, data.enableRetry, data.progressiveSpeed, data.aiStuckLimit, data.disableStuckAIDetection, data.aiUltraModelSettings);
|
|
118
|
-
await
|
|
118
|
+
await initGame();
|
|
119
119
|
} catch(e) {
|
|
120
120
|
console.error(e);
|
|
121
121
|
|
|
@@ -124,18 +124,6 @@ if(!isMainThread) {
|
|
|
124
124
|
errorOccurred: true
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
|
-
|
|
128
|
-
parentPort.postMessage({
|
|
129
|
-
type: "init",
|
|
130
|
-
"snakes": copySnakes(game.snakes),
|
|
131
|
-
"grid": copyGrid(game.grid),
|
|
132
|
-
"enablePause": game.enablePause,
|
|
133
|
-
"enableRetry": game.enableRetry,
|
|
134
|
-
"progressiveSpeed": game.progressiveSpeed,
|
|
135
|
-
"offsetFrame": game.speed * GameConstants.Setting.TIME_MULTIPLIER,
|
|
136
|
-
"errorOccurred": game.errorOccurred,
|
|
137
|
-
"engineLoading": game.engineLoading
|
|
138
|
-
});
|
|
139
127
|
|
|
140
128
|
game.onReset(() => {
|
|
141
129
|
parentPort.postMessage({
|
|
@@ -318,7 +306,7 @@ if(!isMainThread) {
|
|
|
318
306
|
game.countBeforePlay = 3;
|
|
319
307
|
|
|
320
308
|
try {
|
|
321
|
-
await
|
|
309
|
+
await initGame();
|
|
322
310
|
} catch(e) {
|
|
323
311
|
console.error(e);
|
|
324
312
|
|
|
@@ -400,4 +388,20 @@ if(!isMainThread) {
|
|
|
400
388
|
}
|
|
401
389
|
}
|
|
402
390
|
});
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
async function initGame() {
|
|
394
|
+
await game.init();
|
|
395
|
+
|
|
396
|
+
parentPort.postMessage({
|
|
397
|
+
type: "init",
|
|
398
|
+
"snakes": copySnakes(game.snakes),
|
|
399
|
+
"grid": copyGrid(game.grid),
|
|
400
|
+
"enablePause": game.enablePause,
|
|
401
|
+
"enableRetry": game.enableRetry,
|
|
402
|
+
"progressiveSpeed": game.progressiveSpeed,
|
|
403
|
+
"offsetFrame": game.speed * GameConstants.Setting.TIME_MULTIPLIER,
|
|
404
|
+
"errorOccurred": game.errorOccurred,
|
|
405
|
+
"engineLoading": game.engineLoading
|
|
406
|
+
});
|
|
403
407
|
}
|
|
@@ -35,101 +35,24 @@ class GameEngineMultithreadingController extends GameEngine {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
async init() {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const type = data.type;
|
|
42
|
-
const dataKeys = Object.keys(data);
|
|
43
|
-
|
|
44
|
-
if(dataKeys.length > 1) {
|
|
45
|
-
let grid = this.grid;
|
|
46
|
-
let snakes = this.snakes;
|
|
47
|
-
|
|
48
|
-
if(data.grid) {
|
|
49
|
-
grid = Object.assign(new Grid(), data.grid);
|
|
50
|
-
data.grid = grid;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if(data.snakes) {
|
|
54
|
-
for(let i = 0; i < data.snakes.length; i++) {
|
|
55
|
-
data.snakes[i].grid = grid;
|
|
56
|
-
data.snakes[i] = Object.assign(new Snake(), data.snakes[i]);
|
|
57
|
-
|
|
58
|
-
for(let j = 0; j < data.snakes[i].queue.length; j++) {
|
|
59
|
-
data.snakes[i].queue[j] = Object.assign(new Position(), data.snakes[i].queue[j]);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
snakes = data.snakes;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
this.snakes = snakes;
|
|
67
|
-
this.grid = grid;
|
|
68
|
-
|
|
69
|
-
for(let i = 0; i < dataKeys.length; i++) {
|
|
70
|
-
if(dataKeys[i] != "snakes" && dataKeys[i] != "grid") {
|
|
71
|
-
this[dataKeys[i]] = data[dataKeys[i]];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
38
|
+
if(!this.eventsInit) {
|
|
39
|
+
this.initEventHandlers();
|
|
40
|
+
}
|
|
75
41
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
resolve();
|
|
81
|
-
break;
|
|
82
|
-
case "reset":
|
|
83
|
-
this.reactor.dispatchEvent("onReset");
|
|
84
|
-
break;
|
|
85
|
-
case "start":
|
|
86
|
-
this.reactor.dispatchEvent("onStart");
|
|
87
|
-
break;
|
|
88
|
-
case "pause":
|
|
89
|
-
this.reactor.dispatchEvent("onPause");
|
|
90
|
-
break;
|
|
91
|
-
case "continue":
|
|
92
|
-
this.reactor.dispatchEvent("onContinue");
|
|
93
|
-
break;
|
|
94
|
-
case "stop":
|
|
95
|
-
this.reactor.dispatchEvent("onStop");
|
|
96
|
-
break;
|
|
97
|
-
case "exit":
|
|
98
|
-
this.reactor.dispatchEvent("onExit");
|
|
99
|
-
break;
|
|
100
|
-
case "kill":
|
|
101
|
-
this.reactor.dispatchEvent("onKill");
|
|
102
|
-
break;
|
|
103
|
-
case "scoreIncreased":
|
|
104
|
-
this.reactor.dispatchEvent("onScoreIncreased");
|
|
105
|
-
break;
|
|
106
|
-
case "update":
|
|
107
|
-
this.reactor.dispatchEvent("onUpdate");
|
|
108
|
-
break;
|
|
109
|
-
case "updateCounter":
|
|
110
|
-
this.reactor.dispatchEvent("onUpdateCounter");
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
this.worker.on("error", (error) => {
|
|
116
|
-
if(logger) logger.error("Error in GameEngineMultithreading", error);
|
|
117
|
-
this.errorOccurred = true;
|
|
118
|
-
this.reactor.dispatchEvent("onStop");
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
this.worker.on("exit", () => {
|
|
122
|
-
this.gameFinished = true;
|
|
123
|
-
this.reactor.dispatchEvent("onStop");
|
|
124
|
-
});
|
|
42
|
+
if(this.grid) {
|
|
43
|
+
this.grid.rngGrid = null;
|
|
44
|
+
this.grid.rngGame = null;
|
|
45
|
+
}
|
|
125
46
|
|
|
126
|
-
|
|
127
|
-
|
|
47
|
+
return new Promise(resolve => {
|
|
48
|
+
const handleMessage = (data) => {
|
|
49
|
+
if(data.type === "init") {
|
|
50
|
+
this.worker.off("message", handleMessage);
|
|
51
|
+
resolve();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
128
54
|
|
|
129
|
-
|
|
130
|
-
this.grid.rngGrid = null;
|
|
131
|
-
this.grid.rngGame = null;
|
|
132
|
-
}
|
|
55
|
+
this.worker.on("message", handleMessage);
|
|
133
56
|
|
|
134
57
|
this.worker.postMessage({
|
|
135
58
|
type: "init",
|
|
@@ -146,6 +69,95 @@ class GameEngineMultithreadingController extends GameEngine {
|
|
|
146
69
|
});
|
|
147
70
|
}
|
|
148
71
|
|
|
72
|
+
initEventHandlers() {
|
|
73
|
+
this.worker.on("message", data => {
|
|
74
|
+
const type = data.type;
|
|
75
|
+
const dataKeys = Object.keys(data);
|
|
76
|
+
|
|
77
|
+
if (dataKeys.length > 1) {
|
|
78
|
+
let grid = this.grid;
|
|
79
|
+
let snakes = this.snakes;
|
|
80
|
+
|
|
81
|
+
if (data.grid) {
|
|
82
|
+
grid = Object.assign(new Grid(), data.grid);
|
|
83
|
+
data.grid = grid;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (data.snakes) {
|
|
87
|
+
for (let i = 0; i < data.snakes.length; i++) {
|
|
88
|
+
data.snakes[i].grid = grid;
|
|
89
|
+
data.snakes[i] = Object.assign(new Snake(), data.snakes[i]);
|
|
90
|
+
|
|
91
|
+
for (let j = 0; j < data.snakes[i].queue.length; j++) {
|
|
92
|
+
data.snakes[i].queue[j] = Object.assign(new Position(), data.snakes[i].queue[j]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
snakes = data.snakes;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.snakes = snakes;
|
|
100
|
+
this.grid = grid;
|
|
101
|
+
|
|
102
|
+
for (let i = 0; i < dataKeys.length; i++) {
|
|
103
|
+
if (dataKeys[i] != "snakes" && dataKeys[i] != "grid") {
|
|
104
|
+
this[dataKeys[i]] = data[dataKeys[i]];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
switch (type) {
|
|
110
|
+
case "init":
|
|
111
|
+
this.workerReady = true;
|
|
112
|
+
this.passQueuedMessages();
|
|
113
|
+
break;
|
|
114
|
+
case "reset":
|
|
115
|
+
this.reactor.dispatchEvent("onReset");
|
|
116
|
+
break;
|
|
117
|
+
case "start":
|
|
118
|
+
this.reactor.dispatchEvent("onStart");
|
|
119
|
+
break;
|
|
120
|
+
case "pause":
|
|
121
|
+
this.reactor.dispatchEvent("onPause");
|
|
122
|
+
break;
|
|
123
|
+
case "continue":
|
|
124
|
+
this.reactor.dispatchEvent("onContinue");
|
|
125
|
+
break;
|
|
126
|
+
case "stop":
|
|
127
|
+
this.reactor.dispatchEvent("onStop");
|
|
128
|
+
break;
|
|
129
|
+
case "exit":
|
|
130
|
+
this.reactor.dispatchEvent("onExit");
|
|
131
|
+
break;
|
|
132
|
+
case "kill":
|
|
133
|
+
this.reactor.dispatchEvent("onKill");
|
|
134
|
+
break;
|
|
135
|
+
case "scoreIncreased":
|
|
136
|
+
this.reactor.dispatchEvent("onScoreIncreased");
|
|
137
|
+
break;
|
|
138
|
+
case "update":
|
|
139
|
+
this.reactor.dispatchEvent("onUpdate");
|
|
140
|
+
break;
|
|
141
|
+
case "updateCounter":
|
|
142
|
+
this.reactor.dispatchEvent("onUpdateCounter");
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
this.worker.on("error", (error) => {
|
|
148
|
+
if (logger) logger.error("Error in GameEngineMultithreading", error);
|
|
149
|
+
this.errorOccurred = true;
|
|
150
|
+
this.reactor.dispatchEvent("onStop");
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
this.worker.on("exit", () => {
|
|
154
|
+
this.gameFinished = true;
|
|
155
|
+
this.reactor.dispatchEvent("onStop");
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
this.eventsInit = true;
|
|
159
|
+
}
|
|
160
|
+
|
|
149
161
|
reset() {
|
|
150
162
|
this.passMessage({ type: "reset" });
|
|
151
163
|
}
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A server for my [SnakeIA](https://github.com/Eliastik/snakeia) game, written in
|
|
|
8
8
|
|
|
9
9
|
## About this server
|
|
10
10
|
|
|
11
|
-
* Version 1.2.
|
|
11
|
+
* Version 1.2.1 (10/7/2025)
|
|
12
12
|
* Made in France by Eliastik - [eliastiksofts.com](http://eliastiksofts.com) - Contact : [eliastiksofts.com/contact](http://eliastiksofts.com/contact)
|
|
13
13
|
* License: GNU GPLv3 (see LICENCE.txt file)
|
|
14
14
|
|
|
@@ -74,7 +74,7 @@ You can create another configuration file in the **config** directory named **lo
|
|
|
74
74
|
````
|
|
75
75
|
{
|
|
76
76
|
"ServerConfig": {
|
|
77
|
-
"version": "1.2.
|
|
77
|
+
"version": "1.2.1", // The server version
|
|
78
78
|
"port": 3000, // The port where the server runs
|
|
79
79
|
"proxyMode": false, // Sets this value to true if your server is behind a proxy - defaults to false
|
|
80
80
|
"numberOfProxies": 1, // Sets the number of reverse proxies in front of the server. Default to 1. See: https://expressjs.com/en/guide/behind-proxies.html / https://express-rate-limit.mintlify.app/guides/troubleshooting-proxy-issues
|
|
@@ -88,7 +88,7 @@ You can create another configuration file in the **config** directory named **lo
|
|
|
88
88
|
"enableAI": false, // Disable or enable AIs
|
|
89
89
|
"aiUltraAPIURL": "https://www.eliastiksofts.com/snakeia/models/", // URL to the API listing the Ultra AI models. The game engine will use this API to load the default model
|
|
90
90
|
"aiUltraModelID": null, // ID of the model (as returned by the API at the URL above) to load for the Ultra AI. Can be left empty; in that case, the default model provided by the API will be loaded
|
|
91
|
-
"aiUltraCustomModelURL": null, // A URL pointing to a custom AI model to load. Must be a TensorFlow.js model trained for the Ultra AI. If there's an issue, game initialization will fail when Ultra AIs are present in the
|
|
91
|
+
"aiUltraCustomModelURL": null, // A URL pointing to a custom AI model to load. Must be a TensorFlow.js model trained for the Ultra AI. If there's an issue, game initialization will fail when Ultra AIs are present in the game
|
|
92
92
|
"playerWaitTime": 45000, // The time while waiting for players to join a room (ms)
|
|
93
93
|
"enableMaxTimeGame": true, // Enable time limit for each game
|
|
94
94
|
"maxTimeGame": 300000, // The time limit for each game (ms)
|
|
@@ -123,7 +123,10 @@ You can create another configuration file in the **config** directory named **lo
|
|
|
123
123
|
|
|
124
124
|
## Changelog
|
|
125
125
|
|
|
126
|
-
* Version 1.2.
|
|
126
|
+
* Version 1.2.1 (10/7/2025):
|
|
127
|
+
- Fixed a bug where the game could get stuck on the "Loading..." screen when restarting.
|
|
128
|
+
|
|
129
|
+
* Version 1.2.0 (10/5/2025):
|
|
127
130
|
- Adaptation to version 3.0.0 of SnakeIA and implementation of Ultra AI
|
|
128
131
|
- Bug fixes
|
|
129
132
|
- Updated dependencies
|
|
@@ -203,7 +206,7 @@ Un serveur pour mon jeu [SnakeIA](https://github.com/Eliastik/snakeia), écrit e
|
|
|
203
206
|
|
|
204
207
|
## À propos de ce serveur
|
|
205
208
|
|
|
206
|
-
* Version 1.2.
|
|
209
|
+
* Version 1.2.1 (07/10/2025)
|
|
207
210
|
* Made in France by Eliastik - [eliastiksofts.com](http://eliastiksofts.com) - Contact : [eliastiksofts.com/contact](http://eliastiksofts.com/contact)
|
|
208
211
|
* Licence : GNU GPLv3 (voir le fichier LICENCE.txt)
|
|
209
212
|
|
|
@@ -269,7 +272,7 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
|
|
|
269
272
|
````
|
|
270
273
|
{
|
|
271
274
|
"ServerConfig": {
|
|
272
|
-
"version": "1.2.
|
|
275
|
+
"version": "1.2.1", // La version du serveur
|
|
273
276
|
"port": 3000, // Le port sur lequel lancer le server
|
|
274
277
|
"proxyMode": false, // Mettez à true si votre serveur est derrière un proxy - par défaut false
|
|
275
278
|
"numberOfProxies": 1, // Configure le nombre de proxies devant votre serveur. Par défaut 1. Voir : https://expressjs.com/en/guide/behind-proxies.html / https://express-rate-limit.mintlify.app/guides/troubleshooting-proxy-issues
|
|
@@ -318,6 +321,9 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
|
|
|
318
321
|
|
|
319
322
|
## Journal des changements
|
|
320
323
|
|
|
324
|
+
* Version 1.2.1 (07/10/2025):
|
|
325
|
+
- Correction d'un bug où le jeu restait bloqué sur le message "Chargement..." lorsque la partie était recommencée
|
|
326
|
+
|
|
321
327
|
* Version 1.2.0 (05/10/2025) :
|
|
322
328
|
- Adaptation à la version 3.0.0 de SnakeIA et à la mise en place de l'IA Ultra
|
|
323
329
|
- Correction de bugs
|
package/config/default.json
CHANGED