refactor: items

This commit is contained in:
cha0s 2024-06-28 12:12:38 -05:00
parent 023e82c521
commit deb88b07ba
14 changed files with 113 additions and 53 deletions

View File

@ -6,6 +6,7 @@ export const TRAVERSAL_PATH = {
BinaryExpression: ['left', 'right'],
BlockStatement: ['body'],
CallExpression: ['arguments', 'callee'],
ChainExpression: ['expression'],
ConditionalExpression: ['alternate', 'consequent', 'test'],
DoWhileStatement: ['body', 'test'],
ExpressionStatement: ['expression'],

View File

@ -52,16 +52,20 @@ export default class Inventory extends Component {
}
async load(instance) {
const Component = this;
const {readAsset} = this.ecs;
const {slots} = instance;
class ItemProxy {
constructor(slot, json) {
constructor(slot, json, scripts) {
this.json = json;
this.scripts = scripts;
this.slot = slot;
}
project(position, direction) {
const {TileLayers: {layers: [layer]}} = Component.ecs.get(1);
const {TileLayers} = Component.ecs.get(1);
const layer = TileLayers.layer(0);
const {projection} = this.json;
if (!projection) {
return [];
}
let startX = position.x;
let startY = position.y;
switch (direction) {
@ -112,7 +116,14 @@ export default class Inventory extends Component {
}
}
}
return projected;
if (this.scripts.projectionCheckInstance) {
this.scripts.projectionCheckInstance.context.layer = layer;
this.scripts.projectionCheckInstance.context.projected = projected;
return this.scripts.projectionCheckInstance.evaluateSync();
}
else {
return projected;
}
}
get qty() {
return slots[this.slot].qty;
@ -128,15 +139,19 @@ export default class Inventory extends Component {
}
}
}
for (const slot in slots) {
const chars = await readAsset([slots[slot].source, 'item.json'].join('/'))
const json = chars.byteLength > 0
? JSON.parse(
(new TextDecoder()).decode(chars),
)
: {};
instance.$$items[slot] = new ItemProxy(slots, json);
const json = await this.ecs.readJson(slots[slot].source);
const scripts = {};
if (json.projectionCheck) {
scripts.projectionCheckInstance = await this.ecs.readScript(json.projectionCheck);
}
if (json.start) {
scripts.startInstance = await this.ecs.readScript(json.start);
}
if (json.stop) {
scripts.stopInstance = await this.ecs.readScript(json.stop);
}
instance.$$items[slot] = new ItemProxy(slots, json, scripts);
}
}
mergeDiff(original, update) {

View File

@ -1,5 +1,4 @@
import Component from '@/ecs/component.js';
import Script from '@/util/script.js';
export default class Wielder extends Component {
instanceFromSchema() {
@ -15,20 +14,15 @@ export default class Wielder extends Component {
const {Ticking} = entity;
const activeItem = this.activeItem();
if (activeItem) {
ecs.readAsset([activeItem.source, state ? 'start.js' : 'stop.js'].join('/'))
.then((code) => {
if (code.byteLength > 0) {
const context = {
ecs,
item: activeItem,
wielder: entity,
};
Ticking.addTickingPromise(Script.tickingPromise((new TextDecoder()).decode(code), context));
}
});
const {startInstance, stopInstance} = activeItem.scripts;
const script = state ? startInstance : stopInstance;
if (script) {
script.context.ecs = ecs;
script.context.item = activeItem;
script.context.wielder = entity;
Ticking.addTickingPromise(script.tickingPromise());
}
}
}
}
}

View File

@ -5,6 +5,7 @@ import Ecs from '@/ecs/ecs.js';
import Components from '@/ecs-components/index.js';
import Systems from '@/ecs-systems/index.js';
import {decode, encode} from '@/packets/index.js';
import Script from '@/util/script.js';
function join(...parts) {
return parts.join('/');
@ -33,9 +34,19 @@ export default class Engine {
}
const server = this.server = new SilphiusServer();
this.Ecs = class EngineEcs extends Ecs {
readAsset(uri) {
async readAsset(uri) {
return server.readAsset(uri);
}
async readJson(uri) {
const chars = await this.readAsset(uri);
return chars.byteLength > 0 ? JSON.parse((new TextDecoder()).decode(chars)) : {};
}
async readScript(uri) {
const code = await this.readAsset(uri);
if (code.byteLength > 0) {
return Script.fromCode((new TextDecoder()).decode(code));
}
}
}
this.server.addPacketListener('Action', (connection, payload) => {
this.incomingActions.push([this.connectedPlayers.get(connection).entity, payload]);
@ -184,15 +195,15 @@ export default class Engine {
slots: {
1: {
qty: 10,
source: '/assets/potion',
source: '/assets/potion/potion.json',
},
3: {
qty: 1,
source: '/assets/tomato-seeds',
source: '/assets/tomato-seeds/tomato-seeds.json',
},
4: {
qty: 1,
source: '/assets/hoe',
source: '/assets/hoe/hoe.json',
},
},
},

View File

@ -4,15 +4,14 @@ import styles from './slot.module.css';
* An inventory slot. Displays an item image and the quantity of the item if > 1.
*/
export default function Slot({
json,
onClick,
onDragEnter,
onDragOver,
onDragStart,
onDrop,
qty = 1,
source,
}) {
const image = source + '/icon.png';
return (
<button
className={styles.slot}
@ -28,7 +27,7 @@ export default function Slot({
>
<div
className={styles.slotInner}
style={image ? {backgroundImage: `url(${image})`} : {}}
style={json?.icon ? {backgroundImage: `url(${json.icon})`} : {}}
>
{qty > 1 && (
<span

View File

@ -176,7 +176,7 @@ export default function Ui({disconnected}) {
setBufferSlot(entity.Inventory.slots[0]);
const newHotbarSlots = emptySlots();
for (let i = 1; i < 11; ++i) {
newHotbarSlots[i - 1] = entity.Inventory.slots[i];
newHotbarSlots[i - 1] = entity.Inventory.item(i);
}
setHotbarSlots(newHotbarSlots);
}

View File

@ -12,6 +12,7 @@ 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';
import Script from '@/util/script.js';
import {LRUCache} from 'lru-cache';
@ -20,7 +21,7 @@ export const cache = new LRUCache({
});
class ClientEcs extends Ecs {
readAsset(uri) {
async readAsset(uri) {
if (!cache.has(uri)) {
let promise, resolve, reject;
promise = new Promise((res, rej) => {
@ -36,6 +37,16 @@ class ClientEcs extends Ecs {
}
return cache.get(uri);
}
async readJson(uri) {
const chars = await this.readAsset(uri);
return chars.byteLength > 0 ? JSON.parse((new TextDecoder()).decode(chars)) : {};
}
async readScript(uri) {
const code = await this.readAsset(uri);
if (code.byteLength > 0) {
return Script.fromCode((new TextDecoder()).decode(code));
}
}
}
export async function loader({request}) {

View File

@ -0,0 +1,11 @@
{
"icon": "/assets/hoe/icon.png",
"projectionCheck": "/assets/hoe/projection-check.js",
"projection": {
"distance": [1, 0],
"grid": [
[1]
]
},
"start": "/assets/hoe/start.js"
}

View File

@ -1,8 +0,0 @@
{
"projection": {
"distance": [1, 0],
"grid": [
[1]
]
}
}

View File

@ -0,0 +1,10 @@
const filtered = []
for (let i = 0; i < projected.length; ++i) {
const tile = layer.tile(projected[i])
if ([1, 2, 3, 4, 6].includes(tile)) {
filtered.push(projected[i])
}
}
return filtered

View File

@ -0,0 +1,3 @@
{
"icon": "/assets/potion/icon.png"
}

View File

@ -1,10 +0,0 @@
{
"projection": {
"distance": [1, -1],
"grid": [
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]
]
}
}

View File

@ -0,0 +1,10 @@
const filtered = []
for (let i = 0; i < projected.length; ++i) {
const tile = layer.tile(projected[i])
if ([7].includes(tile)) {
filtered.push(projected[i])
}
}
return filtered

View File

@ -0,0 +1,13 @@
{
"icon": "/assets/tomato-seeds/icon.png",
"projection": {
"distance": [1, -1],
"grid": [
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]
]
},
"projectionCheck": "/assets/tomato-seeds/projection-check.js",
"start": "/assets/tomato-seeds/start.js"
}