diff --git a/packages/app/src/components/app/play/index.jsx b/packages/app/src/components/app/play/index.jsx
index acbea57..e0331f6 100644
--- a/packages/app/src/components/app/play/index.jsx
+++ b/packages/app/src/components/app/play/index.jsx
@@ -1,9 +1,63 @@
-import {React} from '@flecks/react';
+import {InputNormalizer} from '@avocado/input/client';
+import {
+ React,
+ useEffect,
+} from '@flecks/react';
+import {useDispatch} from '@flecks/redux';
+import {useSocket} from '@flecks/socket';
+import {setSelfEntity} from '@humus/app/state';
+
+import {
+ useSelfEntity,
+} from '../../../hooks';
import Renderable from './renderable';
import Ui from './ui';
function Play() {
+ const dispatch = useDispatch();
+ const selfEntity = useSelfEntity();
+ const socket = useSocket();
+ // Join.
+ useEffect(() => {
+ const join = async () => {
+ dispatch(setSelfEntity(await socket.send(['Join'])));
+ };
+ join();
+ socket.on('reconnect', join);
+ return () => {
+ socket.off('reconnect', join);
+ };
+ }, [dispatch, socket]);
+ // Input.
+ useEffect(() => {
+ if (!selfEntity) {
+ return undefined;
+ }
+ const inputNormalizer = new InputNormalizer();
+ inputNormalizer.listen(window.document.body);
+ selfEntity.listenForInput(inputNormalizer);
+ selfEntity.actionRegistry.setTransformerFor('UseItem', (type, value) => {
+ switch (type) {
+ case 'joystick':
+ return value === 0 ? -1 : selfEntity.activeSlotIndex;
+ case 'buttonPress':
+ case 'keyDown':
+ return selfEntity.activeSlotIndex;
+ default:
+ return -1;
+ }
+ });
+ const inputHandle = setInterval(() => {
+ const actionStream = selfEntity.drainInput();
+ if (actionStream.length > 0) {
+ socket.send(['Input', actionStream]);
+ }
+ }, 1000 / 60);
+ return () => {
+ clearInterval(inputHandle);
+ };
+ }, [selfEntity, socket]);
return (
<>
diff --git a/packages/app/src/components/app/play/ui/index.jsx b/packages/app/src/components/app/play/ui/index.jsx
index 9ac4376..165810a 100644
--- a/packages/app/src/components/app/play/ui/index.jsx
+++ b/packages/app/src/components/app/play/ui/index.jsx
@@ -1,6 +1,3 @@
-import './index.scss';
-
-import {InputNormalizer} from '@avocado/input/client';
import {Vector} from '@avocado/math';
import {Room} from '@avocado/topdown';
import {
@@ -10,11 +7,6 @@ import {
useRef,
useState,
} from '@flecks/react';
-import {useDispatch} from '@flecks/redux';
-import {useSocket} from '@flecks/socket';
-import {
- setSelfEntity,
-} from '@humus/app/state';
import {
useRoom,
@@ -23,83 +15,47 @@ import {
import Hotbar from './hotbar';
const PlayUi = () => {
- const dispatch = useDispatch();
const flecks = useFlecks();
const ref = useRef();
const room = useRoom();
const selfEntity = useSelfEntity();
- const socket = useSocket();
- const [left, setLeft] = useState(0);
- const [top, setTop] = useState(0);
+ const [position, setPosition] = useState([0, 0]);
const [domScale, setDomScale] = useState([1, 1]);
+ // Handle camera changes.
useEffect(() => {
if (!room || !selfEntity) {
return undefined;
}
+ // Initial snap camera to position.
selfEntity.camera.realPosition = selfEntity.camera.position;
const onCameraRealOffsetChanged = () => {
- const [left, top] = Vector.scale(selfEntity.camera.realOffset, -1);
- const {resolution} = flecks.get('@humus/app');
- setDomScale(Vector.div(resolution, selfEntity.camera.viewSize));
- setLeft(left);
- setTop(top);
+ setPosition(Vector.scale(selfEntity.camera.realOffset, -1));
+ };
+ const onCameraViewSizeChanged = () => {
+ setDomScale(Vector.div(flecks.get('@humus/app.resolution'), selfEntity.camera.viewSize));
};
onCameraRealOffsetChanged();
+ onCameraViewSizeChanged();
selfEntity.camera.on('realOffsetChanged', onCameraRealOffsetChanged);
+ selfEntity.camera.on('viewSizeChanged', onCameraViewSizeChanged);
return () => {
- const {camera} = selfEntity || {};
+ const {camera} = selfEntity;
if (camera) {
- camera.off('realOffsetChanged', onCameraRealOffsetChanged);
+ camera.off('realOffsetChanged', onCameraViewSizeChanged);
+ camera.off('viewSizeChanged', onCameraViewSizeChanged);
}
};
}, [flecks, room, selfEntity]);
+ // Focus.
useEffect(() => {
- const join = async () => {
- dispatch(setSelfEntity(await socket.send(['Join'])));
- };
- join();
- socket.on('reconnect', join);
- return () => {
- socket.off('reconnect', join);
- };
- }, [dispatch, socket]);
- useEffect(() => {
- if (!ref.current || !selfEntity) {
- return undefined;
+ if (ref.current) {
+ ref.current.focus();
}
- const inputNormalizer = new InputNormalizer();
- inputNormalizer.listen(window.document.body);
- selfEntity.listenForInput(inputNormalizer);
- selfEntity.actionRegistry.setTransformerFor('UseItem', (type, value) => {
- switch (type) {
- case 'joystick':
- return value === 0 ? -1 : selfEntity.activeSlotIndex;
- case 'buttonPress':
- case 'keyDown':
- return selfEntity.activeSlotIndex;
- default:
- return -1;
- }
- });
- const inputHandle = setInterval(() => {
- const actionStream = selfEntity.drainInput();
- if (actionStream.length > 0) {
- socket.send(['Input', actionStream]);
- }
- }, 1000 / 60);
- ref.current.focus();
- return () => {
- clearInterval(inputHandle);
- };
- }, [selfEntity, socket]);
+ });
return (
-
-
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
+
+
{selfEntity && }
);
diff --git a/packages/app/src/components/app/play/ui/index.scss b/packages/app/src/components/app/play/ui/index.scss
deleted file mode 100644
index e69de29..0000000