import { Block, ChatSendAfterEvent, ItemStack, ItemUseOnBeforeEvent, MolangVariableMap, Player, world, } from "@minecraft/server"; import { Vector3 } from "@minecraft/server"; import { Vector3Add, Vector3ToString, vector3 } from "../utils/vectorUtils"; import { spawnParticle } from "../utils/particleUtils"; import Pupeteer from "../pupeteer"; import Chalk from "../chalk"; // eslint-disable-next-line @typescript-eslint/no-namespace export namespace TrailMaker { export class Maker { currentTrail: Trail; log: Map = new Map(); selectedIndex: number = 0; //Line point1: Vector3 = vector3(0, 0, 0); point2: Vector3 = vector3(0, 0, 0); waitingForPoint2: boolean = false; OnChat(event: ChatSendAfterEvent) { if (event.message == "!trailWand") { let item: ItemStack = new ItemStack("minecraft:stick"); item.nameTag = "AddPoint"; Pupeteer.givePlayerItem(event.sender as Player, item); world.sendMessage("Thou shall have the Trailing Powah"); } if (event.message == "!trailDeleteWand") { let item: ItemStack = new ItemStack("minecraft:stick"); item.nameTag = "DeletePoint"; Pupeteer.givePlayerItem(event.sender as Player, item); world.sendMessage("Luke, i'm NOT your father"); } if (event.message == "!trailLineWand") { let item: ItemStack = new ItemStack("minecraft:stick"); item.nameTag = "AddLine"; Pupeteer.givePlayerItem(event.sender as Player, item); world.sendMessage(`This is where i draw the ${Chalk.red("Line")} >:(`); } if (event.message == "!trailExport") { this.Export(); } } OnItemUse(event: ItemUseOnBeforeEvent) { const currentItemHeld: ItemStack = event.itemStack; const blockInteracted: Block = event.block; const player: Player = event.source as Player; const oldLog = this.log.get(player.name)!; this.log.set(player.name, Date.now()); if (oldLog + 150 >= Date.now()) return; if (event.itemStack.typeId == "minecraft:stick" && event.itemStack.nameTag == "AddPoint") { let block = event.block; let pos = this.BlockToParticlePosition(block); world.sendMessage(`Added Point ${Vector3ToString(pos)}`); this.currentTrail.points.push(new Point(pos, this.currentTrail.currentPoint)); this.currentTrail.currentPoint++; Pupeteer.setActionBarTimed(`Added point ${this.currentTrail.currentPoint}`, 3); } if (event.itemStack.typeId == "minecraft:stick" && event.itemStack.nameTag == "DeletePoint") { let block = event.block; let pos = this.BlockToParticlePosition(block); let point = this.currentTrail.points.find((point) => Vector3ToString(point.position) == Vector3ToString(pos)); if (point) { this.currentTrail.points.splice(this.currentTrail.points.indexOf(point), 1); Pupeteer.setActionBarTimed(`Deleted point ${point.index}`, 3); } else { Pupeteer.setActionBarTimed(`No point found`, 3); } } if (event.itemStack.typeId == "minecraft:stick" && event.itemStack.nameTag == "AddLine") { world.sendMessage(`Waiting for point 2: ${this.waitingForPoint2}`); if (!this.waitingForPoint2) { // this.point1 = vector3(blockInteracted.location.x, blockInteracted.location.y, blockInteracted.location.z); this.point1 = this.BlockToParticlePosition(blockInteracted); this.waitingForPoint2 = true; Pupeteer.setActionBar("Select a second point"); world.sendMessage("Select a second point"); return; } else { this.point2 = this.BlockToParticlePosition(blockInteracted); //Calculate the blocks between these 2 points, andd add them to the trail //Assume point1 is the start, and point2 is the end let x1 = this.point1.x; let x2 = this.point2.x; let y1 = this.point1.y; let y2 = this.point2.y; let z1 = this.point1.z; let z2 = this.point2.z; //Find out what axis is the movement on, throw an error if it's on more than one axis let xDiff = Math.abs(x2 - x1); let yDiff = Math.abs(y2 - y1); let zDiff = Math.abs(z2 - z1); let axis = ""; if (xDiff > 0 && yDiff == 0 && zDiff == 0) { axis = "x"; } else if (xDiff == 0 && yDiff > 0 && zDiff == 0) { axis = "y"; } else if (xDiff == 0 && yDiff == 0 && zDiff > 0) { axis = "z"; } else { Pupeteer.setActionBarTimed("Invalid line", 3); return; } let start = 0; let end = 0; if (axis == "x") { start = Math.min(x1, x2); end = Math.max(x1, x2); } else if (axis == "y") { start = Math.min(y1, y2); end = Math.max(y1, y2); } else if (axis == "z") { start = Math.min(z1, z2); end = Math.max(z1, z2); } for (let i = start; i <= end; i++) { let pos = vector3(0, 0, 0); if (axis == "x") { pos = vector3(i, y1, z1); } else if (axis == "y") { pos = vector3(x1, i, z1); } else if (axis == "z") { pos = vector3(x1, y1, i); } this.currentTrail.points.push(new Point(pos, this.currentTrail.currentPoint)); this.currentTrail.currentPoint++; } this.waitingForPoint2 = false; Pupeteer.setActionBarTimed("Added line", 3); } } } Update() { this.currentTrail.points.forEach((point) => { spawnParticle(point.position, "minecraft:balloon_gas_particle", new MolangVariableMap()); }); } Export() { let output = ""; for (let i = 0; i < this.currentTrail.points.length; i++) { let point = this.currentTrail.points[i]; let actualPos = point.position; output += `{ index: ${point.index}, position: vector3(${actualPos.x}, ${actualPos.y}, ${actualPos.z}) },\n`; } console.warn(output); } private BlockToParticlePosition(block: Block): Vector3 { let pos = vector3(block.location.x, block.location.y, block.location.z); pos = Vector3Add(pos, vector3(0.5, 0, 0.5)); //If block is a slab or stair, offset by half a block let isHalfBlock = block.typeId.includes("slab") || block.typeId.includes("stair"); if (isHalfBlock) { pos = Vector3Add(pos, vector3(0, 0.5, 0)); } else { pos = Vector3Add(pos, vector3(0, 1.1, 0)); } return pos; } constructor() { this.currentTrail = new Trail(); } } class Trail { points: Point[] = []; currentPoint: number = 0; nextParticleTimer: number = 0; currentParticleCounter: number = 0; constructor() {} } class Point { position: Vector3; index: number; constructor(position: Vector3, index: number) { this.position = position; this.index = index; } } }