flexible instance movement
This commit is contained in:
@@ -1,35 +1,125 @@
|
||||
import { InputPermissionCategory, world, system } from "@minecraft/server";
|
||||
import { Outliner } from "../Outliner";
|
||||
import { MENU_ITEM } from "../../commands/construct";
|
||||
import { Vector } from "../../lib/Vector";
|
||||
import { PlayerMovement } from "../PlayerMovement";
|
||||
import { Builders } from "../Builder/Builders";
|
||||
|
||||
export class FlexibleInstanceMove {
|
||||
player;
|
||||
instance;
|
||||
outliner;
|
||||
currentInstanceLocation;
|
||||
runner = void 0;
|
||||
|
||||
constructor(instance, player) {
|
||||
this.instance = instance;
|
||||
this.player = player;
|
||||
this.tryBeginFlexibleMove();
|
||||
this.currentInstanceLocation = Vector.from(instance.getLocation().location);
|
||||
this.onPlayerUseItemBound = this.onPlayerUseItem.bind(this);
|
||||
this.onPlayerLeaveBound = this.onPlayerLeave.bind(this);
|
||||
this.tryStart();
|
||||
}
|
||||
|
||||
tryBeginFlexibleMove() {
|
||||
if (this.instance.isFlexMoving) {
|
||||
this.feedback('§cThis instance is already being moved.');
|
||||
tryStart() {
|
||||
if (this.instance.isFlexibleMoving()) {
|
||||
this.sendFeedback('§cThis instance is already being moved.');
|
||||
return;
|
||||
}
|
||||
this.beginFlexibleMove();
|
||||
this.start();
|
||||
}
|
||||
|
||||
start() {
|
||||
this.prepInstanceForMovement();
|
||||
this.prepPlayerForMovement();
|
||||
this.runner = system.runInterval(this.onFlexibleMovementTick.bind(this));
|
||||
}
|
||||
|
||||
beginFlexibleMove() {
|
||||
// place structure in movement mode
|
||||
this.instance.startFlexibleMove(this.player);
|
||||
// lock player controls
|
||||
// start handling player movement controls
|
||||
prepInstanceForMovement() {
|
||||
this.instance.flexMovingPlayerId = this.player.id;
|
||||
this.instance.disable();
|
||||
const bounds = this.instance.getBounds();
|
||||
const maxWorldLocation = this.currentInstanceLocation.add(Vector.from(bounds.max));
|
||||
this.outliner = new Outliner(this.instance.getDimension(), this.currentInstanceLocation, maxWorldLocation, 1, 1);
|
||||
this.outliner.startDraw();
|
||||
}
|
||||
|
||||
endFlexibleMove() {
|
||||
this.instance.stopFlexibleMove();
|
||||
prepPlayerForMovement() {
|
||||
this.allowPlayerMovement(false);
|
||||
world.beforeEvents.itemUse.subscribe(this.onPlayerUseItemBound);
|
||||
world.beforeEvents.playerLeave.unsubscribe(this.onPlayerLeaveBound);
|
||||
this.sendFeedback(`§aNow moving "${this.instance.getName()}". Use the Construct item when finished.`);
|
||||
}
|
||||
|
||||
feedback(str) {
|
||||
this.player.sendMessage(str);
|
||||
onFlexibleMovementTick() {
|
||||
const playerMovement = new PlayerMovement(this.player);
|
||||
const instanceVelocity = this.calculateInstanceMovement(playerMovement);
|
||||
this.move(instanceVelocity);
|
||||
}
|
||||
|
||||
calculateInstanceMovement(playerMovement) {
|
||||
const speedFactor = 0.5;
|
||||
|
||||
const viewDir = playerMovement.getMajorDirectionFacing();
|
||||
const forward = new Vector(viewDir.x, viewDir.y, viewDir.z);
|
||||
const right = new Vector(forward.z, 0, -forward.x);
|
||||
const moveInput = playerMovement.getMovementVector();
|
||||
let velocity = forward.multiply(moveInput.y).add(right.multiply(moveInput.x));
|
||||
|
||||
if (playerMovement.isJumping())
|
||||
velocity.y += 1;
|
||||
if (playerMovement.isSneaking())
|
||||
velocity.y -= 1;
|
||||
|
||||
if (velocity.length > 0)
|
||||
velocity = velocity.normalized;
|
||||
return velocity.multiply(speedFactor);
|
||||
}
|
||||
|
||||
move(instanceVelocity) {
|
||||
this.currentInstanceLocation = this.currentInstanceLocation.add(instanceVelocity);
|
||||
this.moveOutline();
|
||||
}
|
||||
|
||||
moveOutline() {
|
||||
const bounds = this.instance.getBounds();
|
||||
const minWorldLocation = this.currentInstanceLocation.floor()
|
||||
const maxWorldLocation = minWorldLocation.add(Vector.from(bounds.max));
|
||||
this.outliner.setVertices(this.instance.getDimension(), minWorldLocation, maxWorldLocation);
|
||||
}
|
||||
|
||||
onPlayerUseItem(event) {
|
||||
if (!event.source || event.itemStack?.typeId !== MENU_ITEM) return;
|
||||
event.cancel = true;
|
||||
system.run(() => this.finish());
|
||||
}
|
||||
|
||||
onPlayerLeave(event) {
|
||||
if (event.player?.id === this.player.id)
|
||||
system.run(() => this.finish());
|
||||
}
|
||||
|
||||
finish() {
|
||||
system.clearRun(this.runner);
|
||||
this.outliner.stopDraw();
|
||||
this.outliner = void 0;
|
||||
this.instance.move(this.instance.getDimension().id, this.currentInstanceLocation);
|
||||
this.instance.enable();
|
||||
this.instance.flexMovingPlayerId = void 0;
|
||||
this.allowPlayerMovement(true);
|
||||
const builder = Builders.get(this.player.id);
|
||||
builder.flexibleInstanceMovement = void 0;
|
||||
world.beforeEvents.itemUse.unsubscribe(this.onPlayerUseItemBound);
|
||||
world.beforeEvents.playerLeave.unsubscribe(this.onPlayerLeaveBound);
|
||||
this.sendFeedback(`§aMoved "${this.instance.getName()}" to ${this.currentInstanceLocation.floor()}.`);
|
||||
}
|
||||
|
||||
allowPlayerMovement(enable) {
|
||||
const inputPermissions = this.player.inputPermissions;
|
||||
inputPermissions.setPermissionCategory(InputPermissionCategory.Movement, enable);
|
||||
}
|
||||
|
||||
sendFeedback(message) {
|
||||
system.run(() => this.player.onScreenDisplay.setActionBar(message));
|
||||
}
|
||||
}
|
||||
|
||||
// if the player logs out, stop the move
|
||||
@@ -5,6 +5,7 @@ import { InstanceButtons } from '../Enums/InstanceButtons';
|
||||
import { InstanceFormBuilder } from './InstanceFormBuilder';
|
||||
import { FormCancelationReason } from '@minecraft/server-ui';
|
||||
import { FlexibleInstanceMove } from './FlexibleInstanceMove';
|
||||
import { Builders } from '../Builder/Builders';
|
||||
|
||||
export class InstanceForm {
|
||||
instanceName;
|
||||
@@ -13,6 +14,7 @@ export class InstanceForm {
|
||||
InstanceButtons.NextLayer,
|
||||
InstanceButtons.PreviousLayer,
|
||||
InstanceButtons.Move,
|
||||
InstanceButtons.FlexibleMove,
|
||||
InstanceButtons.Settings,
|
||||
InstanceButtons.Statistics,
|
||||
InstanceButtons.Materials,
|
||||
@@ -96,7 +98,7 @@ export class InstanceForm {
|
||||
this.instance.move(this.player.dimension.id, this.player.location);
|
||||
break;
|
||||
case InstanceButtons.FlexibleMove:
|
||||
new FlexibleInstanceMove(this.instance, this.player);
|
||||
this.flexibleMovement();
|
||||
break;
|
||||
case InstanceButtons.Settings:
|
||||
this.settingsForm();
|
||||
@@ -135,6 +137,11 @@ export class InstanceForm {
|
||||
});
|
||||
}
|
||||
|
||||
flexibleMovement() {
|
||||
const builder = Builders.get(this.player.id);
|
||||
builder.flexibleInstanceMovement = new FlexibleInstanceMove(this.instance, this.player);
|
||||
}
|
||||
|
||||
setLayerForm() {
|
||||
InstanceFormBuilder.buildSetLayer(this.instance.getBounds().max.y, this.instance.getLayer()).show(this.player).then((response) => {
|
||||
if (response.canceled)
|
||||
|
||||
@@ -246,19 +246,6 @@ export class StructureInstance {
|
||||
this.setLayer(this.options.currentLayer - 1);
|
||||
}
|
||||
|
||||
startFlexibleMove(player) {
|
||||
this.flexMovingPlayerId = player.id;
|
||||
this.disable();
|
||||
// create flex movement outliner
|
||||
}
|
||||
|
||||
stopFlexibleMove(finalLocation) {
|
||||
// disable flex movement outliner
|
||||
this.move(this.getDimension(), finalLocation);
|
||||
this.enable();
|
||||
this.flexMovingPlayerId = void 0;
|
||||
}
|
||||
|
||||
isFlexibleMoving() {
|
||||
return this.flexMovingPlayerId !== void 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user