refactor: item
This commit is contained in:
parent
c4908a8252
commit
e87d921714
|
@ -20,61 +20,13 @@ export default class Inventory extends Component {
|
|||
}
|
||||
return super.insertMany(entities);
|
||||
}
|
||||
mergeDiff(original, update) {
|
||||
if (!update.slotChange) {
|
||||
return super.mergeDiff(original, update);
|
||||
}
|
||||
const slotChange = {
|
||||
...original.slotChange,
|
||||
};
|
||||
for (const index in update.slotChange) {
|
||||
if (false === update.slotChange[index]) {
|
||||
slotChange[index] = false;
|
||||
}
|
||||
else {
|
||||
slotChange[index] = {
|
||||
...slotChange[index],
|
||||
...update.slotChange[index],
|
||||
};
|
||||
}
|
||||
}
|
||||
return {slotChange};
|
||||
}
|
||||
instanceFromSchema() {
|
||||
const Instance = super.instanceFromSchema();
|
||||
const Component = this;
|
||||
return class InventoryInstance extends Instance {
|
||||
async item(slot) {
|
||||
const {slots} = this;
|
||||
if (!(slot in slots)) {
|
||||
return undefined;
|
||||
}
|
||||
const {readAsset} = Component.ecs;
|
||||
const chars = await readAsset([slots[slot].source, 'item.json'].join('/'))
|
||||
const json = chars.byteLength > 0
|
||||
? JSON.parse(
|
||||
(new TextDecoder()).decode(chars),
|
||||
)
|
||||
: {};
|
||||
const item = {
|
||||
...slots[slot],
|
||||
...json,
|
||||
};
|
||||
const instance = this;
|
||||
const proxy = new Proxy(item, {
|
||||
set(target, property, value) {
|
||||
slots[slot][property] = value;
|
||||
if ('qty' === property && value <= 0) {
|
||||
Component.markChange(instance.entity, 'slotChange', {[slot]: false});
|
||||
delete slots[slot];
|
||||
}
|
||||
else {
|
||||
Component.markChange(instance.entity, 'slotChange', {[slot]: {[property]: value}});
|
||||
}
|
||||
return true;
|
||||
},
|
||||
});
|
||||
return proxy;
|
||||
$$items = {};
|
||||
item(slot) {
|
||||
return this.$$items[slot];
|
||||
}
|
||||
swapSlots(l, r) {
|
||||
const {slots} = this;
|
||||
|
@ -98,6 +50,115 @@ export default class Inventory extends Component {
|
|||
}
|
||||
}
|
||||
}
|
||||
async load(instance) {
|
||||
const Component = this;
|
||||
const {readAsset} = this.ecs;
|
||||
const {slots} = instance;
|
||||
class ItemProxy {
|
||||
constructor(slot, json) {
|
||||
this.json = json;
|
||||
this.slot = slot;
|
||||
}
|
||||
project(position, direction) {
|
||||
const {TileLayers: {layers: [layer]}} = Component.ecs.get(1);
|
||||
const {projection} = this.json;
|
||||
let startX = position.x;
|
||||
let startY = position.y;
|
||||
switch (direction) {
|
||||
case 0:
|
||||
startX += projection.distance[1];
|
||||
startY -= projection.distance[0];
|
||||
break;
|
||||
case 1:
|
||||
startX += projection.distance[0];
|
||||
startY += projection.distance[1];
|
||||
break;
|
||||
case 2:
|
||||
startX -= projection.distance[1];
|
||||
startY += projection.distance[0];
|
||||
break;
|
||||
case 3:
|
||||
startX -= projection.distance[0];
|
||||
startY -= projection.distance[1];
|
||||
break;
|
||||
}
|
||||
const projected = [];
|
||||
for (const row in projection.grid) {
|
||||
const columns = projection.grid[row];
|
||||
for (const column in columns) {
|
||||
const targeted = projection.grid[row][column];
|
||||
if (targeted) {
|
||||
let axe;
|
||||
switch (direction) {
|
||||
case 0:
|
||||
axe = [column, row];
|
||||
break;
|
||||
case 1:
|
||||
axe = [-row, column];
|
||||
break;
|
||||
case 2:
|
||||
axe = [-column, -row];
|
||||
break;
|
||||
case 3:
|
||||
axe = [row, -column];
|
||||
break;
|
||||
}
|
||||
const x = startX + parseInt(axe[0]);
|
||||
const y = startY + parseInt(axe[1]);
|
||||
if (x < 0 || y < 0 || x >= layer.area.x || y >= layer.area.y) {
|
||||
continue;
|
||||
}
|
||||
projected.push({x, y});
|
||||
}
|
||||
}
|
||||
}
|
||||
return projected;
|
||||
}
|
||||
get qty() {
|
||||
return slots[this.slot].qty;
|
||||
}
|
||||
set qty(qty) {
|
||||
if (qty <= 0) {
|
||||
Component.markChange(instance.entity, 'slotChange', {[this.slot]: false});
|
||||
delete slots[this.slot];
|
||||
}
|
||||
else {
|
||||
slots[this.slot].qty = qty;
|
||||
Component.markChange(instance.entity, 'slotChange', {[this.slot]: {qty}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
mergeDiff(original, update) {
|
||||
if (!update.slotChange) {
|
||||
return super.mergeDiff(original, update);
|
||||
}
|
||||
const slotChange = {
|
||||
...original.slotChange,
|
||||
};
|
||||
for (const index in update.slotChange) {
|
||||
if (false === update.slotChange[index]) {
|
||||
slotChange[index] = false;
|
||||
}
|
||||
else {
|
||||
slotChange[index] = {
|
||||
...slotChange[index],
|
||||
...update.slotChange[index],
|
||||
};
|
||||
}
|
||||
}
|
||||
return {slotChange};
|
||||
}
|
||||
static properties = {
|
||||
slots: {
|
||||
type: 'map',
|
||||
|
|
|
@ -31,7 +31,6 @@ export default class Plant extends Component {
|
|||
instance.growScriptInstance = await Script.fromCode((new TextDecoder()).decode(code), context);
|
||||
}
|
||||
});
|
||||
|
||||
await readAsset(instance.mayGrowScript)
|
||||
.then(async (code) => {
|
||||
if (code.byteLength > 0) {
|
||||
|
|
|
@ -6,69 +6,14 @@ export default class Wielder extends Component {
|
|||
const {ecs} = this;
|
||||
const Instance = super.instanceFromSchema();
|
||||
return class WielderInstance extends Instance {
|
||||
async activeItem() {
|
||||
activeItem() {
|
||||
const {Inventory, Wielder} = ecs.get(this.entity);
|
||||
return Inventory.item(Wielder.activeSlot + 1);
|
||||
}
|
||||
project(position, projection) {
|
||||
const {TileLayers: {layers: [layer]}} = ecs.get(1);
|
||||
const {Direction: {direction}} = ecs.get(this.entity);
|
||||
let startX = position.x;
|
||||
let startY = position.y;
|
||||
switch (direction) {
|
||||
case 0:
|
||||
startX += projection.distance[1];
|
||||
startY -= projection.distance[0];
|
||||
break;
|
||||
case 1:
|
||||
startX += projection.distance[0];
|
||||
startY += projection.distance[1];
|
||||
break;
|
||||
case 2:
|
||||
startX -= projection.distance[1];
|
||||
startY += projection.distance[0];
|
||||
break;
|
||||
case 3:
|
||||
startX -= projection.distance[0];
|
||||
startY -= projection.distance[1];
|
||||
break;
|
||||
}
|
||||
const projected = [];
|
||||
for (const row in projection.grid) {
|
||||
const columns = projection.grid[row];
|
||||
for (const column in columns) {
|
||||
const targeted = projection.grid[row][column];
|
||||
if (targeted) {
|
||||
let axe;
|
||||
switch (direction) {
|
||||
case 0:
|
||||
axe = [column, row];
|
||||
break;
|
||||
case 1:
|
||||
axe = [-row, column];
|
||||
break;
|
||||
case 2:
|
||||
axe = [-column, -row];
|
||||
break;
|
||||
case 3:
|
||||
axe = [row, -column];
|
||||
break;
|
||||
}
|
||||
const x = startX + parseInt(axe[0]);
|
||||
const y = startY + parseInt(axe[1]);
|
||||
if (x < 0 || y < 0 || x >= layer.area.x || y >= layer.area.y) {
|
||||
continue;
|
||||
}
|
||||
projected.push({x, y});
|
||||
}
|
||||
}
|
||||
}
|
||||
return projected;
|
||||
}
|
||||
async useActiveItem(state) {
|
||||
useActiveItem(state) {
|
||||
const entity = ecs.get(this.entity);
|
||||
const {Ticking} = entity;
|
||||
const activeItem = await this.activeItem();
|
||||
const activeItem = this.activeItem();
|
||||
if (activeItem) {
|
||||
ecs.readAsset([activeItem.source, state ? 'start.js' : 'stop.js'].join('/'))
|
||||
.then((code) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {Container} from '@pixi/react';
|
||||
import {useEffect, useState} from 'react';
|
||||
import {useState} from 'react';
|
||||
|
||||
import {RESOLUTION} from '@/constants.js';
|
||||
import {useEcs, useEcsTick} from '@/context/ecs.js';
|
||||
|
@ -13,29 +13,8 @@ import TileLayer from './tile-layer.jsx';
|
|||
export default function EcsComponent() {
|
||||
const [ecs] = useEcs();
|
||||
const [entities, setEntities] = useState({});
|
||||
const [activeTool, setActiveTool] = useState(false);
|
||||
const [mainEntity] = useMainEntity();
|
||||
useEffect(() => {
|
||||
if (mainEntity) {
|
||||
ecs.get(mainEntity)
|
||||
.Wielder.activeItem()
|
||||
.then(({tool} = {}) => {
|
||||
setActiveTool(tool);
|
||||
});
|
||||
}
|
||||
}, [ecs, mainEntity]);
|
||||
useEcsTick((payload) => {
|
||||
if (
|
||||
mainEntity
|
||||
&& payload[mainEntity]
|
||||
&& (payload[mainEntity].Inventory || payload[mainEntity].Wielder)
|
||||
) {
|
||||
ecs.get(mainEntity)
|
||||
.Wielder.activeItem()
|
||||
.then(({tool} = {}) => {
|
||||
setActiveTool(tool);
|
||||
});
|
||||
}
|
||||
const updatedEntities = {...entities};
|
||||
for (const id in payload) {
|
||||
const update = payload[id];
|
||||
|
@ -58,6 +37,8 @@ export default function EcsComponent() {
|
|||
return false;
|
||||
}
|
||||
const entity = ecs.get(mainEntity);
|
||||
const {Direction, Position, Wielder} = entity;
|
||||
const projected = Wielder.activeItem()?.project(Position.tile, Direction.direction)
|
||||
const {Camera} = entity;
|
||||
const {TileLayers: {layers: [layer]}} = ecs.get(1);
|
||||
const [cx, cy] = [
|
||||
|
@ -70,17 +51,17 @@ export default function EcsComponent() {
|
|||
y={-cy}
|
||||
>
|
||||
<TileLayer tileLayer={layer} />
|
||||
{activeTool && (
|
||||
{projected && (
|
||||
<TargetingGrid
|
||||
entity={entity}
|
||||
tileLayer={layer}
|
||||
x={Position.x}
|
||||
y={Position.y}
|
||||
/>
|
||||
)}
|
||||
<Entities entities={entities} />
|
||||
{activeTool && (
|
||||
{projected?.length > 0 && (
|
||||
<TargetingGhost
|
||||
entity={entity}
|
||||
projection={activeTool.projection}
|
||||
projected={projected}
|
||||
tileLayer={layer}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -36,7 +36,7 @@ function Entities({entity}) {
|
|||
}
|
||||
return (
|
||||
<Container
|
||||
zIndex={entity.Position?.y}
|
||||
zIndex={entity.Position?.y || 0}
|
||||
>
|
||||
{entity.Sprite && (
|
||||
<Sprite
|
||||
|
|
|
@ -33,7 +33,7 @@ const TargetingGhostInternal = PixiComponent('TargetingGhost', {
|
|||
},
|
||||
})
|
||||
|
||||
export default function TargetingGhost({entity, projection, tileLayer}) {
|
||||
export default function TargetingGhost({projected, tileLayer}) {
|
||||
const [radians, setRadians] = useState(0);
|
||||
useEffect(() => {
|
||||
const handle = setInterval(() => {
|
||||
|
@ -43,8 +43,6 @@ export default function TargetingGhost({entity, projection, tileLayer}) {
|
|||
clearInterval(handle);
|
||||
};
|
||||
}, []);
|
||||
const {Position, Wielder} = entity;
|
||||
const projected = Wielder.project(Position.tile, projection)
|
||||
const ghosts = [];
|
||||
const {area} = tileLayer;
|
||||
for (const {x, y} of projected) {
|
||||
|
|
|
@ -69,9 +69,8 @@ const TargetingGridInternal = PixiComponent('TargetingGrid', {
|
|||
top.addChild(container, area);
|
||||
return top;
|
||||
},
|
||||
applyProps: ({children: [container]}, oldProps, {entity, radians}) => {
|
||||
applyProps: ({children: [container]}, oldProps, {x, y, radians}) => {
|
||||
const pulse = (Math.cos(radians) + 1) * 0.5;
|
||||
const {Position: {x, y}} = entity;
|
||||
const tileX = x - (x % tileSize.x);
|
||||
const tileY = y - (y % tileSize.y);
|
||||
const gridX = (tileSize.x * (radius / 2));
|
||||
|
@ -85,7 +84,7 @@ const TargetingGridInternal = PixiComponent('TargetingGrid', {
|
|||
},
|
||||
})
|
||||
|
||||
export default function TargetingGrid({entity, tileLayer}) {
|
||||
export default function TargetingGrid({tileLayer, x, y}) {
|
||||
const app = useApp();
|
||||
const [radians, setRadians] = useState(0);
|
||||
useEffect(() => {
|
||||
|
@ -99,9 +98,10 @@ export default function TargetingGrid({entity, tileLayer}) {
|
|||
return (
|
||||
<TargetingGridInternal
|
||||
app={app}
|
||||
entity={entity}
|
||||
radians={radians}
|
||||
tileLayer={tileLayer}
|
||||
x={x}
|
||||
y={y}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
{
|
||||
"tool": {
|
||||
"projection": {
|
||||
"distance": [1, 0],
|
||||
"grid": [
|
||||
[1]
|
||||
]
|
||||
}
|
||||
"projection": {
|
||||
"distance": [1, 0],
|
||||
"grid": [
|
||||
[1]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const {Position, Wielder} = wielder
|
||||
const projected = Wielder.project(Position.tile, item.tool.projection)
|
||||
if (projected.length > 0) {
|
||||
const {Direction, Position, Wielder} = wielder
|
||||
const projected = Wielder.activeItem()?.project(Position.tile, Direction.direction)
|
||||
if (projected?.length > 0) {
|
||||
|
||||
const {Controlled, Emitter, Sound, Sprite} = wielder
|
||||
const {TileLayers} = ecs.get(1)
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
{
|
||||
"tool": {
|
||||
"projection": {
|
||||
"distance": [1, -1],
|
||||
"grid": [
|
||||
[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1]
|
||||
]
|
||||
}
|
||||
"projection": {
|
||||
"distance": [1, -1],
|
||||
"grid": [
|
||||
[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user