diff --git a/Canopy [BP]/scripts/main.js b/Canopy [BP]/scripts/main.js index 4953176..763709a 100644 --- a/Canopy [BP]/scripts/main.js +++ b/Canopy [BP]/scripts/main.js @@ -22,6 +22,7 @@ import 'src/commands/tick' import 'src/commands/changedimension' import 'src/commands/spawn' import 'src/commands/claimprojectiles' +import 'src/commands/track' // Script Events import 'src/commands/scriptevents/counter' diff --git a/Canopy [BP]/scripts/src/classes/EventTracker.js b/Canopy [BP]/scripts/src/classes/EventTracker.js new file mode 100644 index 0000000..a187d97 --- /dev/null +++ b/Canopy [BP]/scripts/src/classes/EventTracker.js @@ -0,0 +1,88 @@ +import { world } from '@minecraft/server'; + +class EventTracker { + constructor(eventName, isAfterEvent = true) { + this.beforeEvents = world.beforeEvents; + this.afterEvents = world.afterEvents; + this.eventName = eventName; + this.isAfterEvent = isAfterEvent; + this.callback = undefined; + this.count = 0; + this.isTracking = false; + this.setCallback(eventName, isAfterEvent); + } + + setCallback(eventName, isAfterEvent = true) { + if (isAfterEvent && this.afterEvents[eventName]) { + this.callback = this.afterEvents[eventName]; + } else if (this.beforeEvents[eventName]) { + this.callback = this.beforeEvents[eventName]; + } else { + throw new Error(`[EventTracker] Event ${eventName} not found. Could not create new tracker.`); + } + } + + updateDynamicProperty() { + const trackedEventsJSON = world.getDynamicProperty('trackedEvents'); + const trackedEvents = trackedEventsJSON ? JSON.parse(trackedEventsJSON) : []; + + let found = false; + for (let i = 0; i < trackedEvents.length; i++) { + if (trackedEvents[i].eventName === this.eventName && trackedEvents[i].isAfterEvent === this.isAfterEvent) { + if (this.isTracking) { + trackedEvents[i].count = this.count; + } else { + trackedEvents.splice(i, 1); + } + found = true; + break; + } + } + if (!found && this.isTracking) { + trackedEvents.push(this.getInfo()); + } + + world.setDynamicProperty('trackedEvents', JSON.stringify(trackedEvents)); + } + + start() { + this.isTracking = true; + this.callback.subscribe(this.increment.bind(this)); + this.updateDynamicProperty(); + } + + stop() { + this.isTracking = false; + this.callback.unsubscribe(this.increment.bind(this)); + this.updateDynamicProperty(); + } + + increment() { + this.count++; + this.updateDynamicProperty(); + } + + getCount() { + return this.count; + } + + setCount(count) { + this.count = count; + this.updateDynamicProperty(); + } + + reset() { + this.count = 0; + this.updateDynamicProperty(); + } + + getInfo() { + return { eventName: this.eventName, isAfterEvent: this.isAfterEvent, count: this.count }; + } + + getInfoString() { + return `§7${this.eventName}${this.isAfterEvent ? 'After' : 'Before'}Event:§f ${this.count}`; + } +} + +export default EventTracker; \ No newline at end of file diff --git a/Canopy [BP]/scripts/src/classes/HotbarManager.js b/Canopy [BP]/scripts/src/classes/HotbarManager.js index bd13ac2..1cd0186 100644 --- a/Canopy [BP]/scripts/src/classes/HotbarManager.js +++ b/Canopy [BP]/scripts/src/classes/HotbarManager.js @@ -5,7 +5,6 @@ class HotbarManager { this.player = player; let tableName = 'bar' + player.id.toString().substr(0, 9); this.itemDatabase = new SRCItemDatabase(tableName); - console.warn(`HotbarManager for ${player.id} created with table name ${tableName}`); } getActiveHotbarItems() { diff --git a/Canopy [BP]/scripts/src/commands/help.js b/Canopy [BP]/scripts/src/commands/help.js index efcda63..b5c9487 100644 --- a/Canopy [BP]/scripts/src/commands/help.js +++ b/Canopy [BP]/scripts/src/commands/help.js @@ -107,6 +107,7 @@ class HelpBook { this.helpPages[4].addItem('tick', './tick step [steps]', 'Allows the server to run at normal speed for the specified amount of steps.'); this.helpPages[4].addItem('tick', './tick reset', 'Resets the server tick speed to normal.'); + this.helpPages[4].addItem('trackevent', './trackevent [beforeEvent/afterEvent]', 'Toggles counting the specified event in the InfoDisplay.'); this.helpPages[4].addItem('warp', './warp tp ', 'Teleports you to a warp. (alias: ./w)'); this.helpPages[4].addItem('warp', './warp ', 'Adds or removes a warp. (alias: ./w)'); this.helpPages[4].addItem('warps', './warps', 'Lists all available warps.'); diff --git a/Canopy [BP]/scripts/src/commands/track.js b/Canopy [BP]/scripts/src/commands/track.js new file mode 100644 index 0000000..bb19cfd --- /dev/null +++ b/Canopy [BP]/scripts/src/commands/track.js @@ -0,0 +1,87 @@ +import { world } from '@minecraft/server'; +import EventTracker from 'src/classes/EventTracker'; +import Command from 'stickycore/command'; +import Utils from 'stickycore/utils'; + +const trackers = { + before: {}, + after: {} +}; + +world.afterEvents.worldInitialize.subscribe(() => { + const trackedEventsJSON = world.getDynamicProperty('trackedEvents') + const trackedEvents = trackedEventsJSON ? JSON.parse(trackedEventsJSON) : []; + for (const savedTracker of trackedEvents) { + const tracker = new EventTracker(savedTracker.eventName, savedTracker.isAfterEvent, savedTracker.count); + tracker.start(); + tracker.setCount(savedTracker.count); + trackers[savedTracker.isAfterEvent ? 'after' : 'before'][savedTracker.eventName] = tracker; + } +}); + +new Command() + .setName('trackevent') + .addArgument('string', 'eventName') + .addArgument('string', 'isAfterEvent') + .setCallback(trackCommand) + .build(); + +function trackCommand(sender, args) { + let { eventName, isAfterEvent } = args; + if (eventName === null) + return sender.sendMessage('§cUsage: ./trackevent [beforeEvent/afterEvent]'); + if (isAfterEvent == 'beforeEvent') + isAfterEvent = false; + else if (isAfterEvent == 'afterEvent' || isAfterEvent === null) + isAfterEvent = true; + else + return sender.sendMessage('§cUsage: ./trackevent [beforeEvent/afterEvent]'); + + if (alreadyTracking(eventName, isAfterEvent)) + stopTracking(sender, eventName, isAfterEvent); + else + startTracking(sender, eventName, isAfterEvent); +} + +function alreadyTracking(eventName, isAfterEvent) { + return (isAfterEvent && trackers.after[eventName]) || (!isAfterEvent && trackers.before[eventName]); +} + +function stopTracking(sender, eventName, isAfterEvent) { + if (!isValidEvent(sender, eventName, isAfterEvent)) + return; + const tracker = new EventTracker(eventName, isAfterEvent); + tracker.stop(); + delete trackers[isAfterEvent ? 'after' : 'before'][eventName]; + sender.sendMessage(`§7Stopped tracking ${eventName}${isAfterEvent ? 'After' : 'Before'}Event.`); + Utils.broadcastActionBar(`§7${sender.name} stopped tracking ${eventName}${isAfterEvent ? 'After' : 'Before'}Event.`, sender); +} + +function startTracking(sender, eventName, isAfterEvent) { + if (!isValidEvent(sender, eventName, isAfterEvent)) + return; + const tracker = new EventTracker(eventName, isAfterEvent); + tracker.start(); + trackers[isAfterEvent ? 'after' : 'before'][eventName] = tracker; + sender.sendMessage(`§7Tracking ${eventName}${isAfterEvent ? 'After' : 'Before'}Event.`); + Utils.broadcastActionBar(`§7${sender.name} started tracking ${eventName}${isAfterEvent ? 'After' : 'Before'}Event.`, sender); +} + +function isValidEvent(sender, eventName, isAfterEvent) { + if ((isAfterEvent && !world.afterEvents[eventName]) || (!isAfterEvent && !world.beforeEvents[eventName])) { + console.warn(eventName, isAfterEvent, world.afterEvents[eventName], world.beforeEvents[eventName]); + sender.sendMessage(`§cEvent ${eventName} not found in ${isAfterEvent ? 'afterEvents' : 'beforeEvents'}.`); + return false; + } + return true; +} + +function getAllTrackerInfo() { + return Object.values(trackers.before).map(tracker => tracker.getInfo()).concat(Object.values(trackers.after).map(tracker => tracker.getInfo())); +} + +function getAllTrackerInfoString() { + return Object.values(trackers.before).map(tracker => tracker.getInfoString()).concat(Object.values(trackers.after).map(tracker => tracker.getInfoString())); +} + +export { getAllTrackerInfo, getAllTrackerInfoString }; \ No newline at end of file diff --git a/Canopy [BP]/scripts/src/config/database.js b/Canopy [BP]/scripts/src/config/database.js index 341e52d..f43b5af 100644 --- a/Canopy [BP]/scripts/src/config/database.js +++ b/Canopy [BP]/scripts/src/config/database.js @@ -11,6 +11,7 @@ const infoDisplay = newDB([ 'worldDay', 'timeOfDay', 'moonPhase', + 'eventTrackers', 'hopperCounters', 'lookingAt', 'peekInventory', diff --git a/Canopy [BP]/scripts/src/features/InfoDisplay.js b/Canopy [BP]/scripts/src/features/InfoDisplay.js index ed1a9aa..98bc44e 100644 --- a/Canopy [BP]/scripts/src/features/InfoDisplay.js +++ b/Canopy [BP]/scripts/src/features/InfoDisplay.js @@ -5,6 +5,7 @@ import { DataTPS } from 'src/tps' import { Entities } from 'src/entities' import { LightLevel } from 'src/light' import { getInfoDisplayOutput } from 'src/commands/counter' +import { getAllTrackerInfoString } from 'src/commands/track'; system.runInterval(() => { const Players = world.getAllPlayers(); @@ -21,6 +22,7 @@ function InfoDisplay(player) { InfoText += parseLightAndEntities(player) InfoText += parseDayAndTime(player); InfoText += parseMoonPhaseAndSlimeChunk(player) + InfoText += parseEventTrackerInfo(player); InfoText += parseHopperCounters(player); InfoText += parseLookingAtAndPeek(player); @@ -105,6 +107,13 @@ function parseMoonPhaseAndSlimeChunk(player) { return output; } +function parseEventTrackerInfo(player) { + if (!player.getDynamicProperty('eventTrackers')) return ''; + let output = getAllTrackerInfoString().join('\n'); + if (output !== '') output += '\n'; + return output; +} + function parseHopperCounters(player) { if (!player.getDynamicProperty('hopperCounters')) return ''; return getInfoDisplayOutput();