From c72f0a09847a5fcc5c0f300fe8fed1d4555d95c5 Mon Sep 17 00:00:00 2001 From: Obique Date: Thu, 14 May 2020 10:19:03 -0400 Subject: [PATCH] Fixed Issue #48: "Creating waypoints for specific coordinates doesnt apply correct coordinates" --- .../callbacks/WaypointCmdCallback.java | 199 ------------------ .../commands/callbacks/WaypointCmdCallback.kt | 131 ++++++++++++ 2 files changed, 131 insertions(+), 199 deletions(-) delete mode 100644 src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.kt diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java deleted file mode 100644 index 4e80e87e8..000000000 --- a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java +++ /dev/null @@ -1,199 +0,0 @@ -/*********************************************************************************** - * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * - * * - * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * - * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * - * Our goal is to create an emulator which will provide a server for players to * - * continue playing a game similar to the one they used to play. We are basing * - * it on the final publish of the game prior to end-game events. * - * * - * This file is part of Holocore. * - * * - * --------------------------------------------------------------------------------* - * * - * Holocore is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * Holocore is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with Holocore. If not, see . * - ***********************************************************************************/ -package com.projectswg.holocore.resources.support.global.commands.callbacks; - -import com.projectswg.common.data.encodables.oob.waypoint.WaypointColor; -import com.projectswg.common.data.location.Location; -import com.projectswg.common.data.location.Location.LocationBuilder; -import com.projectswg.common.data.location.Terrain; -import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent; -import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent; -import com.projectswg.holocore.resources.support.global.commands.ICmdCallback; -import com.projectswg.holocore.resources.support.global.player.Player; -import com.projectswg.holocore.resources.support.objects.ObjectCreator; -import com.projectswg.holocore.resources.support.objects.swg.SWGObject; -import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject; -import com.projectswg.holocore.resources.support.objects.swg.player.PlayerObject; -import com.projectswg.holocore.resources.support.objects.swg.waypoint.WaypointObject; -import org.jetbrains.annotations.NotNull; - -public class WaypointCmdCallback implements ICmdCallback { - - @Override - public void execute(@NotNull Player player, SWGObject target, @NotNull String args) { - PlayerObject ghost = player.getPlayerObject(); - if (ghost == null) - return; - - String[] cmdArgs = args.split(" "); - - WaypointColor color = WaypointColor.BLUE; - Terrain terrain = null; - String name = null; - float x = Float.NaN; - float z = Float.NaN; - - // Validate parameters, format for proper command arguments as it's split at whitespace - for (int i = 0; i < cmdArgs.length; i++) { - switch(i) { - // This could be either for just a named waypoint at current spot (1 param) or a planet arg (6 param) - case 0: - if (Terrain.getTerrainFromName(cmdArgs[0]) != null) { - // Terrain's name could also be part of the waypoint name, check to see if next few args are coords - try { - if (cmdArgs.length > 2) { - x = Float.parseFloat(cmdArgs[1]); - z = Float.parseFloat(cmdArgs[2]); // Just to be sure.. Maybe someone wanted some numbers in the name. - if (cmdArgs.length != 6) - cmdArgs = args.split(" ", 6); - } - } catch (NumberFormatException e) { - // This is just a named waypoint. - cmdArgs = new String[]{args}; - } - } else { - // This is just a named waypoint. - cmdArgs = new String[]{args}; - } - break; - // This could be either for a name (3 param) or a z coordinate (6 param) - case 3: - try { - z = Float.parseFloat(cmdArgs[3]); - // Ensure 100% this is a 6 argument command as the first param MUST be the planet name - if (Terrain.getTerrainFromName(cmdArgs[0]) != null) - if (cmdArgs.length != 6) - cmdArgs = args.split(" ", 6); - else cmdArgs = args.split(" ", 4); - } catch (NumberFormatException e) { - // This is intended for a name, should be 4 params - cmdArgs = args.split(" ", 4); - } - break; - default: break; - } - } - - // Was there an error message saying the format was wrong? - - switch(cmdArgs.length) { - case 1: // name - name = cmdArgs[0]; - break; - case 2: // x y - x = floatValue(cmdArgs[0]); - if (Float.isNaN(x)) - break; - z = floatValue(cmdArgs[1]); - break; - case 3: // x y z - x = floatValue(cmdArgs[0]); - if (Float.isNaN(x)) - break; - //y = floatValue(cmdArgs[1]); - z = floatValue(cmdArgs[2]); - break; - case 4: // x y z name - x = floatValue(cmdArgs[0]); - if (Float.isNaN(x)) - break; - //y = floatValue(cmdArgs[1]); - z = floatValue(cmdArgs[2]); - if (Float.isNaN(z)) - break; - name = cmdArgs[3]; - break; - case 6: // planet x y z color name - terrain = Terrain.getTerrainFromName(cmdArgs[0]); - if (terrain == null) - break; - x = floatValue(cmdArgs[1]); - if (Float.isNaN(x)) - break; - //y = floatValue(cmdArgs[2]); - z = floatValue(cmdArgs[3]); - if (Float.isNaN(z)) - break; - color = WaypointColor.fromString(cmdArgs[4]); - name = cmdArgs[5]; - break; - default: - // Not a valid format for /waypoint command - return; - } - - CreatureObject creature = player.getCreatureObject(); - LocationBuilder location = Location.builder(creature.getWorldLocation()); - - if (!Float.isNaN(x)) - location.setX(x); - - if (!Float.isNaN(z)) - location.setZ(z); - - boolean differentPlanetMessage = false; - if (terrain != null) { - if (terrain != location.getTerrain()) { - location.setTerrain(terrain); - differentPlanetMessage = true; - } - } - - if (name == null || name.isEmpty()) - name = "Waypoint"; - - if (!ghost.addWaypoint(createWaypoint(color, name, location.build()))) - SystemMessageIntent.broadcastPersonal(player, "@base_player:too_many_waypoints"); - - if (differentPlanetMessage) { - new SystemMessageIntent(player, "Waypoint: New waypoint \""+ name + "\" created for location " - + terrain.getName() + " (" + String.format("%.0f", location.getX()) + ", " - + String.format("%.0f", location.getY()) + ", "+ String.format("%.0f", location.getZ()) + ')').broadcast(); - } else { - new SystemMessageIntent(player, "Waypoint: New waypoint \""+ name + "\" created for location (" - + String.format("%.0f", location.getX()) + ", "+ String.format("%.0f", location.getY()) - + ", "+ String.format("%.0f", location.getZ()) + ')').broadcast(); - } - } - - private WaypointObject createWaypoint(WaypointColor color, String name, Location location) { - WaypointObject waypoint = (WaypointObject) ObjectCreator.createObjectFromTemplate("object/waypoint/shared_waypoint.iff"); - waypoint.setPosition(location.getTerrain(), location.getX(), location.getY(), location.getZ()); - waypoint.setColor(color); - waypoint.setName(name); - new ObjectCreatedIntent(waypoint).broadcast(); - return waypoint; - } - - private float floatValue(String str) { - try { - return Float.parseFloat(str); - } catch (NumberFormatException | NullPointerException e) { - return Float.NaN; - } - } -} diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.kt b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.kt new file mode 100644 index 000000000..d15c10294 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.kt @@ -0,0 +1,131 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see //www.gnu.org/licenses/>. * + */ +package com.projectswg.holocore.resources.support.global.commands.callbacks + +import com.projectswg.common.data.encodables.oob.waypoint.WaypointColor +import com.projectswg.common.data.location.Location +import com.projectswg.common.data.location.Terrain +import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent +import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent +import com.projectswg.holocore.resources.support.global.commands.ICmdCallback +import com.projectswg.holocore.resources.support.global.player.Player +import com.projectswg.holocore.resources.support.objects.ObjectCreator +import com.projectswg.holocore.resources.support.objects.swg.SWGObject +import com.projectswg.holocore.resources.support.objects.swg.waypoint.WaypointObject +import me.joshlarson.jlcommon.log.Log +import java.util.* + +class WaypointCmdCallback : ICmdCallback { + override fun execute(player: Player, target: SWGObject?, args: String) { + val ghost = player.playerObject ?: return + val waypointParameters = EnumMap(Parameter::class.java) + var currentState = Parameter.INITIAL + var argumentIndex = -1 + while (argumentIndex < args.length) { + // If we're the last argument (NAME), parse the remainder of the args + val nextArgumentIndex = if (currentState == Parameter.COLOR) args.length else args.indexOf(' ', startIndex=argumentIndex+1) + // Grab the argument + val nextArgument = args.substring(argumentIndex+1, if (nextArgumentIndex == -1) args.length else nextArgumentIndex) + if (nextArgument.isEmpty()) { + argumentIndex = nextArgumentIndex + if (nextArgumentIndex == -1) + break + continue + } + + val nextArgumentParsed = nextArgument.toDoubleOrNull() + if (nextArgumentParsed == null) { + // Find the next state that is a string + val nextState = currentState.nextStates.firstOrNull { !it.float && it != Parameter.END } ?: break + waypointParameters[nextState] = nextArgument + currentState = nextState + } else { + // Find the next state that is a float + val nextState = currentState.nextStates.firstOrNull { it.float && it != Parameter.END } ?: break + waypointParameters[nextState] = nextArgumentParsed + currentState = nextState + } + if (nextArgumentIndex == -1) + break + argumentIndex = nextArgumentIndex + } + Log.d("Waypoint arguments: %s", waypointParameters) + if (!currentState.nextStates.contains(Parameter.END)) { + SystemMessageIntent.broadcastPersonal(player, "Failed to parse waypoint command!") + return + } + val color = when((waypointParameters[Parameter.COLOR] as String?)?.toLowerCase(Locale.US)) { + "white" -> WaypointColor.WHITE + "purple" -> WaypointColor.PURPLE + "green" -> WaypointColor.GREEN + "yellow" -> WaypointColor.YELLOW + "orange" -> WaypointColor.ORANGE + else -> WaypointColor.BLUE + } + val name = waypointParameters.getOrDefault(Parameter.NAME, "Waypoint") as String + val location = if (waypointParameters.containsKey(Parameter.Z)) + Location.builder() + .setTerrain(Terrain.getTerrainFromName(waypointParameters[Parameter.TERRAIN] as String)) + .setX(waypointParameters[Parameter.X] as Double) + .setZ(waypointParameters[Parameter.Z] as Double) + .setY(waypointParameters.getOrDefault(Parameter.Y, 0.0) as Double) + .build() + else + player.creatureObject.worldLocation + + if (!ghost.addWaypoint(createWaypoint(color, name, location))) SystemMessageIntent.broadcastPersonal(player, "@base_player:too_many_waypoints") + if (player.creatureObject.terrain != location.terrain) { + SystemMessageIntent(player, "Waypoint: New waypoint \"" + name + "\" created for location " + + location.terrain.getName() + " (" + String.format("%.0f", location.x) + ", " + + String.format("%.0f", location.y) + ", " + String.format("%.0f", location.z) + ')').broadcast() + } else { + SystemMessageIntent(player, "Waypoint: New waypoint \"" + name + "\" created for location (" + + String.format("%.0f", location.x) + ", " + String.format("%.0f", location.y) + ", " + String.format("%.0f", location.z) + ')').broadcast() + } + } + + private fun createWaypoint(color: WaypointColor, name: String, location: Location): WaypointObject { + val waypoint = ObjectCreator.createObjectFromTemplate("object/waypoint/shared_waypoint.iff") as WaypointObject + waypoint.setPosition(location.terrain, location.x, location.y, location.z) + waypoint.color = color + waypoint.name = name + ObjectCreatedIntent(waypoint).broadcast() + return waypoint + } + + private enum class Parameter(val float: Boolean, val nextStates: List) { + END (false, listOf()), + NAME (false, listOf(END)), + COLOR (false, listOf(NAME, END)), + Y (true, listOf(COLOR, END)), + Z (true, listOf(COLOR, Y, END)), + X (true, listOf(Z)), + TERRAIN (false, listOf(X)), + INITIAL (false, listOf(TERRAIN, X, END)); + } + +}