mirror of
https://github.com/d07RiV/diabloweb.git
synced 2026-07-03 11:51:35 +00:00
multiplayer fixes and touch ui
This commit is contained in:
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "diabloweb",
|
"name": "diabloweb",
|
||||||
"version": "1.0.28",
|
"version": "1.0.29",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "diabloweb",
|
"name": "diabloweb",
|
||||||
"version": "1.0.28",
|
"version": "1.0.29",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "7.4.3",
|
"@babel/core": "7.4.3",
|
||||||
|
|||||||
68
src/App.js
68
src/App.js
@@ -68,6 +68,25 @@ const TOUCH_MOVE = 0;
|
|||||||
const TOUCH_RMB = 1;
|
const TOUCH_RMB = 1;
|
||||||
const TOUCH_SHIFT = 2;
|
const TOUCH_SHIFT = 2;
|
||||||
|
|
||||||
|
function findKeyboardRule() {
|
||||||
|
for (let sheet of document.styleSheets) {
|
||||||
|
for (let rule of sheet.cssRules) {
|
||||||
|
if (rule.type === CSSRule.MEDIA_RULE && rule.conditionText === '(min-aspect-ratio: 3/1)') {
|
||||||
|
for (let sub of rule.cssRules) {
|
||||||
|
if (sub.selectorText === '.App.keyboard .Body .inner') {
|
||||||
|
return sub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let keyboardRule = null;
|
||||||
|
try {
|
||||||
|
keyboardRule = findKeyboardRule();
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
const Link = ({children, ...props}) => <a target="_blank" rel="noopener noreferrer" {...props}>{children}</a>;
|
const Link = ({children, ...props}) => <a target="_blank" rel="noopener noreferrer" {...props}>{children}</a>;
|
||||||
|
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
@@ -80,6 +99,7 @@ class App extends React.Component {
|
|||||||
touchCtx = [null, null, null, null, null, null];
|
touchCtx = [null, null, null, null, null, null];
|
||||||
touchMods = [false, false, false, false, false, false];
|
touchMods = [false, false, false, false, false, false];
|
||||||
touchBelt = [-1, -1, -1, -1, -1, -1];
|
touchBelt = [-1, -1, -1, -1, -1, -1];
|
||||||
|
maxKeyboard = 0;
|
||||||
|
|
||||||
fs = create_fs(true);
|
fs = create_fs(true);
|
||||||
|
|
||||||
@@ -144,14 +164,19 @@ class App extends React.Component {
|
|||||||
width: `${(100 * (rect[2] - rect[0] + 20) / 640).toFixed(2)}%`,
|
width: `${(100 * (rect[2] - rect[0] + 20) / 640).toFixed(2)}%`,
|
||||||
height: `${(100 * (rect[3] - rect[1] + 20) / 640).toFixed(2)}%`,
|
height: `${(100 * (rect[3] - rect[1] + 20) / 640).toFixed(2)}%`,
|
||||||
};
|
};
|
||||||
|
this.maxKeyboard = rect[4];
|
||||||
this.element.classList.add("keyboard");
|
this.element.classList.add("keyboard");
|
||||||
Object.assign(this.keyboard.style, this.showKeyboard);
|
Object.assign(this.keyboard.style, this.showKeyboard);
|
||||||
this.keyboard.focus();
|
this.keyboard.focus();
|
||||||
|
if (keyboardRule) {
|
||||||
|
keyboardRule.style.transform = `translate(-50%, ${(-(rect[1] + rect[3]) * 56.25 / 960).toFixed(2)}vw)`;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.showKeyboard = false;
|
this.showKeyboard = false;
|
||||||
this.element.classList.remove("keyboard");
|
this.element.classList.remove("keyboard");
|
||||||
this.keyboard.blur();
|
this.keyboard.blur();
|
||||||
this.keyboard.value = "";
|
this.keyboard.value = "";
|
||||||
|
this.keyboardNum = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,22 +361,26 @@ class App extends React.Component {
|
|||||||
onMouseUp = e => {
|
onMouseUp = e => {
|
||||||
if (!this.canvas) return;
|
if (!this.canvas) return;
|
||||||
if (e.target === this.keyboard) {
|
if (e.target === this.keyboard) {
|
||||||
return;
|
//return;
|
||||||
}
|
}
|
||||||
const {x, y} = this.mousePos(e);
|
const {x, y} = this.mousePos(e);
|
||||||
this.game("DApi_Mouse", 2, this.mouseButton(e), this.eventMods(e), x, y);
|
this.game("DApi_Mouse", 2, this.mouseButton(e), this.eventMods(e), x, y);
|
||||||
|
if (e.target !== this.keyboard) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onKeyDown = e => {
|
onKeyDown = e => {
|
||||||
if (!this.canvas) return;
|
if (!this.canvas) return;
|
||||||
this.game("DApi_Key", 0, this.eventMods(e), e.keyCode);
|
this.game("DApi_Key", 0, this.eventMods(e), e.keyCode);
|
||||||
if (e.keyCode >= 32 && e.key.length === 1 && !this.showKeyboard) {
|
if (!this.showKeyboard && (e.keyCode >= 32 && e.key.length === 1)) {
|
||||||
this.game("DApi_Char", e.key.charCodeAt(0));
|
this.game("DApi_Char", e.key.charCodeAt(0));
|
||||||
|
} else if (e.keyCode === 8 || e.keyCode === 13) {
|
||||||
|
this.game("DApi_Char", e.keyCode);
|
||||||
}
|
}
|
||||||
this.clearKeySel();
|
this.clearKeySel();
|
||||||
if (!this.showKeyboard) {
|
if (!this.showKeyboard) {
|
||||||
if (e.keyCode === 8 || (e.keyCode >= 112 && e.keyCode <= 119)) {
|
if (e.keyCode === 8 || e.keyCode === 9 || (e.keyCode >= 112 && e.keyCode <= 119)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -374,18 +403,32 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyboard = () => {
|
onKeyboardInner(flags) {
|
||||||
if (this.showKeyboard) {
|
if (this.showKeyboard) {
|
||||||
const text = this.keyboard.value;
|
const text = this.keyboard.value;
|
||||||
const valid = (text.match(/[\x20-\x7E]/g) || []).join("").substring(0, 15);
|
let valid;
|
||||||
|
if (this.maxKeyboard > 0) {
|
||||||
|
valid = (text.match(/[\x20-\x7E]/g) || []).join("").substring(0, this.maxKeyboard);
|
||||||
|
} else {
|
||||||
|
const maxValue = -this.maxKeyboard;
|
||||||
|
if (text.match(/^\d*$/)) {
|
||||||
|
this.keyboardNum = Math.min(text.length ? parseInt(text) : 0, maxValue);
|
||||||
|
}
|
||||||
|
valid = (this.keyboardNum ? this.keyboardNum.toString() : "");
|
||||||
|
}
|
||||||
if (text !== valid) {
|
if (text !== valid) {
|
||||||
this.keyboard.value = valid;
|
this.keyboard.value = valid;
|
||||||
}
|
}
|
||||||
this.clearKeySel();
|
this.clearKeySel();
|
||||||
const values = [...Array(15)].map((_, i) => i < valid.length ? valid.charCodeAt(i) : 0);
|
this.game("text", valid, flags);
|
||||||
this.game("DApi_SyncText", ...values);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onKeyboard = () => {
|
||||||
|
this.onKeyboardInner(0);
|
||||||
|
}
|
||||||
|
onKeyboardBlur = () => {
|
||||||
|
this.onKeyboardInner(1);
|
||||||
|
}
|
||||||
|
|
||||||
parseFile = e => {
|
parseFile = e => {
|
||||||
const files = e.target.files;
|
const files = e.target.files;
|
||||||
@@ -495,6 +538,8 @@ class App extends React.Component {
|
|||||||
if (!this.canvas) return;
|
if (!this.canvas) return;
|
||||||
if (e.target === this.keyboard) {
|
if (e.target === this.keyboard) {
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
this.keyboard.blur();
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.updateTouchButton(e.touches, false)) {
|
if (this.updateTouchButton(e.touches, false)) {
|
||||||
@@ -519,9 +564,10 @@ class App extends React.Component {
|
|||||||
onTouchEnd = e => {
|
onTouchEnd = e => {
|
||||||
if (!this.canvas) return;
|
if (!this.canvas) return;
|
||||||
if (e.target === this.keyboard) {
|
if (e.target === this.keyboard) {
|
||||||
return;
|
//return;
|
||||||
}
|
} else {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
}
|
||||||
const prevTc = this.touchCanvas;
|
const prevTc = this.touchCanvas;
|
||||||
this.updateTouchButton(e.touches, true);
|
this.updateTouchButton(e.touches, true);
|
||||||
if (prevTc && !this.touchCanvas) {
|
if (prevTc && !this.touchCanvas) {
|
||||||
@@ -530,7 +576,7 @@ class App extends React.Component {
|
|||||||
this.game("DApi_Mouse", 2, 2, this.eventMods(e), x, y);
|
this.game("DApi_Mouse", 2, 2, this.eventMods(e), x, y);
|
||||||
|
|
||||||
if (this.touchMods[TOUCH_RMB] && (!this.touchButton || this.touchButton.index !== TOUCH_RMB)) {
|
if (this.touchMods[TOUCH_RMB] && (!this.touchButton || this.touchButton.index !== TOUCH_RMB)) {
|
||||||
this.setTouchButton(TOUCH_RMB, false);
|
this.setTouchMod(TOUCH_RMB, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!document.fullscreenElement) {
|
if (!document.fullscreenElement) {
|
||||||
@@ -574,7 +620,7 @@ class App extends React.Component {
|
|||||||
<div className="Body">
|
<div className="Body">
|
||||||
<div className="inner">
|
<div className="inner">
|
||||||
{!error && <canvas ref={this.setCanvas} width={640} height={480}/>}
|
{!error && <canvas ref={this.setCanvas} width={640} height={480}/>}
|
||||||
<input type="text" className="keyboard" onChange={this.onKeyboard} ref={this.setKeyboard} spellCheck={false} style={this.showKeyboard || {}}/>
|
<input type="text" className="keyboard" onChange={this.onKeyboard} onBlur={this.onKeyboardBlur} ref={this.setKeyboard} spellCheck={false} style={this.showKeyboard || {}}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="BodyV">
|
<div className="BodyV">
|
||||||
|
|||||||
@@ -268,6 +268,9 @@ body, #root, .App {
|
|||||||
&.touch .touch-ui {
|
&.touch .touch-ui {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
&.touch.keyboard .touch-ui {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media (max-aspect-ratio: 880/480) {
|
@media (max-aspect-ratio: 880/480) {
|
||||||
.App .touch-ui {
|
.App .touch-ui {
|
||||||
|
|||||||
2708
src/api/Diablo.jscc
2708
src/api/Diablo.jscc
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -4,8 +4,8 @@ import SpawnBinary from './DiabloSpawn.wasm';
|
|||||||
import SpawnModule from './DiabloSpawn.jscc';
|
import SpawnModule from './DiabloSpawn.jscc';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const DiabloSize = 1316452;
|
const DiabloSize = 1466809;
|
||||||
const SpawnSize = 1196648;
|
const SpawnSize = 1337416;
|
||||||
|
|
||||||
/* eslint-disable-next-line no-restricted-globals */
|
/* eslint-disable-next-line no-restricted-globals */
|
||||||
const worker = self;
|
const worker = self;
|
||||||
@@ -261,7 +261,19 @@ function call_api(func, ...params) {
|
|||||||
audioBatch = [];
|
audioBatch = [];
|
||||||
audioTransfer = [];
|
audioTransfer = [];
|
||||||
packetBatch = [];
|
packetBatch = [];
|
||||||
|
if (func !== "text") {
|
||||||
wasm["_" + func](...params);
|
wasm["_" + func](...params);
|
||||||
|
} else {
|
||||||
|
const ptr = wasm._DApi_SyncTextPtr();
|
||||||
|
const text = params[0];
|
||||||
|
const length = Math.min(text.length, 255);
|
||||||
|
const heap = wasm.HEAPU8;
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
heap[ptr + i] = text.charCodeAt(i);
|
||||||
|
}
|
||||||
|
heap[ptr + length] = 0;
|
||||||
|
wasm._DApi_SyncText(params[1]);
|
||||||
|
}
|
||||||
if (audioBatch.length) {
|
if (audioBatch.length) {
|
||||||
maxSoundId = maxBatchId;
|
maxSoundId = maxBatchId;
|
||||||
worker.postMessage({action: "audioBatch", batch: audioBatch}, audioTransfer);
|
worker.postMessage({action: "audioBatch", batch: audioBatch}, audioTransfer);
|
||||||
|
|||||||
@@ -102,12 +102,13 @@ const RejectionReason = {
|
|||||||
CREATE_GAME_EXISTS: 0x06,
|
CREATE_GAME_EXISTS: 0x06,
|
||||||
};
|
};
|
||||||
|
|
||||||
const server_info_packet = {
|
const server_packet = {
|
||||||
|
info: {
|
||||||
code: 0x32,
|
code: 0x32,
|
||||||
read: reader => ({version: reader.read32()}),
|
read: reader => ({version: reader.read32()}),
|
||||||
write: ({version}) => new buffer_writer(5).write8(server_info_packet.code).write32(version).result,
|
write: ({version}) => new buffer_writer(5).write8(server_packet.info.code).write32(version).result,
|
||||||
};
|
},
|
||||||
const server_game_list_packet = {
|
game_list: {
|
||||||
code: 0x21,
|
code: 0x21,
|
||||||
read: reader => {
|
read: reader => {
|
||||||
const count = reader.read8();
|
const count = reader.read8();
|
||||||
@@ -119,7 +120,7 @@ const server_game_list_packet = {
|
|||||||
},
|
},
|
||||||
write: ({games}) => {
|
write: ({games}) => {
|
||||||
const writer = new buffer_writer(games.reduce((sum, {name}) => sum + 5 + name.length, 2));
|
const writer = new buffer_writer(games.reduce((sum, {name}) => sum + 5 + name.length, 2));
|
||||||
writer.write8(server_game_list_packet.code);
|
writer.write8(server_packet.game_list.code);
|
||||||
writer.write8(games.length);
|
writer.write8(games.length);
|
||||||
for (let {code, name} of games) {
|
for (let {code, name} of games) {
|
||||||
writer.write32(code);
|
writer.write32(code);
|
||||||
@@ -127,81 +128,94 @@ const server_game_list_packet = {
|
|||||||
}
|
}
|
||||||
return writer.result;
|
return writer.result;
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
const server_join_accept_packet = {
|
join_accept: {
|
||||||
code: 0x12,
|
code: 0x12,
|
||||||
read: reader => ({cookie: reader.read32(), index: reader.read8(), seed: reader.read32(), difficulty: reader.read32()}),
|
read: reader => ({cookie: reader.read32(), index: reader.read8(), seed: reader.read32(), difficulty: reader.read32()}),
|
||||||
write: ({cookie, index, seed, difficulty}) => new buffer_writer(14).write8(server_join_accept_packet.code).write32(cookie).write8(index).write32(seed).write32(difficulty).result,
|
write: ({cookie, index, seed, difficulty}) => new buffer_writer(14).write8(server_packet.join_accept.code).write32(cookie).write8(index).write32(seed).write32(difficulty).result,
|
||||||
};
|
},
|
||||||
const server_join_reject_packet = {
|
join_reject: {
|
||||||
code: 0x15,
|
code: 0x15,
|
||||||
read: reader => ({cookie: reader.read32(), reason: reader.read8()}),
|
read: reader => ({cookie: reader.read32(), reason: reader.read8()}),
|
||||||
write: ({cookie, reason}) => new buffer_writer(6).write8(server_join_reject_packet.code).write32(cookie).write8(reason).result,
|
write: ({cookie, reason}) => new buffer_writer(6).write8(server_packet.join_reject.code).write32(cookie).write8(reason).result,
|
||||||
};
|
},
|
||||||
const server_connect_packet = {
|
connect: {
|
||||||
code: 0x13,
|
code: 0x13,
|
||||||
read: reader => ({id: reader.read8()}),
|
read: reader => ({id: reader.read8()}),
|
||||||
write: ({id}) => new buffer_writer(2).write8(server_connect_packet.code).write8(id).result,
|
write: ({id}) => new buffer_writer(2).write8(server_packet.connect.code).write8(id).result,
|
||||||
};
|
},
|
||||||
const server_disconnect_packet = {
|
disconnect: {
|
||||||
code: 0x14,
|
code: 0x14,
|
||||||
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
||||||
write: ({id, reason}) => new buffer_writer(6).write8(server_disconnect_packet.code).write8(id).write32(reason).result,
|
write: ({id, reason}) => new buffer_writer(6).write8(server_packet.disconnect.code).write8(id).write32(reason).result,
|
||||||
};
|
},
|
||||||
const server_message_packet = {
|
message: {
|
||||||
code: 0x01,
|
code: 0x01,
|
||||||
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
||||||
write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(server_message_packet.code).write8(id).rest(payload).result,
|
write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(server_packet.message.code).write8(id).rest(payload).result,
|
||||||
};
|
},
|
||||||
const server_turn_packet = {
|
turn: {
|
||||||
code: 0x02,
|
code: 0x02,
|
||||||
read: reader => ({id: reader.read8(), turn: reader.read32()}),
|
read: reader => ({id: reader.read8(), turn: reader.read32()}),
|
||||||
write: ({id, turn}) => new buffer_writer(6).write8(server_turn_packet.code).write8(id).write32(turn).result,
|
write: ({id, turn}) => new buffer_writer(6).write8(server_packet.turn.code).write8(id).write32(turn).result,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const client_info_packet = {
|
const client_packet = {
|
||||||
|
info: {
|
||||||
code: 0x31,
|
code: 0x31,
|
||||||
read: reader => ({version: reader.read32()}),
|
read: reader => ({version: reader.read32()}),
|
||||||
write: ({version}) => new buffer_writer(5).write8(client_info_packet.code).write32(version).result,
|
write: ({version}) => new buffer_writer(5).write8(client_packet.info.code).write32(version).result,
|
||||||
};
|
},
|
||||||
const client_game_list_packet = {
|
game_list: {
|
||||||
code: 0x21,
|
code: 0x21,
|
||||||
read: () => ({}),
|
read: () => ({}),
|
||||||
write: () => new buffer_writer(1).write8(client_game_list_packet.code).result,
|
write: () => new buffer_writer(1).write8(client_packet.game_list.code).result,
|
||||||
};
|
},
|
||||||
const client_create_game_packet = {
|
create_game: {
|
||||||
code: 0x22,
|
code: 0x22,
|
||||||
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str(), difficulty: reader.read32()}),
|
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str(), difficulty: reader.read32()}),
|
||||||
write: ({cookie, name, password, difficulty}) => new buffer_writer(11 + name.length + password.length)
|
write: ({cookie, name, password, difficulty}) => new buffer_writer(11 + name.length + password.length)
|
||||||
.write8(client_create_game_packet.code).write32(cookie).write_str(name).write_str(password).write32(difficulty).result,
|
.write8(client_packet.create_game.code).write32(cookie).write_str(name).write_str(password).write32(difficulty).result,
|
||||||
};
|
},
|
||||||
const client_join_game_packet = {
|
join_game: {
|
||||||
code: 0x23,
|
code: 0x23,
|
||||||
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str()}),
|
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str()}),
|
||||||
write: ({cookie, name, password}) => new buffer_writer(7 + name.length + password.length)
|
write: ({cookie, name, password}) => new buffer_writer(7 + name.length + password.length)
|
||||||
.write8(client_join_game_packet.code).write32(cookie).write_str(name).write_str(password).result,
|
.write8(client_packet.join_game.code).write32(cookie).write_str(name).write_str(password).result,
|
||||||
};
|
},
|
||||||
const client_leave_game_packet = {
|
leave_game: {
|
||||||
code: 0x24,
|
code: 0x24,
|
||||||
read: () => ({}),
|
read: () => ({}),
|
||||||
write: () => new buffer_writer(1).write8(client_leave_game_packet.code).result,
|
write: () => new buffer_writer(1).write8(client_packet.leave_game.code).result,
|
||||||
};
|
},
|
||||||
const client_drop_player_packet = {
|
drop_player: {
|
||||||
code: 0x03,
|
code: 0x03,
|
||||||
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
||||||
write: ({id, reason}) => new buffer_writer(6).write8(client_drop_player_packet.code).write8(id).write32(reason).result,
|
write: ({id, reason}) => new buffer_writer(6).write8(client_packet.drop_player.code).write8(id).write32(reason).result,
|
||||||
};
|
},
|
||||||
const client_message_packet = {
|
message: {
|
||||||
code: 0x01,
|
code: 0x01,
|
||||||
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
||||||
write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(client_message_packet.code).write8(id).rest(payload).result,
|
write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(client_packet.message.code).write8(id).rest(payload).result,
|
||||||
};
|
},
|
||||||
const client_turn_packet = {
|
turn: {
|
||||||
code: 0x02,
|
code: 0x02,
|
||||||
read: reader => ({turn: reader.read32()}),
|
read: reader => ({turn: reader.read32()}),
|
||||||
write: ({turn}) => new buffer_writer(5).write8(client_turn_packet.code).write32(turn).result,
|
write: ({turn}) => new buffer_writer(5).write8(client_packet.turn.code).write32(turn).result,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*function log_packet(data, type) {
|
||||||
|
const reader = new buffer_reader(data);
|
||||||
|
const id = reader.read8();
|
||||||
|
for (let [name, {code, read}] of Object.entries(type)) {
|
||||||
|
if (code === id && (name !== 'message' && name !== 'turn')) {
|
||||||
|
console.log(`${type === client_packet ? 'client_packet' : 'server_packet'}.${name} ${JSON.stringify(read(reader))}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
const PeerID = name => `diabloweb_${name}`;
|
const PeerID = name => `diabloweb_${name}`;
|
||||||
const MAX_PLRS = 4;
|
const MAX_PLRS = 4;
|
||||||
|
|
||||||
@@ -222,52 +236,59 @@ class webrtc_server {
|
|||||||
this.seed = Math.floor(Math.random() * Math.pow(2, 32));
|
this.seed = Math.floor(Math.random() * Math.pow(2, 32));
|
||||||
|
|
||||||
const onError = () => {
|
const onError = () => {
|
||||||
onMessage(server_join_reject_packet.write({cookie, reason: RejectionReason.CREATE_GAME_EXISTS}));
|
onMessage(server_packet.join_reject.write({cookie, reason: RejectionReason.CREATE_GAME_EXISTS}));
|
||||||
onClose();
|
onClose();
|
||||||
this.peer.off('error', onError);
|
this.peer.off('error', onError);
|
||||||
this.peer.off('open', onOpen);
|
this.peer.off('open', onOpen);
|
||||||
};
|
};
|
||||||
const onOpen = () => {
|
const onOpen = () => {
|
||||||
onMessage(server_join_accept_packet.write({cookie, index: 0, seed: this.seed, difficulty}));
|
//console.log('peer open');
|
||||||
onMessage(server_connect_packet.write({id: 0}));
|
setTimeout(() => {
|
||||||
|
onMessage(server_packet.join_accept.write({cookie, index: 0, seed: this.seed, difficulty}));
|
||||||
|
onMessage(server_packet.connect.write({id: 0}));
|
||||||
|
}, 0);
|
||||||
this.peer.off('error', onError);
|
this.peer.off('error', onError);
|
||||||
this.peer.off('open', onOpen);
|
this.peer.off('open', onOpen);
|
||||||
};
|
};
|
||||||
this.peer.on('error', onError);
|
this.peer.on('error', onError);
|
||||||
this.peer.on('open', onOpen);
|
this.peer.on('open', onOpen);
|
||||||
|
|
||||||
|
//this.peer.on('error', err => console.log('peer error:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
onConnect(conn) {
|
onConnect(conn) {
|
||||||
|
//conn.on('error', err => console.log('conn error:', err));
|
||||||
|
//console.log('conn open');
|
||||||
const peer = {conn};
|
const peer = {conn};
|
||||||
conn.on('data', packet => {
|
conn.on('data', packet => {
|
||||||
const reader = new buffer_reader(packet);
|
const reader = new buffer_reader(packet);
|
||||||
const code = reader.read8();
|
const code = reader.read8();
|
||||||
let pkt;
|
let pkt;
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case client_info_packet.code:
|
case client_packet.info.code:
|
||||||
pkt = client_info_packet.read(reader);
|
pkt = client_packet.info.read(reader);
|
||||||
peer.version = pkt.version;
|
peer.version = pkt.version;
|
||||||
break;
|
break;
|
||||||
case client_join_game_packet.code:
|
case client_packet.join_game.code:
|
||||||
pkt = client_join_game_packet.read(reader);
|
pkt = client_packet.join_game.read(reader);
|
||||||
if (peer.version !== this.version) {
|
if (peer.version !== this.version) {
|
||||||
conn.send(server_join_reject_packet.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_VERSION_MISMATCH}));
|
conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_VERSION_MISMATCH}));
|
||||||
} else if (pkt.name !== this.name) {
|
} else if (pkt.name !== this.name) {
|
||||||
conn.send(server_join_reject_packet.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND}));
|
conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND}));
|
||||||
} else if (pkt.password !== this.password) {
|
} else if (pkt.password !== this.password) {
|
||||||
conn.send(server_join_reject_packet.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_INCORRECT_PASSWORD}));
|
conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_INCORRECT_PASSWORD}));
|
||||||
} else {
|
} else {
|
||||||
let i = 1;
|
let i = 1;
|
||||||
while (i < MAX_PLRS && this.players[i]) {
|
while (i < MAX_PLRS && this.players[i]) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if (i >= MAX_PLRS) {
|
if (i >= MAX_PLRS) {
|
||||||
conn.send(server_join_reject_packet.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_FULL}));
|
conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_FULL}));
|
||||||
} else {
|
} else {
|
||||||
this.players[i] = peer;
|
this.players[i] = peer;
|
||||||
peer.id = i;
|
peer.id = i;
|
||||||
conn.send(server_join_accept_packet.write({cookie: pkt.cookie, index: i, seed: this.seed, difficulty: this.difficulty}));
|
conn.send(server_packet.join_accept.write({cookie: pkt.cookie, index: i, seed: this.seed, difficulty: this.difficulty}));
|
||||||
this.send(0xFF, server_connect_packet.write({id: i}));
|
this.send(0xFF, server_packet.connect.write({id: i}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -283,6 +304,7 @@ class webrtc_server {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
conn.on('close', () => {
|
conn.on('close', () => {
|
||||||
|
//console.log('conn close');
|
||||||
if (peer.id != null) {
|
if (peer.id != null) {
|
||||||
this.drop(peer.id, 0x40000006);
|
this.drop(peer.id, 0x40000006);
|
||||||
}
|
}
|
||||||
@@ -308,11 +330,11 @@ class webrtc_server {
|
|||||||
for (let i = 1; i < MAX_PLRS; ++i) {
|
for (let i = 1; i < MAX_PLRS; ++i) {
|
||||||
this.drop(i, 0x40000006);
|
this.drop(i, 0x40000006);
|
||||||
}
|
}
|
||||||
this.onMessage(server_disconnect_packet.write({id, reason}));
|
this.onMessage(server_packet.disconnect.write({id, reason}));
|
||||||
this.peer.destroy();
|
this.peer.destroy();
|
||||||
this.onClose();
|
this.onClose();
|
||||||
} else if (this.players[id]) {
|
} else if (this.players[id]) {
|
||||||
this.send(0xFF, server_disconnect_packet.write({id, reason}));
|
this.send(0xFF, server_packet.disconnect.write({id, reason}));
|
||||||
this.players[id].id = null;
|
this.players[id].id = null;
|
||||||
if (this.players[id].conn) {
|
if (this.players[id].conn) {
|
||||||
this.players[id].conn.close();
|
this.players[id].conn.close();
|
||||||
@@ -324,21 +346,21 @@ class webrtc_server {
|
|||||||
handle(id, code, reader) {
|
handle(id, code, reader) {
|
||||||
let pkt;
|
let pkt;
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case client_leave_game_packet.code:
|
case client_packet.leave_game.code:
|
||||||
pkt = client_leave_game_packet.read(reader);
|
pkt = client_packet.leave_game.read(reader);
|
||||||
this.drop(id, 3);
|
this.drop(id, 3);
|
||||||
break;
|
break;
|
||||||
case client_drop_player_packet.code:
|
case client_packet.drop_player.code:
|
||||||
pkt = client_drop_player_packet.read(reader);
|
pkt = client_packet.drop_player.read(reader);
|
||||||
this.drop(pkt.id, pkt.reason);
|
this.drop(pkt.id, pkt.reason);
|
||||||
break;
|
break;
|
||||||
case client_message_packet.code:
|
case client_packet.message.code:
|
||||||
pkt = client_message_packet.read(reader);
|
pkt = client_packet.message.read(reader);
|
||||||
this.send(pkt.id === 0xFF ? ~(1 << id) : (1 << pkt.id), server_message_packet.write({id, payload: pkt.payload}));
|
this.send(pkt.id === 0xFF ? ~(1 << id) : (1 << pkt.id), server_packet.message.write({id, payload: pkt.payload}));
|
||||||
break;
|
break;
|
||||||
case client_turn_packet.code:
|
case client_packet.turn.code:
|
||||||
pkt = client_turn_packet.read(reader);
|
pkt = client_packet.turn.read(reader);
|
||||||
this.send(~(1 << id), server_turn_packet.write({id, turn: pkt.turn}));
|
this.send(~(1 << id), server_packet.turn.write({id, turn: pkt.turn}));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw Error(`invalid packet ${code}`);
|
throw Error(`invalid packet ${code}`);
|
||||||
@@ -353,45 +375,54 @@ class webrtc_client {
|
|||||||
this.peer = new Peer();
|
this.peer = new Peer();
|
||||||
this.conn = this.peer.connect(PeerID(name));
|
this.conn = this.peer.connect(PeerID(name));
|
||||||
|
|
||||||
|
let needUnreg = true;
|
||||||
const unreg = () => {
|
const unreg = () => {
|
||||||
|
if (!needUnreg) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
needUnreg = false;
|
||||||
this.peer.off('error', onError);
|
this.peer.off('error', onError);
|
||||||
this.conn.off('error', onError);
|
this.conn.off('error', onError);
|
||||||
this.conn.off('open', onOpen);
|
this.conn.off('open', onOpen);
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
};
|
};
|
||||||
const onError = () => {
|
const onError = () => {
|
||||||
onMessage(server_join_reject_packet.write({cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND}));
|
onMessage(server_packet.join_reject.write({cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND}));
|
||||||
onClose();
|
onClose();
|
||||||
unreg();
|
unreg();
|
||||||
};
|
};
|
||||||
const onOpen = () => {
|
const onOpen = () => {
|
||||||
unreg();
|
this.conn.send(client_packet.info.write({version}));
|
||||||
this.conn.send(client_info_packet.write({version}));
|
this.conn.send(client_packet.join_game.write({cookie, name, password}));
|
||||||
this.conn.send(client_join_game_packet.write({cookie, name, password}));
|
|
||||||
for (let pkt of this.pending) {
|
for (let pkt of this.pending) {
|
||||||
this.conn.send(pkt);
|
this.conn.send(pkt);
|
||||||
}
|
}
|
||||||
this.pending = null;
|
this.pending = null;
|
||||||
|
this.conn.off('open', onOpen);
|
||||||
};
|
};
|
||||||
const timeout = setTimeout(onError, 5000);
|
const timeout = setTimeout(onError, 10000);
|
||||||
this.peer.on('error', onError);
|
this.peer.on('error', onError);
|
||||||
this.conn.on('error', onError);
|
this.conn.on('error', onError);
|
||||||
this.conn.on('open', onOpen);
|
this.conn.on('open', onOpen);
|
||||||
|
|
||||||
|
//this.peer.on('error', err => console.log('peer error:', err));
|
||||||
|
//this.conn.on('error', err => console.log('conn error:', err));
|
||||||
|
|
||||||
this.conn.on('data', data => {
|
this.conn.on('data', data => {
|
||||||
|
unreg();
|
||||||
const reader = new buffer_reader(data);
|
const reader = new buffer_reader(data);
|
||||||
const code = reader.read8();
|
const code = reader.read8();
|
||||||
let pkt;
|
let pkt;
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case server_join_accept_packet.code:
|
case server_packet.join_accept.code:
|
||||||
pkt = server_join_accept_packet.read(reader);
|
pkt = server_packet.join_accept.read(reader);
|
||||||
this.myplr = pkt.index;
|
this.myplr = pkt.index;
|
||||||
break;
|
break;
|
||||||
case server_join_reject_packet.code:
|
case server_packet.join_reject.code:
|
||||||
onClose();
|
onClose();
|
||||||
break;
|
break;
|
||||||
case server_disconnect_packet.code:
|
case server_packet.disconnect.code:
|
||||||
pkt = server_disconnect_packet.read(reader);
|
pkt = server_packet.disconnect.read(reader);
|
||||||
if (pkt.id === 'myplr') {
|
if (pkt.id === 'myplr') {
|
||||||
onClose();
|
onClose();
|
||||||
}
|
}
|
||||||
@@ -419,28 +450,35 @@ export default function webrtc_open(onMessage) {
|
|||||||
|
|
||||||
let version = 0;
|
let version = 0;
|
||||||
|
|
||||||
|
/*const prevMessage = onMessage;
|
||||||
|
onMessage = data => {
|
||||||
|
log_packet(data, server_packet);
|
||||||
|
prevMessage(data);
|
||||||
|
};*/
|
||||||
|
|
||||||
return {
|
return {
|
||||||
send: function(packet) {
|
send: function(packet) {
|
||||||
|
//log_packet(packet, client_packet);
|
||||||
const reader = new buffer_reader(packet);
|
const reader = new buffer_reader(packet);
|
||||||
const code = reader.read8();
|
const code = reader.read8();
|
||||||
let pkt;
|
let pkt;
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case client_info_packet.code:
|
case client_packet.info.code:
|
||||||
pkt = client_info_packet.read(reader);
|
pkt = client_packet.info.read(reader);
|
||||||
version = pkt.version;
|
version = pkt.version;
|
||||||
break;
|
break;
|
||||||
case client_create_game_packet.code:
|
case client_packet.create_game.code:
|
||||||
pkt = client_create_game_packet.read(reader);
|
pkt = client_packet.create_game.read(reader);
|
||||||
if (server || client) {
|
if (server || client) {
|
||||||
onMessage(server_join_reject_packet.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME}));
|
onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME}));
|
||||||
} else {
|
} else {
|
||||||
server = new webrtc_server(version, pkt, onMessage, () => server = null);
|
server = new webrtc_server(version, pkt, onMessage, () => server = null);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case client_join_game_packet.code:
|
case client_packet.join_game.code:
|
||||||
pkt = client_join_game_packet.read(reader);
|
pkt = client_packet.join_game.read(reader);
|
||||||
if (server || client) {
|
if (server || client) {
|
||||||
onMessage(server_join_reject_packet.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME}));
|
onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME}));
|
||||||
} else {
|
} else {
|
||||||
client = new webrtc_client(version, pkt, onMessage, () => client = null);
|
client = new webrtc_client(version, pkt, onMessage, () => client = null);
|
||||||
}
|
}
|
||||||
@@ -448,16 +486,16 @@ export default function webrtc_open(onMessage) {
|
|||||||
default:
|
default:
|
||||||
if (server) {
|
if (server) {
|
||||||
server.handle(0, code, reader);
|
server.handle(0, code, reader);
|
||||||
if (pkt === client_leave_game_packet.code) {
|
if (code === client_packet.leave_game.code) {
|
||||||
server = null;
|
server = null;
|
||||||
}
|
}
|
||||||
} else if (client) {
|
} else if (client) {
|
||||||
client.send(packet);
|
client.send(packet);
|
||||||
if (pkt === client_leave_game_packet.code) {
|
if (code === client_packet.leave_game.code) {
|
||||||
client = null;
|
client = null;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else if (code !== client_packet.leave_game.code) {
|
||||||
throw Error(`invalid packet ${code}`);
|
throw Error(`invalid packet ${code}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user