Compare commits
5 Commits
3875f897c2
...
f9f3abf4ef
Author | SHA1 | Date | |
---|---|---|---|
|
f9f3abf4ef | ||
|
7cd05faddf | ||
|
65c23b50d9 | ||
|
520b255d5d | ||
|
2d0a3a9794 |
|
@ -4,6 +4,7 @@ import {floodwalk2D, ortho, removeCollinear} from '@/util/math.js';
|
||||||
import vector2d from './helpers/vector-2d';
|
import vector2d from './helpers/vector-2d';
|
||||||
|
|
||||||
class LayerProxy {
|
class LayerProxy {
|
||||||
|
$$sourceJson;
|
||||||
constructor(instance, Component, index) {
|
constructor(instance, Component, index) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.Component = Component;
|
this.Component = Component;
|
||||||
|
@ -79,9 +80,15 @@ class LayerProxy {
|
||||||
get layer() {
|
get layer() {
|
||||||
return this.instance.layers[this.index];
|
return this.instance.layers[this.index];
|
||||||
}
|
}
|
||||||
|
async load() {
|
||||||
|
this.$$sourceJson = await this.Component.ecs.readJson(this.layer.source);
|
||||||
|
}
|
||||||
get source() {
|
get source() {
|
||||||
return this.layer.source;
|
return this.layer.source;
|
||||||
}
|
}
|
||||||
|
get sourceJson() {
|
||||||
|
return this.$$sourceJson;
|
||||||
|
}
|
||||||
stamp(at, data) {
|
stamp(at, data) {
|
||||||
const changes = {};
|
const changes = {};
|
||||||
for (const row in data) {
|
for (const row in data) {
|
||||||
|
@ -112,7 +119,7 @@ class LayerProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TileLayers extends Component {
|
export default class TileLayers extends Component {
|
||||||
insertMany(entities) {
|
async insertMany(entities) {
|
||||||
for (const [id, {layerChange}] of entities) {
|
for (const [id, {layerChange}] of entities) {
|
||||||
if (layerChange) {
|
if (layerChange) {
|
||||||
const component = this.get(id);
|
const component = this.get(id);
|
||||||
|
@ -124,14 +131,24 @@ export default class TileLayers extends Component {
|
||||||
}
|
}
|
||||||
layers[layerIndex] = {...layers[layerIndex]};
|
layers[layerIndex] = {...layers[layerIndex]};
|
||||||
component.$$layersProxies[layerIndex] = new LayerProxy(component, this, layerIndex);
|
component.$$layersProxies[layerIndex] = new LayerProxy(component, this, layerIndex);
|
||||||
|
await component.$$layersProxies[layerIndex].load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.insertMany(entities);
|
return super.insertMany(entities);
|
||||||
}
|
}
|
||||||
load(instance) {
|
instanceFromSchema() {
|
||||||
|
return class TileLayersInstance extends super.instanceFromSchema() {
|
||||||
|
$$layersProxies = {};
|
||||||
|
layer(index) {
|
||||||
|
return this.$$layersProxies[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async load(instance) {
|
||||||
for (const index in instance.layers) {
|
for (const index in instance.layers) {
|
||||||
instance.$$layersProxies[index] = new LayerProxy(instance, this, index);
|
instance.$$layersProxies[index] = new LayerProxy(instance, this, index);
|
||||||
|
await instance.$$layersProxies[index].load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mergeDiff(original, update) {
|
mergeDiff(original, update) {
|
||||||
|
@ -149,14 +166,6 @@ export default class TileLayers extends Component {
|
||||||
}
|
}
|
||||||
return {layerChange};
|
return {layerChange};
|
||||||
}
|
}
|
||||||
instanceFromSchema() {
|
|
||||||
return class TileLayersInstance extends super.instanceFromSchema() {
|
|
||||||
$$layersProxies = {};
|
|
||||||
layer(index) {
|
|
||||||
return this.$$layersProxies[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static properties = {
|
static properties = {
|
||||||
layers: {
|
layers: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
|
|
|
@ -18,6 +18,6 @@ export default class Time extends Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
static properties = {
|
static properties = {
|
||||||
irlSeconds: {defaultValue: 18 * realSecondsPerGameHour, type: 'uint16'},
|
irlSeconds: {defaultValue: 10 * realSecondsPerGameHour, type: 'uint16'},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,13 @@ export default class Engine {
|
||||||
}
|
}
|
||||||
this.incomingActions.get(connection).push(payload);
|
this.incomingActions.get(connection).push(payload);
|
||||||
});
|
});
|
||||||
|
this.server.addPacketListener('AdminAction', (connection, payload) => {
|
||||||
|
// check...
|
||||||
|
if (!this.incomingActions.has(connection)) {
|
||||||
|
this.incomingActions.set(connection, []);
|
||||||
|
}
|
||||||
|
this.incomingActions.get(connection).push(payload);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptActions() {
|
acceptActions() {
|
||||||
|
@ -108,6 +115,14 @@ export default class Engine {
|
||||||
const {Controlled, Ecs, Interacts, Inventory, Wielder} = entity;
|
const {Controlled, Ecs, Interacts, Inventory, Wielder} = entity;
|
||||||
for (const payload of payloads) {
|
for (const payload of payloads) {
|
||||||
switch (payload.type) {
|
switch (payload.type) {
|
||||||
|
case 'paint': {
|
||||||
|
const ecs = this.ecses[Ecs.path];
|
||||||
|
const {TileLayers} = ecs.get(1);
|
||||||
|
const {brush, layer: paintLayer, stamp} = payload.value;
|
||||||
|
const layer = TileLayers.layer(paintLayer);
|
||||||
|
layer.stamp(stamp.at, stamp.data)
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'changeSlot': {
|
case 'changeSlot': {
|
||||||
if (!Controlled.locked) {
|
if (!Controlled.locked) {
|
||||||
Wielder.activeSlot = payload.value - 1;
|
Wielder.activeSlot = payload.value - 1;
|
||||||
|
|
|
@ -80,26 +80,26 @@ if (import.meta.hot) {
|
||||||
const resolver = createResolver();
|
const resolver = createResolver();
|
||||||
resolvers.push(resolver);
|
resolvers.push(resolver);
|
||||||
await beforeResolver;
|
await beforeResolver;
|
||||||
const oldBuffer = await engine.server.readData('players/0');
|
// const oldBuffer = await engine.server.readData('players/0');
|
||||||
const oldPlayer = JSON.parse((new TextDecoder()).decode(oldBuffer));
|
// const oldPlayer = JSON.parse((new TextDecoder()).decode(oldBuffer));
|
||||||
const buffer = await createPlayer(0);
|
// const buffer = await createPlayer(0);
|
||||||
const player = JSON.parse((new TextDecoder()).decode(buffer));
|
// const player = JSON.parse((new TextDecoder()).decode(buffer));
|
||||||
// Less jarring
|
// // Less jarring
|
||||||
player.Ecs = oldPlayer.Ecs;
|
// player.Ecs = oldPlayer.Ecs;
|
||||||
player.Direction = oldPlayer.Direction;
|
// player.Direction = oldPlayer.Direction;
|
||||||
player.Position = oldPlayer.Position;
|
// player.Position = oldPlayer.Position;
|
||||||
await engine.server.writeData('players/0', (new TextEncoder()).encode(JSON.stringify(player)));
|
// await engine.server.writeData('players/0', (new TextEncoder()).encode(JSON.stringify(player)));
|
||||||
resolver.resolve();
|
resolver.resolve();
|
||||||
});
|
});
|
||||||
import.meta.hot.accept('../../create-homestead.js', async ({default: createHomestead}) => {
|
import.meta.hot.accept('../../create-homestead.js', async ({default: createHomestead}) => {
|
||||||
const resolver = createResolver();
|
const resolver = createResolver();
|
||||||
resolvers.push(resolver);
|
resolvers.push(resolver);
|
||||||
await beforeResolver;
|
await beforeResolver;
|
||||||
delete engine.ecses['homesteads/0'];
|
// delete engine.ecses['homesteads/0'];
|
||||||
await engine.server.removeData('homesteads/0');
|
// await engine.server.removeData('homesteads/0');
|
||||||
const homestead = await createHomestead(engine.Ecs);
|
// const homestead = await createHomestead(engine.Ecs);
|
||||||
homestead.get(2).Ecs.path = 'houses/0';
|
// homestead.get(2).Ecs.path = 'houses/0';
|
||||||
await engine.saveEcs('homesteads/0', homestead);
|
// await engine.saveEcs('homesteads/0', homestead);
|
||||||
resolver.resolve();
|
resolver.resolve();
|
||||||
});
|
});
|
||||||
import.meta.hot.on('vite:afterUpdate', async () => {
|
import.meta.hot.on('vite:afterUpdate', async () => {
|
||||||
|
|
3
app/packets/admin-action.js
Normal file
3
app/packets/admin-action.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import Packet from '@/net/packet.js';
|
||||||
|
|
||||||
|
export default class AdminAction extends Packet {}
|
134
app/react-components/devtools.jsx
Normal file
134
app/react-components/devtools.jsx
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
import {useRef, useState} from 'react';
|
||||||
|
|
||||||
|
import {useEcs} from '@/context/ecs.js';
|
||||||
|
|
||||||
|
import styles from './devtools.module.css';
|
||||||
|
|
||||||
|
export default function Devtools({
|
||||||
|
brush,
|
||||||
|
layer,
|
||||||
|
setBrush,
|
||||||
|
setLayer,
|
||||||
|
setStamp,
|
||||||
|
}) {
|
||||||
|
const offsetRef = useRef();
|
||||||
|
const [selection, setSelection] = useState({x: 0, y: 0, w: 2, h: 2});
|
||||||
|
const [moveStart, setMoveStart] = useState();
|
||||||
|
const [ecs] = useEcs();
|
||||||
|
if (!ecs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const master = ecs.get(1);
|
||||||
|
if (!master) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const {TileLayers} = master;
|
||||||
|
const {sourceJson, tileSize} = TileLayers.layer(0);
|
||||||
|
const {w, h} = sourceJson.meta.size;
|
||||||
|
return (
|
||||||
|
<div className={styles.devtools}>
|
||||||
|
<form>
|
||||||
|
<div className={styles.topBar}>
|
||||||
|
<div className={styles.layer}>
|
||||||
|
<label>
|
||||||
|
Layer:
|
||||||
|
<select
|
||||||
|
onChange={(event) => {
|
||||||
|
setLayer(event.target.value)
|
||||||
|
}}
|
||||||
|
value={layer}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
Object.keys(TileLayers.layers)
|
||||||
|
.map((layer, i) => (
|
||||||
|
<option
|
||||||
|
key={i}
|
||||||
|
value={i}
|
||||||
|
>
|
||||||
|
{i}
|
||||||
|
</option>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className={styles.brush}>
|
||||||
|
<label>
|
||||||
|
Brush:
|
||||||
|
<select
|
||||||
|
onChange={(event) => {
|
||||||
|
setLayer(event.target.value)
|
||||||
|
}}
|
||||||
|
value={brush}
|
||||||
|
>
|
||||||
|
<option>Paint</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
||||||
|
<div
|
||||||
|
onMouseDown={(event) => {
|
||||||
|
if (!offsetRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {left, top} = offsetRef.current.getBoundingClientRect();
|
||||||
|
const x = Math.floor((event.clientX - left) / tileSize.x);
|
||||||
|
const y = Math.floor((event.clientY - top) / tileSize.y);
|
||||||
|
setMoveStart({x, y});
|
||||||
|
setSelection({x, y, w: 1, h: 1});
|
||||||
|
}}
|
||||||
|
onMouseMove={(event) => {
|
||||||
|
if (!offsetRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!moveStart) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {x: sx, y: sy} = moveStart;
|
||||||
|
const {left, top} = offsetRef.current.getBoundingClientRect();
|
||||||
|
const x = Math.floor(
|
||||||
|
Math.max(0, Math.min(w - 1, (event.clientX - left)) / tileSize.x),
|
||||||
|
);
|
||||||
|
const y = Math.floor(
|
||||||
|
Math.max(0, Math.min(h - 1, (event.clientY - top)) / tileSize.y),
|
||||||
|
);
|
||||||
|
const mx = Math.min(sx, x);
|
||||||
|
const my = Math.min(sy, y);
|
||||||
|
setSelection({x: mx, y: my, w: Math.abs(sx - x) + 1, h: Math.abs(sy - y) + 1});
|
||||||
|
}}
|
||||||
|
onMouseUp={() => {
|
||||||
|
setMoveStart();
|
||||||
|
const stamp = [];
|
||||||
|
const {x, y, w: sw, h: sh} = selection;
|
||||||
|
const tw = w / tileSize.x;
|
||||||
|
for (let iy = 0; iy < sh; ++iy) {
|
||||||
|
const row = [];
|
||||||
|
for (let ix = 0; ix < sw; ++ix) {
|
||||||
|
row.push((y + iy) * tw + x + ix);
|
||||||
|
}
|
||||||
|
stamp.push(row);
|
||||||
|
}
|
||||||
|
setStamp(stamp);
|
||||||
|
}}
|
||||||
|
className={styles.selectionWrapper}
|
||||||
|
ref={offsetRef}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={styles.selection}
|
||||||
|
style={{
|
||||||
|
top: selection.y * tileSize.y,
|
||||||
|
left: selection.x * tileSize.x,
|
||||||
|
height: selection.h * tileSize.x,
|
||||||
|
width: selection.w * tileSize.y,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
alt="tileset"
|
||||||
|
src={TileLayers.layer(0).source.replace('.json', '.png')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
30
app/react-components/devtools.module.css
Normal file
30
app/react-components/devtools.module.css
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
.topBar {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.devtools {
|
||||||
|
background-color: #444444;
|
||||||
|
color: white;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.devtools p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectionWrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectionWrapper img {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection {
|
||||||
|
background-color: #ffffff44;
|
||||||
|
position: absolute;
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: calc(100% / var(--scale));
|
height: calc(100% / var(--scale));
|
||||||
|
left: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
transform: scale(var(--scale));
|
transform: scale(var(--scale));
|
||||||
|
|
|
@ -44,10 +44,6 @@ function createLayerMask(layer) {
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
|
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
|
||||||
for (let i = 0; i < hulls.length; ++i) {
|
for (let i = 0; i < hulls.length; ++i) {
|
||||||
const {x, y} = hulls[i][0];
|
|
||||||
if (7 !== layer.tile({x: Math.floor(x / tileSize.x), y: Math.floor(y / tileSize.y)})) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const hull = [...hulls[i]];
|
const hull = [...hulls[i]];
|
||||||
hull.push(hull[0]);
|
hull.push(hull[0]);
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 75%;
|
background-size: 75%;
|
||||||
height: calc(100% - var(--space) * 2);
|
height: 100%;
|
||||||
padding: var(--space);
|
padding: var(--space);
|
||||||
position: relative;
|
position: relative;
|
||||||
width: calc(100% - var(--space) * 2);
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.qty {
|
.qty {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useRef, useState} from 'react';
|
||||||
|
|
||||||
import addKeyListener from '@/add-key-listener.js';
|
import addKeyListener from '@/add-key-listener.js';
|
||||||
import ClientEcs from '@/client-ecs';
|
import ClientEcs from '@/client-ecs';
|
||||||
|
@ -8,14 +8,13 @@ import {useDebug} from '@/context/debug.js';
|
||||||
import {useEcs, useEcsTick} from '@/context/ecs.js';
|
import {useEcs, useEcsTick} from '@/context/ecs.js';
|
||||||
import {useMainEntity} from '@/context/main-entity.js';
|
import {useMainEntity} from '@/context/main-entity.js';
|
||||||
|
|
||||||
|
import Devtools from './devtools.jsx';
|
||||||
import Disconnected from './disconnected.jsx';
|
import Disconnected from './disconnected.jsx';
|
||||||
import Dom from './dom.jsx';
|
import Dom from './dom.jsx';
|
||||||
import HotBar from './hotbar.jsx';
|
import HotBar from './hotbar.jsx';
|
||||||
import Pixi from './pixi.jsx';
|
import Pixi from './pixi.jsx';
|
||||||
import styles from './ui.module.css';
|
import styles from './ui.module.css';
|
||||||
|
|
||||||
const ratio = RESOLUTION.x / RESOLUTION.y;
|
|
||||||
|
|
||||||
function emptySlots() {
|
function emptySlots() {
|
||||||
return Array(10).fill(undefined);
|
return Array(10).fill(undefined);
|
||||||
}
|
}
|
||||||
|
@ -23,16 +22,22 @@ function emptySlots() {
|
||||||
export default function Ui({disconnected}) {
|
export default function Ui({disconnected}) {
|
||||||
// Key input.
|
// Key input.
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
|
const gameRef = useRef();
|
||||||
const [mainEntity, setMainEntity] = useMainEntity();
|
const [mainEntity, setMainEntity] = useMainEntity();
|
||||||
const [debug, setDebug] = useDebug();
|
const [debug, setDebug] = useDebug();
|
||||||
const [ecs, setEcs] = useEcs();
|
const [ecs, setEcs] = useEcs();
|
||||||
const [showDisconnected, setShowDisconnected] = useState(false);
|
const [showDisconnected, setShowDisconnected] = useState(false);
|
||||||
const [bufferSlot, setBufferSlot] = useState();
|
const [bufferSlot, setBufferSlot] = useState();
|
||||||
|
const [devtoolsIsOpen, setDevtoolsIsOpen] = useState(false);
|
||||||
|
const ratio = (RESOLUTION.x * (devtoolsIsOpen ? 2 : 1)) / RESOLUTION.y;
|
||||||
const [hotbarSlots, setHotbarSlots] = useState(emptySlots());
|
const [hotbarSlots, setHotbarSlots] = useState(emptySlots());
|
||||||
const [activeSlot, setActiveSlot] = useState(0);
|
const [activeSlot, setActiveSlot] = useState(0);
|
||||||
const [scale, setScale] = useState(2);
|
const [scale, setScale] = useState(2);
|
||||||
const [Components, setComponents] = useState();
|
const [Components, setComponents] = useState();
|
||||||
const [Systems, setSystems] = useState();
|
const [Systems, setSystems] = useState();
|
||||||
|
const [layer, setLayer] = useState(0);
|
||||||
|
const [brush, setBrush] = useState(0);
|
||||||
|
const [stamp, setStamp] = useState([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function setEcsStuff() {
|
async function setEcsStuff() {
|
||||||
const {default: Components} = await import('@/ecs-components/index.js');
|
const {default: Components} = await import('@/ecs-components/index.js');
|
||||||
|
@ -87,6 +92,15 @@ export default function Ui({disconnected}) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'F4': {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
if ('keyDown' === type) {
|
||||||
|
setDevtoolsIsOpen(!devtoolsIsOpen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'w': {
|
case 'w': {
|
||||||
actionPayload = {type: 'moveUp', value: KEY_MAP[type]};
|
actionPayload = {type: 'moveUp', value: KEY_MAP[type]};
|
||||||
break;
|
break;
|
||||||
|
@ -179,7 +193,7 @@ export default function Ui({disconnected}) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [client, debug, setDebug, setScale]);
|
}, [client, debug, devtoolsIsOpen, setDebug, setScale]);
|
||||||
usePacket('EcsChange', async () => {
|
usePacket('EcsChange', async () => {
|
||||||
setMainEntity(undefined);
|
setMainEntity(undefined);
|
||||||
setEcs(new ClientEcs({Components, Systems}));
|
setEcs(new ClientEcs({Components, Systems}));
|
||||||
|
@ -231,16 +245,75 @@ export default function Ui({disconnected}) {
|
||||||
};
|
};
|
||||||
}, [])
|
}, [])
|
||||||
return (
|
return (
|
||||||
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
||||||
<div
|
<div
|
||||||
className={styles.ui}
|
className={styles.ui}
|
||||||
|
>
|
||||||
|
<style>
|
||||||
|
{`
|
||||||
|
@media (max-aspect-ratio: ${ratio}) { .${styles.game} { width: 100%; } }
|
||||||
|
@media (min-aspect-ratio: ${ratio}) { .${styles.game} { height: 100%; } }
|
||||||
|
.${styles.game} {
|
||||||
|
cursor: ${
|
||||||
|
bufferSlot
|
||||||
|
? `url('${bufferSlot.icon}'), auto !important`
|
||||||
|
: 'auto'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
</style>
|
||||||
|
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */ }
|
||||||
|
<div
|
||||||
|
className={[styles.game, devtoolsIsOpen && styles.devtoolsIsOpen].filter(Boolean).join(' ')}
|
||||||
onMouseDown={(event) => {
|
onMouseDown={(event) => {
|
||||||
switch (event.button) {
|
switch (event.button) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (devtoolsIsOpen) {
|
||||||
|
if (!gameRef.current || !mainEntity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {top, left, width} = gameRef.current.getBoundingClientRect();
|
||||||
|
const master = ecs.get(1);
|
||||||
|
if (!master) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {Camera} = ecs.get(mainEntity);
|
||||||
|
const {TileLayers} = master;
|
||||||
|
const {area, tileSize} = TileLayers.layer(0);
|
||||||
|
const size = width / RESOLUTION.x;
|
||||||
|
const cr = {
|
||||||
|
x: (event.clientX - left) / size,
|
||||||
|
y: (event.clientY - top) / size,
|
||||||
|
};
|
||||||
|
const cm = {
|
||||||
|
x: ((Camera.x * scale) - (RESOLUTION.x / 2)),
|
||||||
|
y: ((Camera.y * scale) - (RESOLUTION.y / 2)),
|
||||||
|
}
|
||||||
|
const at = {
|
||||||
|
x: Math.floor((cr.x + cm.x) / (tileSize.x * scale)),
|
||||||
|
y: Math.floor((cr.y + cm.y) / (tileSize.y * scale)),
|
||||||
|
};
|
||||||
|
if (at.x < 0 || at.y < 0 || at.x >= area.x || at.y >= area.y) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
brush,
|
||||||
|
layer,
|
||||||
|
stamp: {
|
||||||
|
at,
|
||||||
|
data: stamp,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
client.send({
|
||||||
|
type: 'AdminAction',
|
||||||
|
payload: {type: 'paint', value: payload},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
client.send({
|
client.send({
|
||||||
type: 'Action',
|
type: 'Action',
|
||||||
payload: {type: 'use', value: 1},
|
payload: {type: 'use', value: 1},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
client.send({
|
client.send({
|
||||||
|
@ -282,23 +355,11 @@ export default function Ui({disconnected}) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
ref={gameRef}
|
||||||
>
|
>
|
||||||
<style>
|
|
||||||
{`
|
|
||||||
@media (max-aspect-ratio: ${ratio}) { .${styles.ui} { width: 100%; } }
|
|
||||||
@media (min-aspect-ratio: ${ratio}) { .${styles.ui} { height: 100%; } }
|
|
||||||
.${styles.ui} {
|
|
||||||
cursor: ${
|
|
||||||
bufferSlot
|
|
||||||
? `url('${bufferSlot.icon}'), auto !important`
|
|
||||||
: 'auto'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
</style>
|
|
||||||
<Pixi scale={scale} />
|
<Pixi scale={scale} />
|
||||||
{mainEntity && (
|
{mainEntity && (
|
||||||
<Dom>
|
<Dom devtoolsIsOpen={devtoolsIsOpen}>
|
||||||
<HotBar
|
<HotBar
|
||||||
active={activeSlot}
|
active={activeSlot}
|
||||||
onActivate={(i) => {
|
onActivate={(i) => {
|
||||||
|
@ -315,6 +376,17 @@ export default function Ui({disconnected}) {
|
||||||
</Dom>
|
</Dom>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className={[styles.devtools, devtoolsIsOpen && styles.devtoolsIsOpen].filter(Boolean).join(' ')}>
|
||||||
|
<Devtools
|
||||||
|
brush={brush}
|
||||||
|
layer={layer}
|
||||||
|
stamp={stamp}
|
||||||
|
setBrush={setBrush}
|
||||||
|
setLayer={setLayer}
|
||||||
|
setStamp={setStamp}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,23 @@
|
||||||
.ui {
|
.devtools {
|
||||||
|
display: none;
|
||||||
|
height: 100%;
|
||||||
|
&.devtoolsIsOpen {
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.game {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
&.devtoolsIsOpen {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui {
|
||||||
|
display: flex;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ html, body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
* {
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user