Compare commits
9 Commits
0c06dd7b83
...
6f7ec2e7ac
Author | SHA1 | Date | |
---|---|---|---|
|
6f7ec2e7ac | ||
|
8eec34fd47 | ||
|
92b167237d | ||
|
db1baa5db4 | ||
|
a781b66cd1 | ||
|
663e33a300 | ||
|
0536e7b4f2 | ||
|
1492884a87 | ||
|
62a613ce80 |
|
@ -26,6 +26,9 @@ module.exports = {
|
|||
|
||||
// Base config
|
||||
extends: ['eslint:recommended'],
|
||||
rules: {
|
||||
'no-constant-condition': ['error', {checkLoops: false}],
|
||||
},
|
||||
|
||||
overrides: [
|
||||
// Tests
|
||||
|
@ -81,7 +84,7 @@ module.exports = {
|
|||
'assets/**/*.js',
|
||||
],
|
||||
rules: {
|
||||
'no-undef': false,
|
||||
'no-undef': 0,
|
||||
},
|
||||
}
|
||||
],
|
||||
|
|
9
app/context/ecs.js
Normal file
9
app/context/ecs.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import {createContext, useContext} from 'react';
|
||||
|
||||
const context = createContext();
|
||||
|
||||
export default context;
|
||||
|
||||
export function useEcs() {
|
||||
return useContext(context);
|
||||
}
|
|
@ -7,4 +7,3 @@ export default context;
|
|||
export function useMainEntity() {
|
||||
return useContext(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Arbitrary from '@/ecs/arbitrary.js';
|
||||
import Base from '@/ecs/base.js';
|
||||
import Schema from '@/ecs/schema.js';
|
||||
import gather from '@/engine/gather.js';
|
||||
import gather from '@/util/gather.js';
|
||||
|
||||
const specificationsAndOrDecorators = gather(
|
||||
import.meta.glob('./*.js', {eager: true, import: 'default'}),
|
||||
|
@ -17,7 +16,7 @@ for (const componentName in specificationsAndOrDecorators) {
|
|||
if ('function' === typeof specificationOrDecorator) {
|
||||
Components[componentName] = specificationOrDecorator(
|
||||
class Decorated extends Arbitrary {
|
||||
static name = componentName;
|
||||
static componentName = componentName;
|
||||
}
|
||||
);
|
||||
if (!Components[componentName]) {
|
||||
|
@ -26,7 +25,7 @@ for (const componentName in specificationsAndOrDecorators) {
|
|||
}
|
||||
else {
|
||||
Components[componentName] = class Component extends Arbitrary {
|
||||
static name = componentName;
|
||||
static componentName = componentName;
|
||||
static schema = new Schema({
|
||||
type: 'object',
|
||||
properties: specificationOrDecorator,
|
||||
|
|
|
@ -2,13 +2,60 @@ import Schema from '@/ecs/schema.js';
|
|||
|
||||
export default function(Component) {
|
||||
return class Inventory extends Component {
|
||||
insertMany(entities) {
|
||||
for (const [id, {slotChanged}] of entities) {
|
||||
if (slotChanged) {
|
||||
for (const slotIndex in slotChanged) {
|
||||
this.get(id).slots[slotIndex] = {
|
||||
...this.get(id).slots[slotIndex],
|
||||
...slotChanged[slotIndex],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.insertMany(entities);
|
||||
}
|
||||
markChange(entityId, key, value) {
|
||||
if ('slotChange' === key) {
|
||||
const {index, change} = value;
|
||||
return super.markChange(entityId, key, {[index]: change});
|
||||
}
|
||||
return super.markChange(entityId, key, value);
|
||||
}
|
||||
mergeDiff(original, update) {
|
||||
if (update.slotChange) {
|
||||
if (!original.slotChange) {
|
||||
original.slotChange = {};
|
||||
}
|
||||
const merged = {};
|
||||
for (const index in update.slotChange) {
|
||||
merged[index] = {
|
||||
...original.slotChange[index],
|
||||
...update.slotChange[index],
|
||||
};
|
||||
}
|
||||
return {slotChanged: merged};
|
||||
}
|
||||
return super.mergeDiff(original, update);
|
||||
}
|
||||
instanceFromSchema() {
|
||||
const Instance = super.instanceFromSchema();
|
||||
const Component = this;
|
||||
Instance.prototype.item = function (slot) {
|
||||
const {slots} = this;
|
||||
for (const {slotIndex, source} of this.slots) {
|
||||
if (slot === slotIndex) {
|
||||
return source;
|
||||
const instance = this;
|
||||
for (const index in slots) {
|
||||
const item = slots[index];
|
||||
if (slot === item.slotIndex) {
|
||||
const proxy = new Proxy(item, {
|
||||
set(target, property, value) {
|
||||
target[property] = value;
|
||||
const change = {[property]: value};
|
||||
Component.markChange(instance.entity, 'slotChange', {index, change});
|
||||
return true;
|
||||
},
|
||||
});
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,28 +1,54 @@
|
|||
import {RESOLUTION} from '@/constants.js'
|
||||
import {System} from '@/ecs/index.js';
|
||||
|
||||
const [hx, hy] = [RESOLUTION.x / 2, RESOLUTION.y / 2];
|
||||
|
||||
export default class FollowCamera extends System {
|
||||
|
||||
static queries() {
|
||||
return {
|
||||
default: ['Camera', 'Position'],
|
||||
};
|
||||
}
|
||||
|
||||
reindex(entities) {
|
||||
super.reindex(entities);
|
||||
for (const id of entities) {
|
||||
this.updateCamera(this.ecs.get(id));
|
||||
this.updateCamera(1, this.ecs.get(id));
|
||||
}
|
||||
}
|
||||
|
||||
tick() {
|
||||
for (const entity of this.ecs.changed(['Position'])) {
|
||||
this.updateCamera(entity);
|
||||
tick(elapsed) {
|
||||
for (const [, , entityId] of this.select('default')) {
|
||||
this.updateCamera(elapsed * 3, this.ecs.get(entityId));
|
||||
}
|
||||
}
|
||||
|
||||
updateCamera(entity) {
|
||||
updateCamera(portion, entity) {
|
||||
const {Camera, Position} = entity;
|
||||
if (Camera && Position) {
|
||||
const {AreaSize: {x, y}} = this.ecs.get(1);
|
||||
const [hx, hy] = [RESOLUTION.x / 2, RESOLUTION.y / 2];
|
||||
Camera.x = Math.max(hx, Math.min(Position.x, x - hx));
|
||||
Camera.y = Math.max(hy, Math.min(Position.y, y - hy));
|
||||
const [px, py] = [
|
||||
Math.max(hx, Math.min(Math.round(Position.x), x - hx)),
|
||||
Math.max(hy, Math.min(Math.round(Position.y), y - hy)),
|
||||
];
|
||||
if (Camera.x === px && Camera.y === py) {
|
||||
return;
|
||||
}
|
||||
if (Math.abs(Camera.x - px) < 0.1) {
|
||||
Camera.x = px;
|
||||
}
|
||||
if (Math.abs(Camera.y - py) < 0.1) {
|
||||
Camera.y = py;
|
||||
}
|
||||
const [dx, dy] = [
|
||||
(px - Camera.x) * portion,
|
||||
(py - Camera.y) * portion,
|
||||
];
|
||||
[Camera.x, Camera.y] = [
|
||||
Camera.x + (Math.sign(dx) * Math.max(0.1, Math.abs(dx))),
|
||||
Camera.y + (Math.sign(dy) * Math.max(0.1, Math.abs(dy))),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import gather from '@/engine/gather.js';
|
||||
import gather from '@/util/gather.js';
|
||||
|
||||
export default gather(import.meta.glob('./*.js', {eager: true, import: 'default'}));
|
||||
|
|
|
@ -83,7 +83,7 @@ export default class Base {
|
|||
}
|
||||
|
||||
markChange(entityId, key, value) {
|
||||
this.ecs.markChange(entityId, {[this.constructor.name]: {[key]: value}})
|
||||
this.ecs.markChange(entityId, {[this.constructor.componentName]: {[key]: value}})
|
||||
}
|
||||
|
||||
mergeDiff(original, update) {
|
||||
|
|
|
@ -75,7 +75,6 @@ export default class Ecs {
|
|||
},
|
||||
next: () => {
|
||||
let result = it.next();
|
||||
let satisfied = false;
|
||||
while (!result.done) {
|
||||
for (const componentName of criteria) {
|
||||
if (!(componentName in result.value[1])) {
|
||||
|
|
|
@ -114,7 +114,7 @@ export default class Engine {
|
|||
Inventory: {
|
||||
slots: [
|
||||
{
|
||||
qty: 10,
|
||||
qty: 500,
|
||||
slotIndex: 0,
|
||||
source: '/assets/potion',
|
||||
}
|
||||
|
@ -221,10 +221,11 @@ export default class Engine {
|
|||
entity,
|
||||
payload,
|
||||
] of this.incomingActions) {
|
||||
const {Ecs, Controlled, id, Inventory, Position, Ticking, Wielder} = entity;
|
||||
const {Controlled, Inventory, Ticking, Wielder} = entity;
|
||||
switch (payload.type) {
|
||||
case 'changeSlot': {
|
||||
Wielder.activeSlot = payload.value - 1;
|
||||
break;
|
||||
}
|
||||
case 'moveUp':
|
||||
case 'moveRight':
|
||||
|
@ -236,11 +237,11 @@ export default class Engine {
|
|||
case 'use': {
|
||||
if (payload.value) {
|
||||
const item = Inventory.item(Wielder.activeSlot);
|
||||
this.server.readAsset(item + '/start.js')
|
||||
this.server.readAsset(item.source + '/start.js')
|
||||
.then((response) => response.text())
|
||||
.then((code) => {
|
||||
Ticking.addTickingPromise(
|
||||
Script.tickingPromise(code, {console, wielder: entity}),
|
||||
Script.tickingPromise(code, {item, wielder: entity}),
|
||||
);
|
||||
});
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
import {expect, test} from 'vitest';
|
||||
|
||||
import gather from './gather.js';
|
||||
|
||||
test('gathers', async () => {
|
||||
const Gathered = gather(
|
||||
import.meta.glob('./test/*.js', {eager: true, import: 'default'}),
|
||||
{mapperForPath: (path) => path.replace(/\.\/test\/(.*)\.js/, '$1')},
|
||||
);
|
||||
expect(Gathered.First.key)
|
||||
.to.equal('First');
|
||||
expect(Gathered[1].id)
|
||||
.to.equal(1);
|
||||
expect(Gathered.Second.key)
|
||||
.to.equal('Second');
|
||||
expect(Gathered[2].id)
|
||||
.to.equal(2);
|
||||
});
|
|
@ -12,5 +12,6 @@ export default function usePacket(type, fn, dependencies) {
|
|||
return () => {
|
||||
client.removePacketListener(type, fn);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [client, ...dependencies]);
|
||||
}
|
|
@ -5,9 +5,6 @@ const encoder = new Encoder();
|
|||
|
||||
export default class Packet {
|
||||
|
||||
static id;
|
||||
static type;
|
||||
|
||||
static decode(view) {
|
||||
return decoder.decode(new DataView(view.buffer, view.byteOffset + 2, view.byteLength - 2));
|
||||
}
|
||||
|
@ -18,11 +15,6 @@ export default class Packet {
|
|||
return new DataView(encoder.bytes.buffer, 0, encoder.pos);
|
||||
}
|
||||
|
||||
static gathered(id, type) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
static pack(payload) {
|
||||
return payload;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import {get, set} from 'idb-keyval';
|
|||
|
||||
import {encode} from '@/packets/index.js';
|
||||
|
||||
import Engine from '../../engine/engine.js';
|
||||
import Engine from '../../engine.js';
|
||||
import Server from './server.js';
|
||||
|
||||
class WorkerServer extends Server {
|
||||
|
@ -51,8 +51,10 @@ onmessage = async (event) => {
|
|||
postMessage(encode({type: 'ConnectionStatus', payload: 'connected'}));
|
||||
})();
|
||||
|
||||
import.meta.hot.accept('../../engine/engine.js', async () => {
|
||||
await engine.disconnectPlayer(0, 0);
|
||||
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
||||
close();
|
||||
});
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept('../engine/engine.js', async () => {
|
||||
await engine.disconnectPlayer(0, 0);
|
||||
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
||||
close();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
import gather from '@/engine/gather.js';
|
||||
import gather from '@/util/gather.js';
|
||||
|
||||
const Gathered = gather(import.meta.glob('./*.js', {eager: true, import: 'default'}));
|
||||
|
||||
const typeToId = new Map(Object.entries(Gathered).map(([type], id) => [type, id]));
|
||||
const idToType = new Map(Object.entries(Gathered).map(([type], id) => [id, type]));
|
||||
|
||||
export function decode(packed) {
|
||||
const view = ArrayBuffer.isView(packed) ? packed : new DataView(packed);
|
||||
const id = view.getUint16(0, true);
|
||||
const Packet = Gathered[id];
|
||||
const type = idToType.get(view.getUint16(0, true));
|
||||
const Packet = Gathered[type];
|
||||
return {
|
||||
type: Packet.type,
|
||||
type,
|
||||
payload: Packet.decode(view),
|
||||
};
|
||||
}
|
||||
|
||||
export function encode(packet) {
|
||||
const Packet = Gathered[packet.type];
|
||||
const encoded = Packet.encode(packet.payload);
|
||||
encoded.setUint16(0, Packet.id, true);
|
||||
const encoded = Gathered[packet.type].encode(packet.payload);
|
||||
encoded.setUint16(0, typeToId.get(packet.type), true);
|
||||
return encoded;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ export default function Dom({children}) {
|
|||
return () => {
|
||||
window.removeEventListener('resize', onResize);
|
||||
}
|
||||
}, [ref.current]);
|
||||
});
|
||||
return (
|
||||
<div className={styles.dom} ref={ref}>
|
||||
{scale > 0 && (
|
||||
|
|
|
@ -2,10 +2,8 @@ import {Container} from '@pixi/react';
|
|||
import {useState} from 'react';
|
||||
|
||||
import {RESOLUTION} from '@/constants.js';
|
||||
import {useEcs} from '@/context/ecs.js';
|
||||
import {useMainEntity} from '@/context/main-entity.js';
|
||||
import Ecs from '@/ecs/ecs.js';
|
||||
import Components from '@/ecs-components/index.js';
|
||||
import Systems from '@/ecs-systems/index.js';
|
||||
import usePacket from '@/hooks/use-packet.js';
|
||||
|
||||
import Entities from './entities.jsx';
|
||||
|
@ -13,14 +11,13 @@ import TargetingGhost from './targeting-ghost.jsx';
|
|||
import TileLayer from './tile-layer.jsx';
|
||||
|
||||
export default function EcsComponent() {
|
||||
const [ecs] = useState(new Ecs({Components, Systems}));
|
||||
const [ecs] = useEcs();
|
||||
const [entities, setEntities] = useState({});
|
||||
const [mainEntity] = useMainEntity();
|
||||
usePacket('Tick', (payload) => {
|
||||
if (0 === Object.keys(payload.ecs).length) {
|
||||
return;
|
||||
}
|
||||
ecs.apply(payload.ecs);
|
||||
const updatedEntities = {...entities};
|
||||
for (const id in payload.ecs) {
|
||||
if (false === payload.ecs[id]) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import {createElement, useContext} from 'react';
|
|||
|
||||
import {RESOLUTION} from '@/constants.js';
|
||||
import ClientContext from '@/context/client.js';
|
||||
import EcsContext from '@/context/ecs.js';
|
||||
import MainEntityContext from '@/context/main-entity.js';
|
||||
|
||||
import Ecs from './ecs.jsx';
|
||||
|
@ -14,7 +15,9 @@ import styles from './pixi.module.css';
|
|||
|
||||
BaseTexture.defaultOptions.scaleMode = SCALE_MODES.NEAREST;
|
||||
|
||||
const ContextBridge = ({children, Contexts, render}) => {
|
||||
const Contexts = [ClientContext, EcsContext, MainEntityContext];
|
||||
|
||||
const ContextBridge = ({children, render}) => {
|
||||
const contexts = Contexts.map(useContext);
|
||||
return render(
|
||||
<>
|
||||
|
@ -33,7 +36,6 @@ const ContextBridge = ({children, Contexts, render}) => {
|
|||
export const Stage = ({children, ...props}) => {
|
||||
return (
|
||||
<ContextBridge
|
||||
Contexts={[ClientContext, MainEntityContext]}
|
||||
render={(children) => <PixiStage {...props}>{children}</PixiStage>}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -3,6 +3,7 @@ import {useContext, useEffect, useState} from 'react';
|
|||
import addKeyListener from '@/add-key-listener.js';
|
||||
import {RESOLUTION} from '@/constants.js';
|
||||
import ClientContext from '@/context/client.js';
|
||||
import {useEcs} from '@/context/ecs.js';
|
||||
import {useMainEntity} from '@/context/main-entity.js';
|
||||
import usePacket from '@/hooks/use-packet.js';
|
||||
|
||||
|
@ -18,6 +19,7 @@ export default function Ui({disconnected}) {
|
|||
// Key input.
|
||||
const client = useContext(ClientContext);
|
||||
const [mainEntity, setMainEntity] = useMainEntity();
|
||||
const [ecs] = useEcs();
|
||||
const [showDisconnected, setShowDisconnected] = useState(false);
|
||||
const [hotbarSlots, setHotbarSlots] = useState(Array(10).fill(0).map(() => {}));
|
||||
const [activeSlot, setActiveSlot] = useState(0);
|
||||
|
@ -136,25 +138,38 @@ export default function Ui({disconnected}) {
|
|||
if (0 === Object.keys(payload.ecs).length) {
|
||||
return;
|
||||
}
|
||||
ecs.apply(payload.ecs);
|
||||
let localMainEntity = mainEntity;
|
||||
for (const id in payload.ecs) {
|
||||
if (payload.ecs[id]?.MainEntity) {
|
||||
const update = payload.ecs[id];
|
||||
if (update?.MainEntity) {
|
||||
setMainEntity(localMainEntity = id);
|
||||
}
|
||||
if (localMainEntity === id) {
|
||||
if (payload.ecs[id].Inventory) {
|
||||
if (update.Inventory) {
|
||||
const newHotbarSlots = [...hotbarSlots];
|
||||
payload.ecs[id].Inventory.slots
|
||||
.forEach(({qty, slotIndex, source}) => {
|
||||
const {slots, slotChanged} = update.Inventory;
|
||||
if (slotChanged) {
|
||||
for (const slotIndex in slotChanged) {
|
||||
newHotbarSlots[slotIndex] = {
|
||||
image: source + '/icon.png',
|
||||
qty,
|
||||
...newHotbarSlots[slotIndex],
|
||||
...slotChanged[slotIndex],
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
if (slots) {
|
||||
slots
|
||||
.forEach(({qty, slotIndex, source}) => {
|
||||
newHotbarSlots[slotIndex] = {
|
||||
image: source + '/icon.png',
|
||||
qty,
|
||||
};
|
||||
});
|
||||
}
|
||||
setHotbarSlots(newHotbarSlots);
|
||||
}
|
||||
if (payload.ecs[id].Wielder && 'activeSlot' in payload.ecs[id].Wielder) {
|
||||
setActiveSlot(payload.ecs[id].Wielder.activeSlot);
|
||||
if (update.Wielder && 'activeSlot' in update.Wielder) {
|
||||
setActiveSlot(update.Wielder.activeSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,11 @@ import {useEffect, useState} from 'react';
|
|||
import {useOutletContext, useParams} from 'react-router-dom';
|
||||
|
||||
import ClientContext from '@/context/client.js';
|
||||
import EcsContext from '@/context/ecs.js';
|
||||
import MainEntityContext from '@/context/main-entity.js';
|
||||
|
||||
import Ecs from '@/ecs/ecs.js';
|
||||
import Components from '@/ecs-components/index.js';
|
||||
import Systems from '@/ecs-systems/index.js';
|
||||
import Ui from '@/react-components/ui.jsx';
|
||||
import {juggleSession} from '@/session.server';
|
||||
|
||||
|
@ -17,6 +20,7 @@ export default function PlaySpecific() {
|
|||
const Client = useOutletContext();
|
||||
const [client, setClient] = useState();
|
||||
const mainEntityTuple = useState();
|
||||
const ecsTuple = useState(new Ecs({Components, Systems}));
|
||||
const [disconnected, setDisconnected] = useState(false);
|
||||
const params = useParams();
|
||||
const [type, url] = params['*'].split('/');
|
||||
|
@ -39,7 +43,7 @@ export default function PlaySpecific() {
|
|||
if ('local' !== type) {
|
||||
return;
|
||||
}
|
||||
async function onBeforeUnload(event) {
|
||||
async function onBeforeUnload() {
|
||||
client.disconnect();
|
||||
function waitForSave() {
|
||||
return new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
@ -88,7 +92,9 @@ export default function PlaySpecific() {
|
|||
return (
|
||||
<ClientContext.Provider value={client}>
|
||||
<MainEntityContext.Provider value={mainEntityTuple}>
|
||||
<Ui disconnected={disconnected} />
|
||||
<EcsContext.Provider value={ecsTuple}>
|
||||
<Ui disconnected={disconnected} />
|
||||
</EcsContext.Provider>
|
||||
</MainEntityContext.Provider>
|
||||
</ClientContext.Provider>
|
||||
);
|
||||
|
|
|
@ -7,17 +7,13 @@ export default function gather(imports, options = {}) {
|
|||
mapperForPath = (path) => path.replace(/\.\/(.*)\.js/, '$1'),
|
||||
} = options;
|
||||
const Gathered = {};
|
||||
let id = 1;
|
||||
for (const [path, Component] of Object.entries(imports).sort(([l], [r]) => l < r ? -1 : 1)) {
|
||||
const key = mapperForPath(path)
|
||||
.split('-')
|
||||
.map(capitalize)
|
||||
.join('');
|
||||
if (Component.gathered) {
|
||||
Component.gathered(id, key);
|
||||
}
|
||||
Gathered[key] = Gathered[id] = Component;
|
||||
id += 1;
|
||||
Gathered[
|
||||
mapperForPath(path)
|
||||
.split('-')
|
||||
.map(capitalize)
|
||||
.join('')
|
||||
] = Component;
|
||||
}
|
||||
return Gathered;
|
||||
}
|
17
app/util/gather.test.js
Normal file
17
app/util/gather.test.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {expect, test} from 'vitest';
|
||||
|
||||
import gather from './gather.js';
|
||||
|
||||
import First from './gather-test/first.js';
|
||||
import Second from './gather-test/second.js';
|
||||
|
||||
test('gathers', async () => {
|
||||
const Gathered = gather(
|
||||
import.meta.glob('./gather-test/*.js', {eager: true, import: 'default'}),
|
||||
{mapperForPath: (path) => path.replace(/\.\/gather-test\/(.*)\.js/, '$1')},
|
||||
);
|
||||
expect(Gathered.First)
|
||||
.to.equal(First);
|
||||
expect(Gathered.Second)
|
||||
.to.equal(Second);
|
||||
});
|
|
@ -146,4 +146,4 @@ export default class Script {
|
|||
);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import TickingPromise from './ticking-promise.js';
|
|||
|
||||
test('runs executor', async () => {
|
||||
expect(
|
||||
await new TickingPromise((resolve, reject) => {
|
||||
await new TickingPromise((resolve) => {
|
||||
resolve(32);
|
||||
}),
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ import {WebSocketServer} from 'ws';
|
|||
import Server from '@/net/server/server.js';
|
||||
import {getSession} from '@/session.server.js';
|
||||
|
||||
import Engine from './engine/engine.js';
|
||||
import Engine from './engine.js';
|
||||
|
||||
const wss = new WebSocketServer({
|
||||
noServer: true,
|
||||
|
@ -85,7 +85,7 @@ async function remakeServer(Engine) {
|
|||
})();
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept('./engine/engine.js', async ({default: Engine}) => {
|
||||
import.meta.hot.accept('./engine.js', async ({default: Engine}) => {
|
||||
await remakeServer(Engine);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,2 @@
|
|||
wielder.Health.health += 10
|
||||
wielder.Inventory.slots = [
|
||||
{
|
||||
...wielder.Inventory.slots[0],
|
||||
qty: wielder.Inventory.slots[0].qty - 1,
|
||||
}
|
||||
]
|
||||
item.qty -= 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user