refactor: input

This commit is contained in:
cha0s 2021-02-10 10:59:49 -06:00
parent b100b523f5
commit 28e5e9f56f
2 changed files with 103 additions and 11 deletions

View File

@ -1,6 +1,6 @@
import './index.scss'; import './index.scss';
import {ActionRegistry, InputNormalizer} from '@avocado/input'; import {InputNormalizer} from '@avocado/input';
import {setSelfEntity, useSelfEntity} from '@humus/core'; import {setSelfEntity, useSelfEntity} from '@humus/core';
import {useDispatch} from '@latus/redux'; import {useDispatch} from '@latus/redux';
import {useSocket} from '@latus/socket'; import {useSocket} from '@latus/socket';
@ -26,23 +26,18 @@ const Play = () => {
}; };
}, [dispatch, socket, uuid]); }, [dispatch, socket, uuid]);
useEffect(() => { useEffect(() => {
if (!ref.current) { if (!ref.current || !selfEntity) {
return undefined; return undefined;
} }
const inputNormalizer = new InputNormalizer(); const inputNormalizer = new InputNormalizer();
inputNormalizer.listen(window.document.body); inputNormalizer.listen(window.document.body);
const actionRegistry = new ActionRegistry(); selfEntity.listenForInput(inputNormalizer);
actionRegistry.setActionTransformerFor('UseItem', (type) => ( selfEntity.actionRegistry.setTransformerFor('UseItem', (type) => (
selfEntity && 'keyDown' === type ? selfEntity.activeSlotIndex : -1 'keyDown' === type ? selfEntity.activeSlotIndex : -1
)); ));
actionRegistry.listen(inputNormalizer);
const inputHandle = setInterval(() => { const inputHandle = setInterval(() => {
const inputStream = actionRegistry.drain(); const inputStream = selfEntity.drainInput();
if (inputStream.length > 0) { if (inputStream.length > 0) {
// Inject input.
if (selfEntity) {
selfEntity.inputStream = inputStream;
}
const sending = inputStream.filter(({action}) => { const sending = inputStream.filter(({action}) => {
if (action.match(/^HotbarSlot(\d)/)) { if (action.match(/^HotbarSlot(\d)/)) {
return false; return false;

View File

@ -2,6 +2,7 @@ import {
TickingPromise, TickingPromise,
} from '@avocado/core'; } from '@avocado/core';
import {Vector} from '@avocado/math'; import {Vector} from '@avocado/math';
import {ActionRegistry} from '@avocado/input';
import {Trait} from '@avocado/traits'; import {Trait} from '@avocado/traits';
import { import {
compose, compose,
@ -18,15 +19,85 @@ const decorate = compose(
// Input handling. // Input handling.
export default () => class Controllable extends decorate(Trait) { export default () => class Controllable extends decorate(Trait) {
#actionRegistry;
#itemPromise; #itemPromise;
#itemUseRequest = -1; #itemUseRequest = -1;
#queued = [];
constructor() { constructor() {
super(); super();
this.on('controllableMovementChanged', this.updateAnimation, this); this.on('controllableMovementChanged', this.updateAnimation, this);
} }
get actionRegistry() {
return this.#actionRegistry;
}
static defaultParams() {
return {
actions: {
HotbarSlot0: [
{type: 'key', index: '1'},
],
HotbarSlot1: [
{type: 'key', index: '2'},
],
HotbarSlot2: [
{type: 'key', index: '3'},
],
HotbarSlot3: [
{type: 'key', index: '4'},
],
HotbarSlot4: [
{type: 'key', index: '5'},
],
HotbarSlot5: [
{type: 'key', index: '6'},
],
HotbarSlot6: [
{type: 'key', index: '7'},
],
HotbarSlot7: [
{type: 'key', index: '8'},
],
HotbarSlot8: [
{type: 'key', index: '9'},
],
HotbarSlot9: [
{type: 'key', index: '0'},
],
HotbarSlotNext: [
{type: 'key', index: 'WheelDown'},
],
HotbarSlotPrevious: [
{type: 'key', index: 'WheelUp'},
],
MoveUp: [
{type: 'key', index: 'w'},
],
MoveLeft: [
{type: 'key', index: 'a'},
],
MoveDown: [
{type: 'key', index: 's'},
],
MoveRight: [
{type: 'key', index: 'd'},
],
UseItem: [
{type: 'key', index: 'ArrowLeft'},
{type: 'button', index: 0},
],
Interact: [
{type: 'key', index: 'e'},
],
},
};
}
static dependencies() { static dependencies() {
return [ return [
'Animated', 'Animated',
@ -36,6 +107,10 @@ export default () => class Controllable extends decorate(Trait) {
]; ];
} }
destroy() {
this.#actionRegistry.stopListening();
}
set inputStream(inputStream) { set inputStream(inputStream) {
for (let i = 0; i < inputStream.length; i++) { for (let i = 0; i < inputStream.length; i++) {
const {action, value} = inputStream[i]; const {action, value} = inputStream[i];
@ -76,9 +151,31 @@ export default () => class Controllable extends decorate(Trait) {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
this.entity.on('isMobileChanged', this.updateAnimation, this); this.entity.on('isMobileChanged', this.updateAnimation, this);
this.#actionRegistry = new ActionRegistry(this.params.actions);
}
methods() {
return {
drainInput: () => {
const drained = this.#queued;
this.#queued = [];
return drained;
},
listenForInput: (inputNormalizer) => {
this.#actionRegistry.listen(inputNormalizer);
},
};
} }
tick(elapsed) { tick(elapsed) {
if ('client' === process.env.SIDE) {
const drained = this.#actionRegistry.drain();
this.inputStream = drained;
this.#queued.push(...drained);
}
if (-1 !== this.#itemUseRequest && !this.#itemPromise) { if (-1 !== this.#itemUseRequest && !this.#itemPromise) {
this.#itemPromise = this.entity.useItemInSlot(this.#itemUseRequest); this.#itemPromise = this.entity.useItemInSlot(this.#itemUseRequest);
Promise.resolve(this.#itemPromise).then(() => { Promise.resolve(this.#itemPromise).then(() => {