const aClientSystem = client.registerSystem(0, 0); // Global variables let globalVars = {}; // A query to control fighters that need to be animated globalVars.animationQuery = {}; // Setup which events to listen for aClientSystem.initialize = function () { this.listenForEvent("minecraft:pick_hit_result_changed", (eventData) => this.onPick(eventData)); // Setup callback for when the player enters the world this.listenForEvent("minecraft:client_entered_world", (eventData) => this.onClientEnteredWorld(eventData)); // Setup callback for UI events from the custom screens this.listenForEvent("minecraft:ui_event", (eventData) => this.onUIMessage(eventData)); // Setup callback for the victory event from the server script this.listenForEvent("rpg_game:victory", (eventData) => this.onVictory(eventData)); // Setup callback for the loss event from the server script this.listenForEvent("rpg_game:loss", (eventData) => this.onLoss(eventData)); // Setup callback for the turn order event from the server script this.listenForEvent("rpg_game:update_turn_order", (eventData) => this.onUpdateTurnOrder(eventData)); // Setup callback to handle the on-hit animation from the server script this.listenForEvent("rpg_game:execute_on_hit_animation", (eventData) => this.onExecuteOnHitAnimation(eventData)); // Register a script only component to help control animations this.registerComponent("rpg_game:animation_controller", { counter: 0 }); // Register a query to get all fighters that have the custom component that helps control animations globalVars.animationQuery = this.registerQuery(); this.addFilterToQuery(globalVars.animationQuery, "rpg_game:animation_controller"); }; aClientSystem.update = function () { // Update all animating fighters this.UpdateAnimationState(); }; aClientSystem.onPick = function (eventData) { // Relay pick event to the server script to update the newest hovered target this.broadcastEvent("rpg_game:update_hovered_target", eventData); }; aClientSystem.onUpdateTurnOrder = function (turnOrderData) { // Package up the turn order data to send to the custom screen for display. // The data property requires a string. Turn an object into a string by using JSON.stringify() let uiEventData = { eventName: "UpdateTurnOrder", data: JSON.stringify(turnOrderData) }; // Send the event to the custom screen this.broadcastEvent("minecraft:send_ui_event", uiEventData); }; aClientSystem.onClientEnteredWorld = function (eventData) { // Client has entered the world, show the starting screen aClientSystem.broadcastEvent("minecraft:load_ui", {path:"rpg_game_start.html"}); // Notify the server script that the player has finished loading in. aClientSystem.broadcastEvent("rpg_game:client_entered_world", eventData); }; aClientSystem.onVictory = function (eventData) { // Server told us that the player won, remove the game screen and show the victory screen this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game.html"}); this.broadcastEvent("minecraft:load_ui", {path:"rpg_game_victory.html"}); }; aClientSystem.onLoss = function (eventData) { // Server told us that the player lost, remove the game screen and show the loss screen this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game.html"}); this.broadcastEvent("minecraft:load_ui", {path:"rpg_game_loss.html"}); }; aClientSystem.onUIMessage = function (eventData) { // UI engine sent us an event. if (eventData === "damageSingleTargetAbilityClicked" || eventData === "damageWholeTeamAbilityClicked" || eventData === "healSingleTargetAbilityClicked") { // An ability button was clicked. Send an ability clicked event to the server script this.broadcastEvent("rpg_game:ability_clicked", eventData); } else if (eventData === "rpg_game:click") { this.broadcastEvent("rpg_game:click", ""); } else if (eventData === "startPressed" || eventData === "restartPressed") { // Start or restart button was pressed on a screen. Start up the game. this.startGame(); } else if (eventData === "leavePressed") { // Leave button was pressed. Exit all custom screens and stop turn-based game. this.leaveGame(); } }; aClientSystem.startGame = function () { // Remove any screens we might have loaded this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game_start.html"}); this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game.html"}); this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game_loss.html"}); this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game_victory.html"}); // Load and show the game screen this.broadcastEvent("minecraft:load_ui", {path:"rpg_game.html"}); // Tell the server to start the game this.broadcastEvent("rpg_game:start", ""); }; aClientSystem.leaveGame = function () { // Remove any screens we might have loaded this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game_start.html"}); this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game.html"}); this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game_loss.html"}); this.broadcastEvent("minecraft:unload_ui", {path:"rpg_game_victory.html"}); // Tell the server to leave the game this.broadcastEvent("rpg_game:leave", ""); }; aClientSystem.onExecuteOnHitAnimation = function(fighter) { // Add a animation controller component to the fighter that was just hit // Used to track animation counters this.createComponent(fighter, "rpg_game:animation_controller"); }; aClientSystem.UpdateAnimationState = function () { // Get all currently animating fighters let animatedFighters = this.getEntitiesFromQuery(globalVars.animationQuery); // Update animation for (let index in animatedFighters) { let fighter = animatedFighters[index]; let molangComponent = this.getComponent(fighter, "minecraft:molang"); // Get the animation controller component that was added when the fighter was hit let animationComponent = this.getComponent(fighter, "rpg_game:animation_controller"); if (animationComponent.data.counter < 1) { // Increment counter and base the fighters animation on it animationComponent.data.counter += 0.03; molangComponent.data["variable.script_attacktime"] = animationComponent.data.counter; this.applyComponentChanges(fighter, animationComponent); } else { // Animation has finished. Reset the molang component. Remove the animation controller component from the fighter. molangComponent.data["variable.script_attacktime"] = 0; this.destroyComponent(fighter, "rpg_game:animation_controller"); } this.applyComponentChanges(fighter, molangComponent); } };