From 1aa87584171fd36d9e52e5d46cbc7547a70a5c16 Mon Sep 17 00:00:00 2001 From: george112n Date: Thu, 7 Sep 2023 12:59:39 +0100 Subject: [PATCH 01/18] Creates a base for the new location step menu --- .../locationcreatemenus/StepEditorMenu.java | 48 +++++++++++++++++++ .../newlocation/NewLocation.java | 2 + .../teachingtutorials/tutorials/Step.java | 15 +++++- 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java diff --git a/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java b/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java new file mode 100644 index 0000000..72ffccb --- /dev/null +++ b/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java @@ -0,0 +1,48 @@ +package teachingtutorials.guis.locationcreatemenus; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextDecoration; +import teachingtutorials.TeachingTutorials; +import teachingtutorials.guis.Gui; +import teachingtutorials.tutorials.Step; +import teachingtutorials.utils.User; + +/** + * A menu accessible to a creator when creating a new location, used to set the step instructions, + * the step start location and the hologram location of whatever step the creator is currently at + */ +public class StepEditorMenu extends Gui +{ + private static final int iInvSize = 3 * 9; + private final TeachingTutorials plugin; + private final User user; + private final Step step; + + public StepEditorMenu(TeachingTutorials plugin, User user, Step step) + { + super(iInvSize, getName(step.getName())); + this.plugin = plugin; + this.user = user; + this.step = step; + + setItems(); + } + + public void setItems() + { + } + + public static Component getName(String szStepName) + { + Component inventoryName = Component.text("Step - " +szStepName, Style.style(TextDecoration.BOLD, NamedTextColor.DARK_AQUA)); + return inventoryName; + } + + @Override + public void refresh() + { + + } +} diff --git a/src/main/java/teachingtutorials/newlocation/NewLocation.java b/src/main/java/teachingtutorials/newlocation/NewLocation.java index fb31c2d..55af026 100644 --- a/src/main/java/teachingtutorials/newlocation/NewLocation.java +++ b/src/main/java/teachingtutorials/newlocation/NewLocation.java @@ -17,6 +17,7 @@ import teachingtutorials.TeachingTutorials; import teachingtutorials.TutorialPlaythrough; import teachingtutorials.fundamentalTasks.GeometricUtils; +import teachingtutorials.guis.MainMenu; import teachingtutorials.listeners.Falling; import teachingtutorials.newlocation.elevation.ElevationManager; import teachingtutorials.tutorials.Location; @@ -352,6 +353,7 @@ public void terminateEarly() case inputtingAnswers: //Performs common playthrough termination processes super.commonEndPlaythrough(); + creatorOrStudent.mainGui = new MainMenu(plugin, creatorOrStudent); //Delete the location in the DB if(Location.deleteLocationByID(location.getLocationID())) diff --git a/src/main/java/teachingtutorials/tutorials/Step.java b/src/main/java/teachingtutorials/tutorials/Step.java index ddc9c21..a83413e 100644 --- a/src/main/java/teachingtutorials/tutorials/Step.java +++ b/src/main/java/teachingtutorials/tutorials/Step.java @@ -6,8 +6,10 @@ import org.bukkit.entity.Player; import teachingtutorials.TeachingTutorials; import teachingtutorials.fundamentalTasks.TpllListener; +import teachingtutorials.guis.locationcreatemenus.StepEditorMenu; import teachingtutorials.utils.Display; import teachingtutorials.utils.Hologram; +import teachingtutorials.utils.User; import java.sql.ResultSet; import java.sql.SQLException; @@ -30,7 +32,7 @@ public class Step private int iGroupInStepLocationCreation; private Group currentGroup; - //Handle multiple tasks being registered and the way they depend on ecahother + //Handle multiple tasks being registered and the way they depend on each other private boolean selectionCompleteHold; public ArrayList handledTpllListeners = new ArrayList<>(); public boolean bTpllDistanceMessageQueued; @@ -40,6 +42,8 @@ public class Step //Tasks in groups are completed synchronously public ArrayList groups = new ArrayList<>(); + private StepEditorMenu menu; + //Used for creating a step in a lesson public Step(int iStepID, int iStepInStage, String szStepName, Player player, TeachingTutorials plugin, Stage parentStage, String szStepInstructions, String szInstructionDisplayType) { @@ -53,6 +57,15 @@ public Step(int iStepID, int iStepInStage, String szStepName, Player player, Tea this.szStepInstructions = szStepInstructions; this.szInstructionDisplayType = szInstructionDisplayType; this.selectionCompleteHold = false; + + //Creates the menu + if (parentStage.bLocationCreation) + { + User user = parentStage.tutorialPlaythrough.getCreatorOrStudent(); + menu = new StepEditorMenu(plugin, user, this); + user.mainGui.delete(); + user.mainGui = menu; + } } //Used for adding a step to the DB From 99fd1708336eaf5c5b60017581d5d56fc9def477 Mon Sep 17 00:00:00 2001 From: george112n Date: Thu, 7 Sep 2023 13:22:38 +0100 Subject: [PATCH 02/18] Makes provisions for location specific data. --- .../tutorials/LocationStep.java | 23 +++++++++++++++++ .../teachingtutorials/tutorials/Step.java | 25 ++++++++++++++----- 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 src/main/java/teachingtutorials/tutorials/LocationStep.java diff --git a/src/main/java/teachingtutorials/tutorials/LocationStep.java b/src/main/java/teachingtutorials/tutorials/LocationStep.java new file mode 100644 index 0000000..d8ac405 --- /dev/null +++ b/src/main/java/teachingtutorials/tutorials/LocationStep.java @@ -0,0 +1,23 @@ +package teachingtutorials.tutorials; + +import teachingtutorials.utils.Hologram; + +/** + * Step data specific to a location + */ +public class LocationStep// extend step? +{ + //Data stored in the LocationSteps table in the DB + private double dStartLatitude; + private double dStartLongitude; + private String szInstructions; + private double dHologramLocationX; + private double dHologramLocationY; + private double dHologramLocationZ; + + public static LocationStep getFromStepAndLocation(int iStepID, int iLocationID) + { + //Accesses the DB and fetches the information about the step location + return new LocationStep(); + } +} diff --git a/src/main/java/teachingtutorials/tutorials/Step.java b/src/main/java/teachingtutorials/tutorials/Step.java index a83413e..48662cb 100644 --- a/src/main/java/teachingtutorials/tutorials/Step.java +++ b/src/main/java/teachingtutorials/tutorials/Step.java @@ -21,7 +21,6 @@ public class Step private String szName; private String szStepInstructions; private String szInstructionDisplayType; - private Hologram instructions; private Player player; private TeachingTutorials plugin; public Stage parentStage; @@ -29,6 +28,11 @@ public class Step protected int iStepID; protected int iStepInStage; + //Stores the location specific step data + private LocationStep locationStep; + + private Hologram instructions; + private int iGroupInStepLocationCreation; private Group currentGroup; @@ -44,7 +48,7 @@ public class Step private StepEditorMenu menu; - //Used for creating a step in a lesson + //Used for creating a step for a lesson public Step(int iStepID, int iStepInStage, String szStepName, Player player, TeachingTutorials plugin, Stage parentStage, String szStepInstructions, String szInstructionDisplayType) { this.player = player; @@ -54,17 +58,24 @@ public Step(int iStepID, int iStepInStage, String szStepName, Player player, Tea this.iStepID = iStepID; this.iStepInStage = iStepInStage; this.szName = szStepName; - this.szStepInstructions = szStepInstructions; this.szInstructionDisplayType = szInstructionDisplayType; this.selectionCompleteHold = false; - //Creates the menu if (parentStage.bLocationCreation) { + //Creates the menu User user = parentStage.tutorialPlaythrough.getCreatorOrStudent(); menu = new StepEditorMenu(plugin, user, this); user.mainGui.delete(); user.mainGui = menu; + + //Initialises location step + this.locationStep = new LocationStep(); + } + else + { + //Gets the location specific data + this.locationStep = LocationStep.getFromStepAndLocation(this.iStepID, this.parentStage.tutorialPlaythrough.getLocation().getLocationID()); } } @@ -72,8 +83,8 @@ public Step(int iStepID, int iStepInStage, String szStepName, Player player, Tea public Step(String szName, String szInstructionDisplayType, String szInstructions) { this.szName = szName; - this.szStepInstructions = szInstructions; this.szInstructionDisplayType = szInstructionDisplayType; + this.szStepInstructions = szInstructions; this.selectionCompleteHold = false; } @@ -82,10 +93,12 @@ public String getName() { return szName; } - public String getInstructions() + + /* public String getInstructions() { return szStepInstructions; } + */ public String getInstructionDisplayType() { From 3fdf39dfe3c18fcb63ed27bfbd3fc798b94095cb Mon Sep 17 00:00:00 2001 From: george112n Date: Thu, 7 Sep 2023 16:10:37 +0100 Subject: [PATCH 03/18] Slightly improves the height and position of the hologram. This is not a final solution but will help whilst the custom hologram position feature is developed. --- .../teachingtutorials/utils/Hologram.java | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/main/java/teachingtutorials/utils/Hologram.java b/src/main/java/teachingtutorials/utils/Hologram.java index 2640d21..842b393 100644 --- a/src/main/java/teachingtutorials/utils/Hologram.java +++ b/src/main/java/teachingtutorials/utils/Hologram.java @@ -21,33 +21,30 @@ public Hologram(Location location, Player player, String szTitle, String szText) @Override public void run() { - double[] xzAddition; + //Calculates the direction of the hologram from the player + double[] xzAddition = new double[2]; float fYaw = player.getLocation().getYaw(); - //Calculates where to move the hologram to based on the player's location - if (fYaw < -135 || fYaw > 135) - { - xzAddition = new double[]{0, -4.5}; - } - else if (fYaw < -45) - { - xzAddition = new double[]{4.5, 0}; - } - else if (fYaw > 45) - { - xzAddition = new double[]{-4.5, 0}; - } - else - { - xzAddition = new double[]{0, 4.5}; - } + xzAddition[0] = -4.5 * Math.sin(fYaw); + xzAddition[1] = 4.5 * Math.cos(fYaw); //Moves the hologram location.set(location.getX() +xzAddition[0], location.getY(), location.getZ() +xzAddition[1]); - //Raises or lowers the hologram - int iHeight = location.getWorld().getHighestBlockYAt(location.getBlockX(), location.getBlockZ()); - location.set(location.getX(), iHeight + 3.1, location.getZ()); + //Raises or lowers the hologram to be clear of the ground around the location + int iMaxHeight = location.getWorld().getHighestBlockYAt(location.getBlockX(), location.getBlockZ()); + int iHeight; + for (int i = - 1 ; i <= 1 ; i++) + { + for (int j = - 1 ; j <= 1 ; j++) + { + iHeight = location.getWorld().getHighestBlockYAt(location.getBlockX() + i, location.getBlockZ() + j); + if (iHeight > iMaxHeight) + iMaxHeight = iHeight; + } + } + + location.set(location.getX(), iMaxHeight + 3.1, location.getZ()); //Creates the hologram hologram = api.createHologram(location); From d635f41e2810264d5d409c56d5b85ff2fcf17b0b Mon Sep 17 00:00:00 2001 From: george112n Date: Fri, 8 Sep 2023 12:03:49 +0100 Subject: [PATCH 04/18] Slightly improves the height and position of the hologram. This is not a final solution but will help whilst the custom hologram position feature is developed. --- .../teachingtutorials/utils/Hologram.java | 127 +++++++++--------- 1 file changed, 61 insertions(+), 66 deletions(-) diff --git a/src/main/java/teachingtutorials/utils/Hologram.java b/src/main/java/teachingtutorials/utils/Hologram.java index 842b393..495972b 100644 --- a/src/main/java/teachingtutorials/utils/Hologram.java +++ b/src/main/java/teachingtutorials/utils/Hologram.java @@ -16,95 +16,90 @@ public class Hologram public Hologram(Location location, Player player, String szTitle, String szText) { //Performs the hologram creation synchronously - Bukkit.getScheduler().runTask(TeachingTutorials.getInstance(), new Runnable() - { - @Override - public void run() - { - //Calculates the direction of the hologram from the player - double[] xzAddition = new double[2]; - float fYaw = player.getLocation().getYaw(); + Bukkit.getScheduler().runTask(TeachingTutorials.getInstance(), () -> { + //Calculates the direction of the hologram from the player + double[] xzAddition = new double[2]; + float fYaw = player.getLocation().getYaw(); - xzAddition[0] = -4.5 * Math.sin(fYaw); - xzAddition[1] = 4.5 * Math.cos(fYaw); + xzAddition[0] = -4.5 * Math.sin((fYaw*Math.PI)/180); + xzAddition[1] = 4.5 * Math.cos((fYaw*Math.PI)/180); - //Moves the hologram - location.set(location.getX() +xzAddition[0], location.getY(), location.getZ() +xzAddition[1]); + //Moves the hologram + location.set(location.getX() +xzAddition[0], location.getY(), location.getZ() +xzAddition[1]); - //Raises or lowers the hologram to be clear of the ground around the location - int iMaxHeight = location.getWorld().getHighestBlockYAt(location.getBlockX(), location.getBlockZ()); - int iHeight; - for (int i = - 1 ; i <= 1 ; i++) + //Raises or lowers the hologram to be clear of the ground around the location + int iMaxHeight = location.getWorld().getHighestBlockYAt(location.getBlockX(), location.getBlockZ()); + int iHeight; + for (int i = - 1 ; i <= 1 ; i++) + { + for (int j = - 1 ; j <= 1 ; j++) { - for (int j = - 1 ; j <= 1 ; j++) - { - iHeight = location.getWorld().getHighestBlockYAt(location.getBlockX() + i, location.getBlockZ() + j); - if (iHeight > iMaxHeight) - iMaxHeight = iHeight; - } + iHeight = location.getWorld().getHighestBlockYAt(location.getBlockX() + i, location.getBlockZ() + j); + if (iHeight > iMaxHeight) + iMaxHeight = iHeight; } + } - location.set(location.getX(), iMaxHeight + 3.1, location.getZ()); + location.set(location.getX(), iMaxHeight + 3.1, location.getZ()); - //Creates the hologram - hologram = api.createHologram(location); + //Creates the hologram + hologram = api.createHologram(location); - Position position = hologram.getPosition(); + Position position = hologram.getPosition(); - //Inserts the text - hologram.getLines().appendText(szTitle); - String[] szWords = szText.split(" "); + //Inserts the text + hologram.getLines().appendText(szTitle); + String[] szWords = szText.split(" "); - String szLine = ""; - String szLineNew; - String szDisplayedText; + String szLine = ""; + String szLineNew; + String szDisplayedText; - for (int iWord = 0; iWord < szWords.length ; iWord++) + for (int iWord = 0; iWord < szWords.length ; iWord++) + { + szLineNew = szLine + szWords[iWord] +" "; + szDisplayedText = szLineNew.replace("&[A-Fa-f0-9]", ""); + if (szDisplayedText.length() > TeachingTutorials.getInstance().getConfig().getInt("Hologram_Max_Width") + 1) //Line is Hologram_Max_Width without the space { - szLineNew = szLine + szWords[iWord] +" "; - szDisplayedText = szLineNew.replace("&[A-Fa-f0-9]", ""); - if (szDisplayedText.length() > TeachingTutorials.getInstance().getConfig().getInt("Hologram_Max_Width") + 1) //Line is Hologram_Max_Width without the space + //Indicates that the line just added had one, >40 characters long word, so must display on a new line + if (szLine.equals("")) { - //Indicates that the line just added had one, >40 characters long word, so must display on a new line - if (szLine.equals("")) - { - //Adds the line to the hologram, removing the trailing space - hologram.getLines().appendText(szLineNew.substring(0, szLineNew.length() - 1)); - } - else //Indicates that the line already had some words in it so display those - { - //Adds the line to the hologram, removing the trailing space - hologram.getLines().appendText(szLine.substring(0, szLine.length() - 1)); - } - szLine = szWords[iWord] +" "; - if (iWord == szWords.length - 1) - { - hologram.getLines().appendText(szWords[iWord]); - } + //Adds the line to the hologram, removing the trailing space + hologram.getLines().appendText(szLineNew.substring(0, szLineNew.length() - 1)); } - else if (iWord == szWords.length - 1) + else //Indicates that the line already had some words in it so display those { - hologram.getLines().appendText(szLineNew); + //Adds the line to the hologram, removing the trailing space + hologram.getLines().appendText(szLine.substring(0, szLine.length() - 1)); } - else + szLine = szWords[iWord] +" "; + if (iWord == szWords.length - 1) { - szLine = szLineNew; + hologram.getLines().appendText(szWords[iWord]); } } - - Bukkit.getConsoleSender().sendMessage(hologram.getLines().size() +""); - //Shifts the hologram up if it is too tall - if (hologram.getLines().size() > 7) + else if (iWord == szWords.length - 1) + { + hologram.getLines().appendText(szLineNew); + } + else { - position = position.add(0, 0.2 * (hologram.getLines().size() - 7) , 0); - hologram.setPosition(position); + szLine = szLineNew; } + } - //Sets the visibility - VisibilitySettings visibilitySettings = hologram.getVisibilitySettings(); - visibilitySettings.setGlobalVisibility(VisibilitySettings.Visibility.HIDDEN); - visibilitySettings.setIndividualVisibility(player, VisibilitySettings.Visibility.VISIBLE); + Bukkit.getConsoleSender().sendMessage(hologram.getLines().size() +""); + //Shifts the hologram up if it is too tall + if (hologram.getLines().size() > 7) + { + position = position.add(0, 0.2 * (hologram.getLines().size() - 7) , 0); + hologram.setPosition(position); } + + //Sets the visibility + VisibilitySettings visibilitySettings = hologram.getVisibilitySettings(); + visibilitySettings.setGlobalVisibility(VisibilitySettings.Visibility.HIDDEN); + visibilitySettings.setIndividualVisibility(player, VisibilitySettings.Visibility.VISIBLE); }); } From 94f404618e8552e4c9ce40d31245fc74b3128093 Mon Sep 17 00:00:00 2001 From: george112n Date: Fri, 8 Sep 2023 12:05:19 +0100 Subject: [PATCH 05/18] Fixes a bug where the gui was deleted unnecessarily before being refreshed after toggling a tutorial in use. --- src/main/java/teachingtutorials/guis/CreatorTutorialsMenu.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/teachingtutorials/guis/CreatorTutorialsMenu.java b/src/main/java/teachingtutorials/guis/CreatorTutorialsMenu.java index d584e0c..d44823a 100644 --- a/src/main/java/teachingtutorials/guis/CreatorTutorialsMenu.java +++ b/src/main/java/teachingtutorials/guis/CreatorTutorialsMenu.java @@ -177,9 +177,7 @@ private void leftClicked(User u, int iSlot) { if (tutorials[iSlot].toggleInUse()) { - delete(); this.refresh(); - u.mainGui.open(u); } else { From aeac7500dcf8bf1220fd0e322cad2e1e9f744bec Mon Sep 17 00:00:00 2001 From: george112n Date: Fri, 8 Sep 2023 12:06:28 +0100 Subject: [PATCH 06/18] Adds provisions for step locations Now allows the safe location to be updated, and the object to be initialised without a safe location specified. --- .../java/teachingtutorials/listeners/Falling.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/teachingtutorials/listeners/Falling.java b/src/main/java/teachingtutorials/listeners/Falling.java index 7438f8e..6465f12 100644 --- a/src/main/java/teachingtutorials/listeners/Falling.java +++ b/src/main/java/teachingtutorials/listeners/Falling.java @@ -23,6 +23,17 @@ public Falling (Player player, Location safeLocation, TeachingTutorials plugin) this.plugin = plugin; } + public Falling (Player player, TeachingTutorials plugin) + { + this.player = player; + this.plugin = plugin; + } + + public void setSafeLocation(Location location) + { + this.safeLocation = location; + } + @EventHandler public void onClick(PlayerMoveEvent event) { From 7f1159436187cee490ed740c9a43aa41327e5631 Mon Sep 17 00:00:00 2001 From: george112n Date: Fri, 8 Sep 2023 12:06:58 +0100 Subject: [PATCH 07/18] Adds conversion method for minecraft to geometric coordinates. --- .../fundamentalTasks/GeometricUtils.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/teachingtutorials/fundamentalTasks/GeometricUtils.java b/src/main/java/teachingtutorials/fundamentalTasks/GeometricUtils.java index b6dcfb5..946fafa 100644 --- a/src/main/java/teachingtutorials/fundamentalTasks/GeometricUtils.java +++ b/src/main/java/teachingtutorials/fundamentalTasks/GeometricUtils.java @@ -58,8 +58,6 @@ public static double[] convertToMCCoordinates(double dLatitude, double dLongitud { double[] xz = null; - final GeographicProjection projection = EarthGeneratorSettings.parse(EarthGeneratorSettings.BTE_DEFAULT_SETTINGS).projection(); - try { xz = projection.fromGeo(dLongitude, dLatitude); @@ -71,6 +69,21 @@ public static double[] convertToMCCoordinates(double dLatitude, double dLongitud return xz; } + public static double[] convertToGeometricCoordinates(double X, double Z) + { + double[] longLat = null; + + try + { + longLat = projection.toGeo(X, Z); + } + catch (OutOfProjectionBoundsException e) + { + //Player has selected an area outside of the projection + } + return longLat; + } + public static boolean tpllPlayer(World world, double latitude, double longitude, Player player) { try From 430672b86ca47799a39d72127e37b9c9ff65573e Mon Sep 17 00:00:00 2001 From: george112n Date: Fri, 8 Sep 2023 12:09:18 +0100 Subject: [PATCH 08/18] Fixes a bug where /tutorials logic would be executed even if the event was cancelled in a lower priority handler. Also now just opens up the last accessed page when running /tutorials rather than always going to the main menu. --- .../listeners/GlobalPlayerCommandProcess.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java b/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java index 06e01f0..506df7d 100644 --- a/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java +++ b/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java @@ -44,6 +44,9 @@ public GlobalPlayerCommandProcess(TeachingTutorials plugin) @EventHandler(priority = EventPriority.LOW) public void commandEvent(PlayerCommandPreprocessEvent event) { + if (event.isCancelled()) + return; + //Extracts the player to a local variable Player player = event.getPlayer(); @@ -116,11 +119,12 @@ else if (command.startsWith("/tutorials") || command.startsWith("/learn")) User user = User.identifyUser(plugin, player); if (user != null) { - if (user.mainGui != null) - user.mainGui.delete(); - - user.mainGui = new MainMenu(plugin, user); user.mainGui.open(user); +// if (user.mainGui != null) +// user.mainGui.delete(); +// +// user.mainGui = new MainMenu(plugin, user); +// user.mainGui.open(user); } } } From 8fb256dadcc074b70fdc95715a7e9b458dacf248 Mon Sep 17 00:00:00 2001 From: george112n Date: Fri, 8 Sep 2023 12:11:11 +0100 Subject: [PATCH 09/18] Adds step start locations. Removes the Location start location. --- .../TutorialPlaythrough.java | 5 + .../locationcreatemenus/StepEditorMenu.java | 25 ++- .../newlocation/NewLocation.java | 16 +- .../teachingtutorials/tutorials/Lesson.java | 36 +--- .../teachingtutorials/tutorials/Location.java | 48 +---- .../tutorials/LocationStep.java | 189 +++++++++++++++++- .../teachingtutorials/tutorials/Step.java | 87 ++++++-- 7 files changed, 299 insertions(+), 107 deletions(-) diff --git a/src/main/java/teachingtutorials/TutorialPlaythrough.java b/src/main/java/teachingtutorials/TutorialPlaythrough.java index 32ee610..4827aa9 100644 --- a/src/main/java/teachingtutorials/TutorialPlaythrough.java +++ b/src/main/java/teachingtutorials/TutorialPlaythrough.java @@ -46,6 +46,11 @@ public User getCreatorOrStudent() return creatorOrStudent; } + public void setFallListenerSafeLocation(org.bukkit.Location location) + { + fallListener.setSafeLocation(location); + } + // Moves the tutorial on to the next stage // Accessed after the end of each stage (Called from Stage.endStage() asynchronously) // or at the start of the playthrough diff --git a/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java b/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java index 72ffccb..efa2d8c 100644 --- a/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java +++ b/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java @@ -4,10 +4,14 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; import teachingtutorials.TeachingTutorials; import teachingtutorials.guis.Gui; +import teachingtutorials.tutorials.LocationStep; import teachingtutorials.tutorials.Step; import teachingtutorials.utils.User; +import teachingtutorials.utils.Utils; /** * A menu accessible to a creator when creating a new location, used to set the step instructions, @@ -19,19 +23,38 @@ public class StepEditorMenu extends Gui private final TeachingTutorials plugin; private final User user; private final Step step; + private final LocationStep locationStep; - public StepEditorMenu(TeachingTutorials plugin, User user, Step step) + public StepEditorMenu(TeachingTutorials plugin, User user, Step step, LocationStep locationStep) { super(iInvSize, getName(step.getName())); this.plugin = plugin; this.user = user; this.step = step; + this.locationStep = locationStep; setItems(); } public void setItems() { + //Set start location coordinates to current location + ItemStack startLocation = Utils.createItem(Material.COMPASS, 1, + Component.text("Set the step's start location", NamedTextColor.GREEN), + Component.text("Set the start location to your current position and direction", NamedTextColor.DARK_GREEN)); + + setItem(11, startLocation, new guiAction() { + @Override + public void rightClick(User u) { + leftClick(u); + } + + @Override + public void leftClick(User u) { + locationStep.setStartLocation(u.player.getLocation()); + step.tryNextStep(); + } + }); } public static Component getName(String szStepName) diff --git a/src/main/java/teachingtutorials/newlocation/NewLocation.java b/src/main/java/teachingtutorials/newlocation/NewLocation.java index 55af026..e2920e2 100644 --- a/src/main/java/teachingtutorials/newlocation/NewLocation.java +++ b/src/main/java/teachingtutorials/newlocation/NewLocation.java @@ -12,7 +12,6 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.player.PlayerTeleportEvent; import teachingtutorials.TeachingTutorials; import teachingtutorials.TutorialPlaythrough; @@ -26,7 +25,6 @@ import teachingtutorials.utils.Display; import teachingtutorials.utils.Mode; import teachingtutorials.utils.User; -import teachingtutorials.utils.VirtualBlock; import teachingtutorials.utils.plugins.Multiverse; import teachingtutorials.utils.plugins.WorldGuard; @@ -203,13 +201,13 @@ public void AreaSelectionMade() } //Called from the StartLocationListener once the start location has been dictated - public void lessonStart(LatLng latLong) + public void lessonStart(LatLng startTP) { //Updates the stage this.stage = NewLocationProcess.creatingLocationForDB; //Creates a new location object - this.location = new Location(latLong, this.getTutorialID()); + this.location = new Location(this.getTutorialID(), true); //Adds the location to the database if (location.insertNewLocation()) @@ -281,7 +279,7 @@ public void lessonStart(LatLng latLong) @Override public void run() { try { - generateArea(world); + generateArea(world, startTP); } catch (OutOfProjectionBoundsException e) { @@ -296,10 +294,10 @@ public void run() { }); } - private void teleportCreatorAndStartLesson(World world) + private void teleportCreatorAndStartLesson(World world, LatLng startTP) { //Finds the start location - org.bukkit.Location tpLocation = GeometricUtils.convertToBukkitLocation(world, location.getStartCoordinates().getLat(), location.getStartCoordinates().getLng()); + org.bukkit.Location tpLocation = GeometricUtils.convertToBukkitLocation(world, startTP.getLat(), startTP.getLng()); //Registers the fall listener fallListener = new Falling(creatorOrStudent.player, tpLocation, plugin); @@ -389,7 +387,7 @@ protected void endPlaythrough() super.commonEndPlaythrough(); } - private void generateArea(World world) throws OutOfProjectionBoundsException + private void generateArea(World world, LatLng startTP) throws OutOfProjectionBoundsException { //UK121Generation(world); TerraMinusMinusGeneration(world); @@ -400,7 +398,7 @@ private void generateArea(World world) throws OutOfProjectionBoundsException Bukkit.getScheduler().runTask(plugin, new Runnable() { @Override public void run() { - teleportCreatorAndStartLesson(world); + teleportCreatorAndStartLesson(world, startTP); } }); } diff --git a/src/main/java/teachingtutorials/tutorials/Lesson.java b/src/main/java/teachingtutorials/tutorials/Lesson.java index 9926587..08a19ad 100644 --- a/src/main/java/teachingtutorials/tutorials/Lesson.java +++ b/src/main/java/teachingtutorials/tutorials/Lesson.java @@ -92,10 +92,6 @@ public void startLesson() //Attempts to resume the lesson if the student has a lesson that they need to complete if (resumeLesson()) { //If the lesson resumed successfully - //Registers the fall listener - fallListener = new Falling(creatorOrStudent.player, location.calculateBukkitStartLocation(), plugin); - fallListener.register(); - creatorOrStudent.currentMode = Mode.Doing_Tutorial; //Updates the user's current mode creatorOrStudent.bInLesson = true; //Updates the user's "In Lesson" status in RAM creatorOrStudent.setInLesson(1); //Updates the DB @@ -122,10 +118,6 @@ public void startLesson() addLessonToDB(); //There is currently no check to determine whether the DB creation worked - //Registers the fall listener - fallListener = new Falling(creatorOrStudent.player, location.calculateBukkitStartLocation(), plugin); - fallListener.register(); - //Updates the user's mode, "In Lesson" status in RAM, and "In Lesson" status in the DB creatorOrStudent.currentMode = Mode.Doing_Tutorial; creatorOrStudent.bInLesson = true; @@ -160,16 +152,6 @@ private boolean resumeLesson() +", Tutorial ID = " +this.tutorial.getTutorialID() +" and LocationID = "+this.location.getLocationID()); - //Teleports the player to the location's world - org.bukkit.Location tpLocation = location.calculateBukkitStartLocation(); - if (tpLocation == null) - { - creatorOrStudent.player.sendMessage(ChatColor.RED +"Could not teleport you to the start location"); - return false; - } - else - creatorOrStudent.player.teleport(tpLocation); - //Redisplays all virtual blocks for (int i = 0 ; i < iStageIndex ; i++) { @@ -182,6 +164,10 @@ private boolean resumeLesson() //Takes the stage position back for it to then be set forward again at the start of nextStage() iStageIndex = iStageIndex - 1; + //Registers the fall listener + fallListener = new Falling(creatorOrStudent.player, plugin); + fallListener.register(); + //Continues the current stage nextStage(iStepToStart); @@ -240,19 +226,13 @@ else if (bTutorialDetailsAlreadyEntered) +", Tutorial ID = " +this.tutorial.getTutorialID() +" and LocationID = "+this.location.getLocationID()); - //Teleports the student to the start location of the location - org.bukkit.Location tpLocation = location.calculateBukkitStartLocation(); - if (tpLocation == null) - { - creatorOrStudent.player.sendMessage(ChatColor.RED +"Could not teleport you to the start location"); - return false; - } - else - creatorOrStudent.player.teleport(tpLocation); - //Set the current stage to the first stage this.iStageIndex = 0; + //Registers the fall listener + fallListener = new Falling(creatorOrStudent.player, plugin); + fallListener.register(); + //Signals for the next stage (the first stage) to begin nextStage(1); } diff --git a/src/main/java/teachingtutorials/tutorials/Location.java b/src/main/java/teachingtutorials/tutorials/Location.java index e18e983..9b51eb7 100644 --- a/src/main/java/teachingtutorials/tutorials/Location.java +++ b/src/main/java/teachingtutorials/tutorials/Location.java @@ -1,8 +1,5 @@ package teachingtutorials.tutorials; -import net.buildtheearth.terraminusminus.generator.EarthGeneratorSettings; -import net.buildtheearth.terraminusminus.projection.GeographicProjection; -import net.buildtheearth.terraminusminus.util.geo.LatLng; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.World; @@ -15,7 +12,6 @@ public class Location { private int iLocationID; - private LatLng startCoordinates; private int iTutorialID; private float fDifficulty; private World world; @@ -25,9 +21,8 @@ public class Location //-------------------------------------------------- //Used for creating a new location - public Location(LatLng latlong, int iTutorialID) + public Location(int iTutorialID, boolean bNew) { - this.startCoordinates = latlong; this.iTutorialID = iTutorialID; } @@ -56,6 +51,8 @@ public int getLocationID() public World getWorld() { + if (world == null) + world = Bukkit.getWorld(iLocationID+""); return world; } @@ -64,11 +61,6 @@ public int getTutorialID() return iTutorialID; } - public LatLng getStartCoordinates() - { - return startCoordinates; - } - //--------------------------------------------------- //----------------------Setters---------------------- //--------------------------------------------------- @@ -78,33 +70,6 @@ public void setWorld(World world) this.world = world; } - //--------------------------------------------------- - //-----------------------Utils----------------------- - //--------------------------------------------------- - - public org.bukkit.Location calculateBukkitStartLocation() - { - double[] xz; - final GeographicProjection projection = EarthGeneratorSettings.parse(EarthGeneratorSettings.BTE_DEFAULT_SETTINGS).projection(); - - //Converts the longitude and latitude start coordinates of the location to minecraft coordinates - try - { - xz = projection.fromGeo(this.getStartCoordinates().getLng(), this.getStartCoordinates().getLat()); - //Declares location object - org.bukkit.Location tpLocation; - - tpLocation = new org.bukkit.Location(world, xz[0], world.getHighestBlockYAt((int) xz[0], (int) xz[1]) + 1, xz[1]); - return tpLocation; - } - catch (Exception e) - { - e.printStackTrace(); - Bukkit.getConsoleSender().sendMessage(ChatColor.RED +"Unable to convert lat,long coordinates of start location to minecraft coordinates"); - return null; - } - } - //--------------------------------------------------- //--------------------SQL Fetches-------------------- //--------------------------------------------------- @@ -130,12 +95,7 @@ private void fetchDetailsByLocationID() //Stores the information this.fDifficulty = resultSet.getFloat("Difficulty");; - double dLatitude = resultSet.getDouble("Latitude"); - double dLongitude = resultSet.getDouble("Longitude"); this.iTutorialID = resultSet.getInt("TutorialID"); - - //Puts the start coordinates into the LatLng object - this.startCoordinates = new LatLng(dLatitude, dLongitude); } catch (Exception e) { @@ -199,7 +159,7 @@ public boolean insertNewLocation() try { SQL = TeachingTutorials.getInstance().getConnection().createStatement(); - sql = "INSERT INTO Locations (TutorialID, Latitude, Longitude) VALUES (" +iTutorialID +", " +startCoordinates.getLat() +", " +startCoordinates.getLng() +")"; + sql = "INSERT INTO Locations (TutorialID) VALUES (" +iTutorialID+")"; Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +sql); iCount = SQL.executeUpdate(sql); diff --git a/src/main/java/teachingtutorials/tutorials/LocationStep.java b/src/main/java/teachingtutorials/tutorials/LocationStep.java index d8ac405..69e1323 100644 --- a/src/main/java/teachingtutorials/tutorials/LocationStep.java +++ b/src/main/java/teachingtutorials/tutorials/LocationStep.java @@ -1,23 +1,204 @@ package teachingtutorials.tutorials; -import teachingtutorials.utils.Hologram; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import teachingtutorials.TeachingTutorials; +import teachingtutorials.fundamentalTasks.GeometricUtils; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; /** - * Step data specific to a location + * Holds step data specific to a location and contains some procedures related to utilising this data */ public class LocationStep// extend step? { //Data stored in the LocationSteps table in the DB + private int iLocationID; + private int iStepID; + private double dStartLatitude; private double dStartLongitude; + private float fStartYaw; + private float fStartPitch; + private String szInstructions; private double dHologramLocationX; private double dHologramLocationY; private double dHologramLocationZ; + + + private boolean bLocationSet; + + public LocationStep(int iLocationID, int iStepID) + { + this.iLocationID = iLocationID; + this.iStepID = iStepID; + + bLocationSet = false; + } + + public boolean isLocationSet() + { + return bLocationSet; + } + + /** + * //Accesses the DB and fetches the information about the step location + * @param iStepID The step ID of the step + * @param iLocationID The location that is being played + * @return + */ public static LocationStep getFromStepAndLocation(int iStepID, int iLocationID) { - //Accesses the DB and fetches the information about the step location - return new LocationStep(); + LocationStep locationStep = new LocationStep(iLocationID, iStepID); + + String sql; + Statement SQL = null; + ResultSet resultSet = null; + + try + { + //Compiles the command to fetch the location step + sql = "Select * FROM LocationSteps WHERE Step = "+iStepID +" AND Location = " +iLocationID; + SQL = TeachingTutorials.getInstance().getConnection().createStatement(); + + //Executes the query + resultSet = SQL.executeQuery(sql); + if (resultSet.next()) + { + //Extracts and stores the data + locationStep.dStartLatitude = resultSet.getDouble("Latitude"); + locationStep.dStartLongitude = resultSet.getDouble("Longitude"); + locationStep.fStartYaw = resultSet.getFloat("StartYaw"); + locationStep.fStartPitch = resultSet.getFloat("StartPitch"); +// locationStep.szInstructions = resultSet.getString("Instructions"); +// locationStep.dHologramLocationX = resultSet.getDouble("InstructionsX"); +// locationStep.dHologramLocationY = resultSet.getDouble("InstructionsY"); +// locationStep.dHologramLocationZ = resultSet.getDouble("InstructionsZ"); + } + } + catch(SQLException se) + { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[TeachingTutorials] - SQL - SQL Error fetching Steps by StageID"); + se.printStackTrace(); + } + catch (Exception e) + { + e.printStackTrace(); + } + return locationStep; + } + + /** + * Adds the location step to the DB + */ + public boolean storeDetailsInDB() + { + String sql; + Statement SQL = null; + ResultSet resultSet = null; + + int iCount; + + try + { + SQL = TeachingTutorials.getInstance().getConnection().createStatement(); + sql = "INSERT INTO LocationSteps (Location, Step, Latitude, Longitude, StartYaw, StartPitch) VALUES (" + + iLocationID +", " + + iStepID +", " + + dStartLatitude +", " + + dStartLongitude +", " + + fStartYaw +", " + + fStartPitch + +")"; + Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +sql); + iCount = SQL.executeUpdate(sql); + + if (iCount != 1) + { + return false; + } + return true; + } + catch (SQLException se) + { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[TeachingTutorials] - SQL - SQL Error adding new location step"); + se.printStackTrace(); + return false; + } + catch (Exception e) + { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[TeachingTutorials] - SQL - Other error adding new location step"); + e.printStackTrace(); + return false; + } + } + + /** + * Teleports the player to the start of the step + * @param player The player to teleport + * @param world The world for the relevant location + * @return The start location of the step + */ + public Location teleportPlayerToStartOfStep(Player player, World world, TeachingTutorials plugin) + { + Location location = getStartLocation(world); + if (location != null) + { + //Teleports the player + Location finalLocation = location; + Bukkit.getScheduler().runTask(plugin, () -> player.teleport(finalLocation)); + } + else + location = player.getLocation(); + + return location; + } + + /** + * Sets the step start location + * @param location The location of the intended step start location + */ + public void setStartLocation(Location location) + { + double[] longLat = GeometricUtils.convertToGeometricCoordinates(location.getX(), location.getZ()); + + if (longLat != null) + { + this.dStartLongitude = longLat[0]; + this.dStartLatitude = longLat[1]; + + this.fStartPitch = location.getPitch(); + this.fStartYaw = location.getYaw(); + + bLocationSet = true; + } + else + { + + } + } + + /** + * + * @return The start location for the step as a bukkit object + */ + public Location getStartLocation(World world) + { + Location location = GeometricUtils.convertToBukkitLocation(world, dStartLatitude, dStartLongitude); + + if (location != null) + { + location.setY(location.getY() + 1); + location.setYaw(fStartYaw); + location.setPitch(fStartPitch); + } + return location; } } diff --git a/src/main/java/teachingtutorials/tutorials/Step.java b/src/main/java/teachingtutorials/tutorials/Step.java index 48662cb..0c86190 100644 --- a/src/main/java/teachingtutorials/tutorials/Step.java +++ b/src/main/java/teachingtutorials/tutorials/Step.java @@ -1,5 +1,7 @@ package teachingtutorials.tutorials; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -59,24 +61,15 @@ public Step(int iStepID, int iStepInStage, String szStepName, Player player, Tea this.iStepInStage = iStepInStage; this.szName = szStepName; this.szInstructionDisplayType = szInstructionDisplayType; + this.szStepInstructions = szStepInstructions; this.selectionCompleteHold = false; if (parentStage.bLocationCreation) - { - //Creates the menu - User user = parentStage.tutorialPlaythrough.getCreatorOrStudent(); - menu = new StepEditorMenu(plugin, user, this); - user.mainGui.delete(); - user.mainGui = menu; - //Initialises location step - this.locationStep = new LocationStep(); - } + this.locationStep = new LocationStep(parentStage.getLocationID(), iStepID); else - { //Gets the location specific data this.locationStep = LocationStep.getFromStepAndLocation(this.iStepID, this.parentStage.tutorialPlaythrough.getLocation().getLocationID()); - } } //Used for adding a step to the DB @@ -94,11 +87,10 @@ public String getName() return szName; } - /* public String getInstructions() + public String getInstructions() { return szStepInstructions; } - */ public String getInstructionDisplayType() { @@ -187,6 +179,10 @@ public void run() }, 2L); } + /** + * Starts the player on this step. Sends them the title of the step, registers the fall listener + * teleports them to the start, displays the instructions and initialises the groups of tasks + */ public void startStep() { //Display step title @@ -208,16 +204,27 @@ public void run() { display.Title(ChatColor.AQUA +"Step " +iStepInStage +" - " +szName, 10, 60, 12); } - //TP to location? + if (!parentStage.bLocationCreation) + { + //TP to start location, and store this location for later use + Location startLocation = locationStep.teleportPlayerToStartOfStep(player, parentStage.tutorialPlaythrough.getLocation().getWorld(), plugin); + + //Updates the fall listener + parentStage.tutorialPlaythrough.setFallListenerSafeLocation(startLocation); + } - //Displays the step instructions + //Displays the step instructions - location is based on the start location for now Location instructionLocation; if (iStepInStage == 1 && parentStage.isFirstStage()) { - instructionLocation = parentStage.tutorialPlaythrough.getLocation().calculateBukkitStartLocation(); + instructionLocation = locationStep.getStartLocation(parentStage.tutorialPlaythrough.getLocation().getWorld()); } else - instructionLocation = player.getLocation(); + { + instructionLocation = locationStep.getStartLocation(parentStage.tutorialPlaythrough.getLocation().getWorld()); + if (instructionLocation == null) + instructionLocation = player.getLocation(); + } switch (szInstructionDisplayType) { @@ -244,6 +251,13 @@ public void run() { iGroupInStepLocationCreation = 1; currentGroup.initialRegister(); Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] Registered group "+iGroupInStepLocationCreation +" of step"); + + //Creates the menu, assigns it to the user + User user = parentStage.tutorialPlaythrough.getCreatorOrStudent(); + menu = new StepEditorMenu(plugin, user, this, this.locationStep); + if (user.mainGui != null) + user.mainGui.delete(); + user.mainGui = menu; } else { @@ -273,10 +287,6 @@ protected void groupFinished() if (iGroupInStepLocationCreation == groups.size()) //If the current group is the last group { bAllGroupsFinished = true; - - //Remove hologram - if (szInstructionDisplayType.equals("hologram")) - instructions.removeHologram(); } else { @@ -308,6 +318,39 @@ protected void groupFinished() instructions.removeHologram(); this.bStepFinished = true; + + if (parentStage.bLocationCreation) + { + if (locationStep.isLocationSet()) + tryNextStep(); + else + { + Display display = new Display(player, Component.text("You must now set the step's start location. Use the learning menu", NamedTextColor.RED)); + display.Message(); + + //We wait and then perform the code in the if statement above once the location has been set, via tryNextStep() + } + } + else + { + parentStage.nextStep(); + } + } + } + + /** + * Will move the player on to the next step if the current step is finished. + * This is used if the creator finished the step answer submissions before setting the start location. + * This method has one use: it is called directly after the start location is set + */ + public void tryNextStep() + { + if (!parentStage.bLocationCreation) + return; + + if (bStepFinished) + { + locationStep.storeDetailsInDB(); parentStage.nextStep(); } } @@ -318,12 +361,14 @@ public void terminateEarly() if (szInstructionDisplayType.equals("hologram")) instructions.removeHologram(); + //Unregisters the current task listener if (parentStage.bLocationCreation) { currentGroup.terminateEarly(); Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +" [TeachingTutorials] Unregistered group "+iGroupInStepLocationCreation); } + //Unregisters the task listeners else { int i; From 23e3465718d0392138bf4a3415888c017ff3d658 Mon Sep 17 00:00:00 2001 From: george112n Date: Mon, 25 Sep 2023 15:00:08 +0100 Subject: [PATCH 10/18] Renamed FundamentalTask to FundamentalTaskType --- src/main/java/teachingtutorials/fundamentalTasks/Chat.java | 2 +- .../java/teachingtutorials/fundamentalTasks/Command.java | 2 +- .../{FundamentalTask.java => FundamentalTaskType.java} | 2 +- src/main/java/teachingtutorials/fundamentalTasks/Place.java | 2 +- .../java/teachingtutorials/fundamentalTasks/Selection.java | 2 +- .../teachingtutorials/fundamentalTasks/TpllListener.java | 6 +----- .../teachingtutorials/newlocation/DifficultyListener.java | 6 +++--- 7 files changed, 9 insertions(+), 13 deletions(-) rename src/main/java/teachingtutorials/fundamentalTasks/{FundamentalTask.java => FundamentalTaskType.java} (73%) diff --git a/src/main/java/teachingtutorials/fundamentalTasks/Chat.java b/src/main/java/teachingtutorials/fundamentalTasks/Chat.java index aa5e981..ffaf2a6 100644 --- a/src/main/java/teachingtutorials/fundamentalTasks/Chat.java +++ b/src/main/java/teachingtutorials/fundamentalTasks/Chat.java @@ -47,7 +47,7 @@ public Chat(TeachingTutorials plugin, Player player, Group parentGroup, int iTas this.szDetails = szDetails; //Listen out for difficulty - There will only be one difficulty listener per chat to avoid bugs - difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTask.chat); + difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTaskType.chat); difficultyListener.register(); } diff --git a/src/main/java/teachingtutorials/fundamentalTasks/Command.java b/src/main/java/teachingtutorials/fundamentalTasks/Command.java index 08c6fce..2c984c6 100644 --- a/src/main/java/teachingtutorials/fundamentalTasks/Command.java +++ b/src/main/java/teachingtutorials/fundamentalTasks/Command.java @@ -103,7 +103,7 @@ public Command(TeachingTutorials plugin, Player player, Group parentGroup, int i this.commandType = teachingtutorials.fundamentalTasks.commandType.valueOf(szDetails); //Listen out for difficulty - There will only be one difficulty listener per command to avoid bugs - difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTask.command); + difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTaskType.command); difficultyListener.register(); tasksInGroup = tasks; diff --git a/src/main/java/teachingtutorials/fundamentalTasks/FundamentalTask.java b/src/main/java/teachingtutorials/fundamentalTasks/FundamentalTaskType.java similarity index 73% rename from src/main/java/teachingtutorials/fundamentalTasks/FundamentalTask.java rename to src/main/java/teachingtutorials/fundamentalTasks/FundamentalTaskType.java index 6483039..4fe9bf7 100644 --- a/src/main/java/teachingtutorials/fundamentalTasks/FundamentalTask.java +++ b/src/main/java/teachingtutorials/fundamentalTasks/FundamentalTaskType.java @@ -1,6 +1,6 @@ package teachingtutorials.fundamentalTasks; -public enum FundamentalTask +public enum FundamentalTaskType { tpll, selection, command, place, chat } diff --git a/src/main/java/teachingtutorials/fundamentalTasks/Place.java b/src/main/java/teachingtutorials/fundamentalTasks/Place.java index b040338..c755f3f 100644 --- a/src/main/java/teachingtutorials/fundamentalTasks/Place.java +++ b/src/main/java/teachingtutorials/fundamentalTasks/Place.java @@ -67,7 +67,7 @@ public Place(TeachingTutorials plugin, Player player, Group parentGroup, int iTa this.szDetails = szDetails; //Listen out for difficulty - There will only be one difficulty listener per place task to avoid bugs - difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTask.tpll); + difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTaskType.tpll); difficultyListener.register(); } diff --git a/src/main/java/teachingtutorials/fundamentalTasks/Selection.java b/src/main/java/teachingtutorials/fundamentalTasks/Selection.java index 45845e3..cb03a90 100644 --- a/src/main/java/teachingtutorials/fundamentalTasks/Selection.java +++ b/src/main/java/teachingtutorials/fundamentalTasks/Selection.java @@ -86,7 +86,7 @@ public Selection(TeachingTutorials plugin, Player player, Group parentGroup, int this.bSelection2Made = false; //Listen out for difficulty - There will only be one difficulty listener per selection to avoid bugs - difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTask.selection); + difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTaskType.selection); difficultyListener.register(); } diff --git a/src/main/java/teachingtutorials/fundamentalTasks/TpllListener.java b/src/main/java/teachingtutorials/fundamentalTasks/TpllListener.java index e364661..d21dd23 100644 --- a/src/main/java/teachingtutorials/fundamentalTasks/TpllListener.java +++ b/src/main/java/teachingtutorials/fundamentalTasks/TpllListener.java @@ -1,8 +1,5 @@ package teachingtutorials.fundamentalTasks; -import net.buildtheearth.terraminusminus.generator.EarthGeneratorSettings; -import net.buildtheearth.terraminusminus.projection.GeographicProjection; -import net.buildtheearth.terraminusminus.projection.OutOfProjectionBoundsException; import net.buildtheearth.terraminusminus.util.geo.CoordinateParseUtils; import net.buildtheearth.terraminusminus.util.geo.LatLng; import org.bukkit.*; @@ -15,7 +12,6 @@ import teachingtutorials.TeachingTutorials; import teachingtutorials.newlocation.DifficultyListener; import teachingtutorials.tutorials.Group; -import teachingtutorials.tutorials.Location; import teachingtutorials.tutorials.LocationTask; import teachingtutorials.utils.Display; @@ -82,7 +78,7 @@ public TpllListener(TeachingTutorials plugin, Player player, Group parentGroup, this.szDetails = szDetails; //Listen out for difficulty - There will only be one difficulty listener per tpll command to avoid bugs - difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTask.tpll); + difficultyListener = new DifficultyListener(this.plugin, this.player, this, FundamentalTaskType.tpll); difficultyListener.register(); } diff --git a/src/main/java/teachingtutorials/newlocation/DifficultyListener.java b/src/main/java/teachingtutorials/newlocation/DifficultyListener.java index bfb9397..b62588e 100644 --- a/src/main/java/teachingtutorials/newlocation/DifficultyListener.java +++ b/src/main/java/teachingtutorials/newlocation/DifficultyListener.java @@ -9,7 +9,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import teachingtutorials.TeachingTutorials; -import teachingtutorials.fundamentalTasks.FundamentalTask; +import teachingtutorials.fundamentalTasks.FundamentalTaskType; import teachingtutorials.fundamentalTasks.Task; import teachingtutorials.tutorials.LocationTask; import teachingtutorials.utils.Display; @@ -21,10 +21,10 @@ public class DifficultyListener implements Listener Player player; LocationTask locationTask; Task task; - FundamentalTask taskType; + FundamentalTaskType taskType; boolean bReadyForDifficulty; - public DifficultyListener(TeachingTutorials plugin, Player player, Task task, FundamentalTask taskType) + public DifficultyListener(TeachingTutorials plugin, Player player, Task task, FundamentalTaskType taskType) { this.plugin = plugin; this.player = player; From 84332e96407a910761b7d74e34819363b1bea094 Mon Sep 17 00:00:00 2001 From: george112n Date: Mon, 25 Sep 2023 15:05:17 +0100 Subject: [PATCH 11/18] Adds a check to see whether the lesson started successfully before closing the menu which called it. If the lesson doesn't start successfully the menu will now remain open. --- .../compulsory/Compulsory.java | 4 +- .../teachingtutorials/guis/LibraryMenu.java | 6 +- .../java/teachingtutorials/guis/MainMenu.java | 67 ++++++++++--------- .../teachingtutorials/tutorials/Lesson.java | 9 ++- 4 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/main/java/teachingtutorials/compulsory/Compulsory.java b/src/main/java/teachingtutorials/compulsory/Compulsory.java index 0c7e78d..1530cb7 100644 --- a/src/main/java/teachingtutorials/compulsory/Compulsory.java +++ b/src/main/java/teachingtutorials/compulsory/Compulsory.java @@ -12,8 +12,8 @@ public Compulsory(TeachingTutorials plugin, User user) super(user, plugin, true); } - public void startLesson() + public boolean startLesson() { - super.startLesson(); + return super.startLesson(); } } diff --git a/src/main/java/teachingtutorials/guis/LibraryMenu.java b/src/main/java/teachingtutorials/guis/LibraryMenu.java index c5c9dd7..ac209c1 100644 --- a/src/main/java/teachingtutorials/guis/LibraryMenu.java +++ b/src/main/java/teachingtutorials/guis/LibraryMenu.java @@ -145,13 +145,13 @@ public void rightClick(User u) { @Override public void leftClick(User u) { - delete(); - //Creates a NewLocation object Lesson newLesson = new Lesson(user, plugin, tutorials[iSlot]); //Launches them into the new location adding process - newLesson.startLesson(); + if (newLesson.startLesson()) + delete(); + user.mainGui = null; } }); } diff --git a/src/main/java/teachingtutorials/guis/MainMenu.java b/src/main/java/teachingtutorials/guis/MainMenu.java index b1c0a02..a555197 100644 --- a/src/main/java/teachingtutorials/guis/MainMenu.java +++ b/src/main/java/teachingtutorials/guis/MainMenu.java @@ -68,10 +68,9 @@ public void rightClick(User u) @Override public void leftClick(User u) { - //Deletes this gui - delete(); - - performEvent(EventType.COMPULSORY, u, plugin); + if (performEvent(EventType.COMPULSORY, u, plugin)) + //Deletes this gui + delete(); } }); @@ -83,10 +82,9 @@ public void rightClick(User u) { } @Override public void leftClick(User u) { - //Deletes this gui - delete(); - - performEvent(EventType.LIBRARY, u, plugin); + if (performEvent(EventType.LIBRARY, u, plugin)) + //Deletes this gui + delete(); } }); @@ -100,10 +98,9 @@ public void rightClick(User u) @Override public void leftClick(User u) { - //Deletes this gui - delete(); - - performEvent(EventType.CONTINUE, u, plugin); + if (performEvent(EventType.CONTINUE, u, plugin)) + //Deletes this gui + delete(); } }); } @@ -129,10 +126,9 @@ public void rightClick(User u) { } @Override public void leftClick(User u) { - //Deletes this gui - delete(); - - performEvent(EventType.COMPULSORY, u, plugin); + if (performEvent(EventType.COMPULSORY, u, plugin)) + //Deletes this gui + delete(); } }); } @@ -149,10 +145,9 @@ public void rightClick(User u) @Override public void leftClick(User u) { - //Deletes this gui - delete(); - - performEvent(EventType.CONTINUE, u, plugin); + if (performEvent(EventType.CONTINUE, u, plugin)) + //Deletes this gui + delete(); } }); @@ -164,10 +159,9 @@ public void rightClick(User u) { } @Override public void leftClick(User u) { - //Deletes this gui - delete(); - - performEvent(EventType.LIBRARY, u, plugin); + if (performEvent(EventType.LIBRARY, u, plugin)) + //Deletes this gui + delete(); } }); } @@ -184,36 +178,42 @@ public void rightClick(User u) { } @Override public void leftClick(User u) { - //Deletes this gui - delete(); - performEvent(EventType.ADMIN_MENU, u, plugin); + if (performEvent(EventType.ADMIN_MENU, u, plugin)) + //Deletes this gui + delete(); } }); } } - public static void performEvent(EventType event, User user, TeachingTutorials plugin) + public static boolean performEvent(EventType event, User user, TeachingTutorials plugin) { switch (event) { case COMPULSORY -> { //Starts the compulsory tutorial Compulsory compulsory = new Compulsory(plugin, user); - compulsory.startLesson(); + return compulsory.startLesson(); } case CONTINUE -> { //Creates a lesson with the user Lesson lesson = new Lesson(user, plugin, false); - lesson.startLesson(); + return lesson.startLesson(); } case ADMIN_MENU -> { user.mainGui = new AdminMenu(plugin, user); user.mainGui.open(user); + return true; } case LIBRARY -> { user.mainGui = new LibraryMenu(plugin, user, Tutorial.getInUseTutorialsWithLocations()); user.mainGui.open(user); + return true; + } + default -> + { + return false; } } } @@ -226,4 +226,11 @@ public void refresh() this.open(user); } + + @Override + public void delete() + { + super.delete(); + user.mainGui = null; + } } diff --git a/src/main/java/teachingtutorials/tutorials/Lesson.java b/src/main/java/teachingtutorials/tutorials/Lesson.java index 08a19ad..db4d371 100644 --- a/src/main/java/teachingtutorials/tutorials/Lesson.java +++ b/src/main/java/teachingtutorials/tutorials/Lesson.java @@ -73,7 +73,7 @@ public Lesson(User player, TeachingTutorials plugin, Tutorial tutorial) } //Used for kicking the lesson off, determines whether it needs to create a new lesson or resume a previous lesson - public void startLesson() + public boolean startLesson() { //Checks to see whether a user is actually free to start a new lesson //(Not already doing a tutorial, creating a tutorial, creating a location etc.) @@ -81,6 +81,7 @@ public void startLesson() { Display display = new Display(creatorOrStudent.player, ChatColor.DARK_AQUA +"Complete your current tutorial first"); display.Message(); + return false; } //Student is ready to go into a lesson and the tutorial must now be determined @@ -98,12 +99,14 @@ public void startLesson() //Adds this lesson to the list of lessons ongoing on the server this.plugin.lessons.add(this); + return true; } else { //If the lesson failed to resume Display display = new Display(creatorOrStudent.player, ChatColor.RED +"Could not resume lesson, speak to staff"); display.Message(); Bukkit.getConsoleSender().sendMessage(ChatColor.RED +"Could not resume lesson for player: "+creatorOrStudent.player.getName()); + return false; } } @@ -125,12 +128,16 @@ public void startLesson() //Adds this lesson to the list of lessons ongoing on the server this.plugin.lessons.add(this); + + return true; } else { //If the lesson failed to be created Display display = new Display(creatorOrStudent.player, ChatColor.RED +"Could not create lesson, speak to staff"); display.Message(); Bukkit.getConsoleSender().sendMessage(ChatColor.RED +"Could not create lesson for player: "+creatorOrStudent.player.getName()); + + return false; } } } From 95af85b45ac9507f057f61fc81359cc86eb473f3 Mon Sep 17 00:00:00 2001 From: george112n Date: Mon, 25 Sep 2023 15:07:14 +0100 Subject: [PATCH 12/18] Fixes a bug imported from Network's GUI system resulting in all menus for all players being deleted when a menu of one player was deleted. --- src/main/java/teachingtutorials/guis/Gui.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/teachingtutorials/guis/Gui.java b/src/main/java/teachingtutorials/guis/Gui.java index 2458460..6c6e1bc 100644 --- a/src/main/java/teachingtutorials/guis/Gui.java +++ b/src/main/java/teachingtutorials/guis/Gui.java @@ -85,12 +85,7 @@ public void open(User u) { public void delete() { for (Player p : Bukkit.getOnlinePlayers()) { - UUID u = openInventories.get(p.getUniqueId()); - if (u != null) { - if (u.equals(getUuid())) { - p.closeInventory(); - } - } + openInventories.remove(p.getUniqueId(), getUuid()); } inventoriesByUUID.remove(getUuid()); } From fbe2f47232732663feaef1410261758a54791224 Mon Sep 17 00:00:00 2001 From: george112n Date: Mon, 25 Sep 2023 15:13:13 +0100 Subject: [PATCH 13/18] /tutorials now opens whatever menu is already open rather than always defaulting to main menu. The also solves an issue where if /tutorials was run whilst creating a new location there was then no way to get back to the step editor menu. --- .../listeners/GlobalPlayerCommandProcess.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java b/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java index 506df7d..38f7953 100644 --- a/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java +++ b/src/main/java/teachingtutorials/listeners/GlobalPlayerCommandProcess.java @@ -1,7 +1,6 @@ package teachingtutorials.listeners; import net.buildtheearth.terraminusminus.generator.EarthGeneratorSettings; -import net.buildtheearth.terraminusminus.projection.GeographicProjection; import net.buildtheearth.terraminusminus.projection.OutOfProjectionBoundsException; import net.buildtheearth.terraminusminus.util.geo.CoordinateParseUtils; import net.buildtheearth.terraminusminus.util.geo.LatLng; @@ -119,12 +118,20 @@ else if (command.startsWith("/tutorials") || command.startsWith("/learn")) User user = User.identifyUser(plugin, player); if (user != null) { - user.mainGui.open(user); -// if (user.mainGui != null) -// user.mainGui.delete(); -// -// user.mainGui = new MainMenu(plugin, user); -// user.mainGui.open(user); + //Check if the mainGui is not null. + if (user.mainGui != null) + //If not then open it after refreshing its contents. + user.mainGui.refresh(); + + //If no gui exists open the learning menu + else + { + //Creates a new main menu + user.mainGui = new MainMenu(plugin, user); + + //Opens the gui + user.mainGui.open(user); + } } } } From ecd8f309ddfb9b433646343468b8ae74941ab684 Mon Sep 17 00:00:00 2001 From: george112n Date: Wed, 27 Sep 2023 12:10:36 +0100 Subject: [PATCH 14/18] Adds the give item utils from Network --- .../java/teachingtutorials/utils/Utils.java | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/src/main/java/teachingtutorials/utils/Utils.java b/src/main/java/teachingtutorials/utils/Utils.java index f33a29f..1d57c08 100644 --- a/src/main/java/teachingtutorials/utils/Utils.java +++ b/src/main/java/teachingtutorials/utils/Utils.java @@ -5,6 +5,7 @@ import java.util.List; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.ChatColor; import org.bukkit.Color; import org.bukkit.FireworkEffect; @@ -88,4 +89,70 @@ public static int getHighestYAt(World w, int x, int z) { } return 0; } -} \ No newline at end of file + + //Gives a player an item, it will be set in their main hand, if it does not already exist there. + + //If the main hand is empty, set it there. + //If then main hand is slot 8 and includes the navigator, find the first empty slot available and set it there. + //If no empty slots are available set it to slot 7. + //If the main hand has an item swap the current item to an empty slot in the inventory. + //If no empty slots are available overwrite it. + + public static void giveItem(Player p, ItemStack item, String name) { + int emptySlot = getEmptyHotbarSlot(p); + + boolean hasItemAlready = p.getInventory().containsAtLeast(item, 1); + + //If we already have the item switch to current slot. + if (hasItemAlready) + { + //Switch item to current slot. + int slot = p.getInventory().first(item); + + p.getInventory().setItem(slot, p.getInventory().getItemInMainHand()); + p.getInventory().setItemInMainHand(item); + p.sendMessage(Component.text("Set ", NamedTextColor.GREEN).append(Component.text(name, NamedTextColor.DARK_AQUA).append(Component.text(" to main hand.", NamedTextColor.GREEN)))); + } + else if (emptySlot >= 0) + { + //The current slot is empty. This also implies no navigator, and thus the item does not yet exist in the inventory. + //Set item to empty slot. + p.getInventory().setItem(emptySlot, item); + p.sendMessage(Component.text("Set ", NamedTextColor.GREEN).append(Component.text(name, NamedTextColor.DARK_AQUA).append(Component.text(" to slot " + (emptySlot + 1), NamedTextColor.GREEN)))); + + } + else + { + //Player has no empty slots and is holding the navigator and learning menu, set to item to slot 6. + p.getInventory().setItem(6, item); + p.sendMessage(Component.text("Set ", NamedTextColor.GREEN).append(Component.text(name, NamedTextColor.DARK_AQUA).append(Component.text(" to slot 8", NamedTextColor.GREEN)))); + + } + } + + //Return an empty hotbar slot, if no empty slot exists return -1. + public static int getEmptyHotbarSlot(Player p) { + + //If main hand is empty return that slot. + ItemStack heldItem = p.getInventory().getItemInMainHand(); + if (heldItem.getType() == Material.AIR) { + return p.getInventory().getHeldItemSlot(); + } + + //Check if hotbar has an empty slot. + for (int i = 0; i < 9; i++) { + + ItemStack item = p.getInventory().getItem(i); + + if (item == null) { + return i; + } + if (item.getType() == Material.AIR) { + return i; + } + } + + //No slot could be found, return -1. + return -1; + } +} From 394a27f5db8f0293741230f871702a2eaa6ccc40 Mon Sep 17 00:00:00 2001 From: george112n Date: Wed, 27 Sep 2023 12:12:52 +0100 Subject: [PATCH 15/18] Redesigns how holograms are placed. The position is no longer determined by where the player is and is instead parsed into the function. Now handles new lines properly --- .../teachingtutorials/utils/Hologram.java | 138 +++++++++++------- 1 file changed, 88 insertions(+), 50 deletions(-) diff --git a/src/main/java/teachingtutorials/utils/Hologram.java b/src/main/java/teachingtutorials/utils/Hologram.java index 495972b..49fb3c0 100644 --- a/src/main/java/teachingtutorials/utils/Hologram.java +++ b/src/main/java/teachingtutorials/utils/Hologram.java @@ -1,7 +1,6 @@ package teachingtutorials.utils; import me.filoghost.holographicdisplays.api.HolographicDisplaysAPI; -import me.filoghost.holographicdisplays.api.Position; import me.filoghost.holographicdisplays.api.hologram.VisibilitySettings; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -17,83 +16,122 @@ public Hologram(Location location, Player player, String szTitle, String szText) { //Performs the hologram creation synchronously Bukkit.getScheduler().runTask(TeachingTutorials.getInstance(), () -> { - //Calculates the direction of the hologram from the player - double[] xzAddition = new double[2]; - float fYaw = player.getLocation().getYaw(); - - xzAddition[0] = -4.5 * Math.sin((fYaw*Math.PI)/180); - xzAddition[1] = 4.5 * Math.cos((fYaw*Math.PI)/180); - - //Moves the hologram - location.set(location.getX() +xzAddition[0], location.getY(), location.getZ() +xzAddition[1]); - - //Raises or lowers the hologram to be clear of the ground around the location - int iMaxHeight = location.getWorld().getHighestBlockYAt(location.getBlockX(), location.getBlockZ()); - int iHeight; - for (int i = - 1 ; i <= 1 ; i++) - { - for (int j = - 1 ; j <= 1 ; j++) - { - iHeight = location.getWorld().getHighestBlockYAt(location.getBlockX() + i, location.getBlockZ() + j); - if (iHeight > iMaxHeight) - iMaxHeight = iHeight; - } - } - - location.set(location.getX(), iMaxHeight + 3.1, location.getZ()); - //Creates the hologram hologram = api.createHologram(location); - Position position = hologram.getPosition(); - - //Inserts the text + //Inserts the title hologram.getLines().appendText(szTitle); String[] szWords = szText.split(" "); + //At the start of the for loop, represents the current line being compiled before + // the current word has been added String szLine = ""; + + //Represents the current line after the current word has been added String szLineNew; + + //Represents the current line after the current word has been added + // but also after the text has been stripped of colour codes String szDisplayedText; + //The maximum width a hologram line can be + final int iMax_Width = TeachingTutorials.getInstance().getConfig().getInt("Hologram_Max_Width"); + + boolean bCreateNewLineAfter; + bCreateNewLineAfter = false; + + //Used when a new line is manually specified and the start of the next line needs to be stored to added to the szLine at the end of the loop after the new line is added + String szStartOfNextLine = ""; + + //Goes through each word in the text for (int iWord = 0; iWord < szWords.length ; iWord++) { - szLineNew = szLine + szWords[iWord] +" "; - szDisplayedText = szLineNew.replace("&[A-Fa-f0-9]", ""); - if (szDisplayedText.length() > TeachingTutorials.getInstance().getConfig().getInt("Hologram_Max_Width") + 1) //Line is Hologram_Max_Width without the space + //TODO: what if two line seperators together or in one word? + //-Expand algorithm time + //Checks to see if the word contains a new line separator + if (szWords[iWord].contains(System.lineSeparator())) { - //Indicates that the line just added had one, >40 characters long word, so must display on a new line - if (szLine.equals("")) + int iIndexOfLine = szWords[iWord].indexOf(System.lineSeparator()); + if (iIndexOfLine == 0) { - //Adds the line to the hologram, removing the trailing space - hologram.getLines().appendText(szLineNew.substring(0, szLineNew.length() - 1)); + hologram.getLines().appendText(szLine); + szLine = ""; } - else //Indicates that the line already had some words in it so display those + else if (iIndexOfLine == (szWords[iWord].length() - 1)) { - //Adds the line to the hologram, removing the trailing space - hologram.getLines().appendText(szLine.substring(0, szLine.length() - 1)); + bCreateNewLineAfter = true; + } + else + { + bCreateNewLineAfter = true; + String[] twoWords = szWords[iWord].split(System.lineSeparator()); + szWords[iWord] = twoWords[0]; + szStartOfNextLine = twoWords[1]; } - szLine = szWords[iWord] +" "; - if (iWord == szWords.length - 1) + } + + //Adds the word to the new line being compiled + szLineNew = szLine + szWords[iWord].replaceFirst(System.lineSeparator(), ""); + + //Strips the text of colour codes so that the length can be accurately measured + szDisplayedText = szLineNew.replace("&[A-Fa-f0-9]", ""); + + //Checks to see whether the new line exceeds the maximum width + if (szDisplayedText.length() > iMax_Width) //Line is Hologram_Max_Width without the space + { + //If the new line is too big, needs to deal with it + + //Unless the new line is purely one word (aka the old one was blank) + //How does the old one get blank? - if the same thing happened previously, see below + + //Indicates that the previous line had one > Max_Width characters long word, + // so the new word must display on a new line + if (szLine == "") + //szLine remains as "" + hologram.getLines().appendText(szLineNew); + + //Indicates that the line already had some words in it so display those + //Adding the new one to it takes it over the maximum + else { - hologram.getLines().appendText(szWords[iWord]); + //Adds the previous line to the hologram, removing the trailing space + hologram.getLines().appendText(szLine.substring(0, szLine.length() - 1)); + + //Adds the new line if it is over max characters long + if (szWords[iWord].replace("&[A-Fa-f0-9]", "").length() > iMax_Width) + { + hologram.getLines().appendText(szWords[iWord]); + szLine = ""; + } + + //If this is the last word, can immediately append it on a new line + else if (iWord == szWords.length - 1) + hologram.getLines().appendText(szWords[iWord]); + + else + //Sends the line with the new word just added into the next loop, adds the space + szLine = szWords[iWord] + " "; } } + + //If this is the last worst, but the length didn't max out, we can append the new line + else if (bCreateNewLineAfter) + { + hologram.getLines().appendText(szLineNew); + szLine = szStartOfNextLine + " "; + } else if (iWord == szWords.length - 1) { hologram.getLines().appendText(szLineNew); } else { - szLine = szLineNew; + //Sends the line with the new word just added into the next loop, adds the space + szLine = szLineNew + " "; } - } - Bukkit.getConsoleSender().sendMessage(hologram.getLines().size() +""); - //Shifts the hologram up if it is too tall - if (hologram.getLines().size() > 7) - { - position = position.add(0, 0.2 * (hologram.getLines().size() - 7) , 0); - hologram.setPosition(position); + bCreateNewLineAfter = false; + szStartOfNextLine = ""; } //Sets the visibility From 2a74d14784785b766dac02584a6454934835e19b Mon Sep 17 00:00:00 2001 From: george112n Date: Wed, 27 Sep 2023 12:13:22 +0100 Subject: [PATCH 16/18] Fixes an error where LocationSteps were not removed from the DB when a Location was --- src/main/java/teachingtutorials/tutorials/Location.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/teachingtutorials/tutorials/Location.java b/src/main/java/teachingtutorials/tutorials/Location.java index 9b51eb7..dd3a05e 100644 --- a/src/main/java/teachingtutorials/tutorials/Location.java +++ b/src/main/java/teachingtutorials/tutorials/Location.java @@ -207,6 +207,12 @@ public static boolean deleteLocationByID(int iLocationID) iCount = SQL.executeUpdate(sql); Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] " +iCount +" LocationTasks were deleted"); + //Removes the location specific step details + sql = "Delete FROM LocationSteps WHERE LocationID = " +iLocationID; + Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] " +sql); + iCount = SQL.executeUpdate(sql); + Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] " +iCount +" LocationSteps were deleted"); + //Removes the location sql = "Delete FROM Locations WHERE LocationID = " +iLocationID; Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] " +sql); From 4cc1b7b55ca64a4ba1277b1af6c9f531ae55c2c4 Mon Sep 17 00:00:00 2001 From: george112n Date: Wed, 27 Sep 2023 12:14:39 +0100 Subject: [PATCH 17/18] Minor changes to how menus are opened when clicking on the emerald --- .../listeners/PlayerInteract.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/teachingtutorials/listeners/PlayerInteract.java b/src/main/java/teachingtutorials/listeners/PlayerInteract.java index 9b133b7..eae78f9 100644 --- a/src/main/java/teachingtutorials/listeners/PlayerInteract.java +++ b/src/main/java/teachingtutorials/listeners/PlayerInteract.java @@ -42,15 +42,21 @@ public void interactEvent(PlayerInteractEvent e) if (player.getInventory().getItemInMainHand().equals(TeachingTutorials.menu)) { e.setCancelled(true); - //Check if the mainGui is not null. - //If not then open it after refreshing its contents. - //If no gui exists open the navigator. + //Check if the mainGui is not null. if (user.mainGui != null) + //If not then open it after refreshing its contents. user.mainGui.refresh(); + + //If no gui exists open the learning menu else + { + //Creates a new main menu user.mainGui = new MainMenu(plugin, user); - user.mainGui.open(user); + + //Opens the gui + user.mainGui.open(user); + } } } } From 3fcf678b6d19d8b8a45e0a78fef4df33e238076a Mon Sep 17 00:00:00 2001 From: george112n Date: Wed, 27 Sep 2023 12:16:11 +0100 Subject: [PATCH 18/18] Adds location specific step instructions and fixed hologram positions --- .../teachingtutorials/TeachingTutorials.java | 35 +--- .../TutorialPlaythrough.java | 3 +- .../locationcreatemenus/StepEditorMenu.java | 124 +++++++++++- .../listeners/TextEditorBookListener.java | 95 ++++++++++ .../tutorials/LocationStep.java | 147 +++++++++++++-- .../teachingtutorials/tutorials/Step.java | 176 ++++++++++-------- .../java/teachingtutorials/utils/Display.java | 5 + 7 files changed, 457 insertions(+), 128 deletions(-) create mode 100644 src/main/java/teachingtutorials/listeners/TextEditorBookListener.java diff --git a/src/main/java/teachingtutorials/TeachingTutorials.java b/src/main/java/teachingtutorials/TeachingTutorials.java index dcbe5aa..432e462 100644 --- a/src/main/java/teachingtutorials/TeachingTutorials.java +++ b/src/main/java/teachingtutorials/TeachingTutorials.java @@ -17,6 +17,7 @@ import teachingtutorials.newlocation.NewLocation; import teachingtutorials.tutorials.*; import teachingtutorials.utils.DBConnection; +import teachingtutorials.utils.Display; import teachingtutorials.utils.User; import teachingtutorials.utils.VirtualBlock; @@ -357,22 +358,15 @@ else if(szLines[iLine].startsWith("(")) return; } szFields = szLines[iLine].split(","); - //Field 1 is step name, field 2 is display type, field 3 is the instruction - if (szFields.length < 3) + //Field 1 is step name, field 2 is display type + if (szFields.length < 2) { Bukkit.getConsoleSender().sendMessage(ChatColor.RED +"Tutorial config is not configured correctly, line: "+(iLine+1)); return; } szType = "Step"; - //Compiles instructions if commas were part of the instruction and split - String szInstructions = szFields[2]; - for (int k = 3 ; k < szFields.length ; k++) - { - szInstructions = szInstructions +"," +szFields[k]; - } - - Step step = new Step(szFields[0].replace("(",""), szFields[1], szInstructions); + Step step = new Step(szFields[0].replace("(",""), szFields[1]); lastStage.steps.add(step); lastStep = step; } @@ -569,10 +563,9 @@ public boolean addNewTutorialToDB(Tutorial tutorial) Step step = steps.get(j); try { - String szStepInstructions = step.getInstructions().replace("\'", "\'\'"); - String szInstructionType = step.getInstructionDisplayType(); + Display.DisplayType instructionDisplayType = step.getInstructionDisplayType(); - sql = "INSERT INTO Steps (StepName, StageID, StepInStage, StepInstructions, InstructionDisplay) VALUES ('"+step.getName()+"', "+iStageID+", "+(j+1)+", '" +szStepInstructions +"' ,'" +szInstructionType +"')"; + sql = "INSERT INTO Steps (StepName, StageID, StepInStage, InstructionDisplay) VALUES ('"+step.getName()+"', "+iStageID+", "+(j+1)+",'" +instructionDisplayType +"')"; Bukkit.getConsoleSender().sendMessage(sql); SQL.executeUpdate(sql); @@ -671,10 +664,6 @@ public Connection getConnection() private boolean createTables() { - //Is assumed true and if any of the tables fail to create will change to false - boolean bSuccess = true; -// int iCount = -1; - sql = ""; FileReader fileReader = null; @@ -712,16 +701,6 @@ private boolean createTables() //Executes the update and returns how many rows were changed SQL.executeUpdate(statements[i]); - -// //If only 1 record was changed, success is set to true - FCKING IDIOT -// if (iCount == 1) -// { -// } -// else -// { -// Bukkit.getConsoleSender().sendMessage(ChatColor.RED +"[TeachingTutorials] - Failed to execute table, iCount = "+iCount +"\n"); -// bSuccess = false; -// } Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] - Executed command\n"); } } @@ -758,7 +737,7 @@ private boolean createTables() } dbConnection.disconnect(); } - return (bSuccess); + return true; } private String readAll(BufferedReader br) diff --git a/src/main/java/teachingtutorials/TutorialPlaythrough.java b/src/main/java/teachingtutorials/TutorialPlaythrough.java index 4827aa9..bf3ee01 100644 --- a/src/main/java/teachingtutorials/TutorialPlaythrough.java +++ b/src/main/java/teachingtutorials/TutorialPlaythrough.java @@ -48,7 +48,8 @@ public User getCreatorOrStudent() public void setFallListenerSafeLocation(org.bukkit.Location location) { - fallListener.setSafeLocation(location); + //Raises the safe location by 1 block to ensure players do not tp inside blocks as used to happen sometimes + fallListener.setSafeLocation(location.add(0, 1, 0)); } // Moves the tutorial on to the next stage diff --git a/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java b/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java index efa2d8c..e644c85 100644 --- a/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java +++ b/src/main/java/teachingtutorials/guis/locationcreatemenus/StepEditorMenu.java @@ -4,12 +4,17 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; import teachingtutorials.TeachingTutorials; import teachingtutorials.guis.Gui; +import teachingtutorials.listeners.TextEditorBookListener; import teachingtutorials.tutorials.LocationStep; import teachingtutorials.tutorials.Step; +import teachingtutorials.utils.Display; import teachingtutorials.utils.User; import teachingtutorials.utils.Utils; @@ -25,6 +30,10 @@ public class StepEditorMenu extends Gui private final Step step; private final LocationStep locationStep; + private TextEditorBookListener bookListener; + + private ItemStack book; + public StepEditorMenu(TeachingTutorials plugin, User user, Step step, LocationStep locationStep) { super(iInvSize, getName(step.getName())); @@ -33,17 +42,102 @@ public StepEditorMenu(TeachingTutorials plugin, User user, Step step, LocationSt this.step = step; this.locationStep = locationStep; + this.book = new ItemStack(Material.WRITABLE_BOOK, 1); + BookMeta bookMeta = (BookMeta) book.getItemMeta(); + bookMeta.setTitle(step.getName()); + this.book.setItemMeta(bookMeta); + setItems(); } public void setItems() { - //Set start location coordinates to current location - ItemStack startLocation = Utils.createItem(Material.COMPASS, 1, + ItemStack setStartLocation = Utils.createItem(Material.COMPASS, 1, Component.text("Set the step's start location", NamedTextColor.GREEN), Component.text("Set the start location to your current position and direction", NamedTextColor.DARK_GREEN)); - setItem(11, startLocation, new guiAction() { + ItemStack teleportToStart = Utils.createItem(Material.VILLAGER_SPAWN_EGG, 1, + Component.text("Teleport back to the start location", NamedTextColor.GREEN)); + + boolean bIsHologramNeeded = step.getInstructionDisplayType().equals(Display.DisplayType.hologram); + if (bIsHologramNeeded) + { + //Set start location coordinates to current location + setItem(11, setStartLocation, new guiAction() { + @Override + public void rightClick(User u) { + leftClick(u); + } + + @Override + public void leftClick(User u) { + setStartLocation(u.player.getLocation()); + } + }); + + //Set instructions + ItemStack instructions = Utils.createItem(Material.WRITABLE_BOOK, 1, + Component.text("Set the instructions", NamedTextColor.GREEN)); + + setItem(13, instructions, new guiAction() { + @Override + public void rightClick(User u) { + leftClick(u); + } + + @Override + public void leftClick(User u) { + //The book must have the step name as the title + Utils.giveItem(u.player, book, "Instructions editor book"); + Display display = new Display(u.player, Component.text("Use the instructions editor book to set the instructions", NamedTextColor.GREEN)); + display.Message(); + + //Closes the current inventory + u.player.closeInventory(InventoryCloseEvent.Reason.PLUGIN); + + //Sets up the book listener and registers it + bookListener = new TextEditorBookListener(plugin, u, locationStep, StepEditorMenu.this, step.getInstructionDisplayType(), step.getName(), book); + bookListener.register(); + + //step.tryNextStep() is called via instructionsEdited() from TextEditorBookListener once the book close event occurs + } + }); + + //Set hologram coordinates to player's current location + ItemStack hologramLocation = Utils.createItem(Material.FILLED_MAP, 1, + Component.text("Set the instructions hologram location", NamedTextColor.GREEN), + Component.text("Set the instructions hologram to your current position", NamedTextColor.DARK_GREEN)); + + setItem(15, hologramLocation, new guiAction() { + @Override + public void rightClick(User u) { + leftClick(u); + } + + @Override + public void leftClick(User u) { + locationStep.setHologramLocationToThatOfPlayer(u.player, step.getName()); + step.tryNextStep(); + } + }); + } + else + { + setItem(13, setStartLocation, new guiAction() { + @Override + public void rightClick(User u) { + leftClick(u); + } + + @Override + public void leftClick(User u) { + setStartLocation(u.player.getLocation()); + } + }); + } + + //Teleport to start + setItem(0, teleportToStart, new guiAction() { @Override public void rightClick(User u) { leftClick(u); @@ -51,21 +145,41 @@ public void rightClick(User u) { @Override public void leftClick(User u) { - locationStep.setStartLocation(u.player.getLocation()); - step.tryNextStep(); + locationStep.teleportPlayerToStartOfStep(u.player, step.parentStage.tutorialPlaythrough.getLocation().getWorld(), plugin); } }); } + private void setStartLocation(Location playersLocation) + { + locationStep.setStartLocation(playersLocation); + step.parentStage.tutorialPlaythrough.setFallListenerSafeLocation(playersLocation); + step.tryNextStep(); + } + public static Component getName(String szStepName) { Component inventoryName = Component.text("Step - " +szStepName, Style.style(TextDecoration.BOLD, NamedTextColor.DARK_AQUA)); return inventoryName; } + /** + * Clears items from the GUI, recreates the items and then opens the menu + */ @Override public void refresh() { + this.clearGui(); + this.setItems(); + this.open(user); + } + + /** + * Triggers the step to test whether it can move forwards with the stage + */ + public void instructionsEdited() + { + step.tryNextStep(); } } diff --git a/src/main/java/teachingtutorials/listeners/TextEditorBookListener.java b/src/main/java/teachingtutorials/listeners/TextEditorBookListener.java new file mode 100644 index 0000000..0b0a764 --- /dev/null +++ b/src/main/java/teachingtutorials/listeners/TextEditorBookListener.java @@ -0,0 +1,95 @@ +package teachingtutorials.listeners; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerEditBookEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; +import teachingtutorials.TeachingTutorials; +import teachingtutorials.guis.locationcreatemenus.StepEditorMenu; +import teachingtutorials.tutorials.LocationStep; +import teachingtutorials.utils.Display; +import teachingtutorials.utils.User; + +import java.util.List; + +public class TextEditorBookListener implements Listener +{ + private TeachingTutorials plugin; + private User user; + private LocationStep locationStep; + private StepEditorMenu stepEditorMenu; + private Display.DisplayType displayType; + private String szStepName; + private ItemStack book; + + public TextEditorBookListener(TeachingTutorials plugin, User user, LocationStep locationStep, StepEditorMenu stepEditorMenu, Display.DisplayType displayType, String szStepName, ItemStack book) + { + this.plugin = plugin; + this.user = user; + this.locationStep = locationStep; + this.stepEditorMenu = stepEditorMenu; + this.displayType = displayType; + this.szStepName = szStepName; + this.book = book; + } + + public void register() + { + Bukkit.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void BookCloseEvent(PlayerEditBookEvent e) + { + //Check the player + if (!e.getPlayer().equals(user.player)) + return; + + //We can't actually also check the book because the event doesn't give that + //We can only check the title + if (!e.getNewBookMeta().getTitle().equalsIgnoreCase(szStepName)) + return; + + //Extracts the new content from the book + String szNewContent = ""; + List pages = e.getNewBookMeta().pages(); + for (Component page: pages) + { + szNewContent = szNewContent + ((TextComponent) page).content() + " "; + + } + //Removes the end space, the space after the last page is added in the loop but then needs to be removed + szNewContent = szNewContent.substring(0, szNewContent.length() - 1); + + //Edits the step instructions + locationStep.setInstruction(szNewContent, displayType, user.player, szStepName); + + //Saves the instructions in the book + BookMeta bookMeta = (BookMeta) book.getItemMeta(); + bookMeta.pages(e.getNewBookMeta().pages()); + this.book.setItemMeta(bookMeta); + + //Reopen the feature menu + user.mainGui = stepEditorMenu; + user.mainGui.refresh(); + + //Unregisters this listener + unregister(); + + //Removes the book + user.player.getInventory().getItemInMainHand().setAmount(0); + + //Informs the menu that some instructions were edited + stepEditorMenu.instructionsEdited(); + } + + private void unregister() + { + HandlerList.unregisterAll(this); + } +} diff --git a/src/main/java/teachingtutorials/tutorials/LocationStep.java b/src/main/java/teachingtutorials/tutorials/LocationStep.java index 69e1323..ab64f94 100644 --- a/src/main/java/teachingtutorials/tutorials/LocationStep.java +++ b/src/main/java/teachingtutorials/tutorials/LocationStep.java @@ -7,6 +7,8 @@ import org.bukkit.entity.Player; import teachingtutorials.TeachingTutorials; import teachingtutorials.fundamentalTasks.GeometricUtils; +import teachingtutorials.utils.Display; +import teachingtutorials.utils.Hologram; import java.sql.ResultSet; import java.sql.SQLException; @@ -30,33 +32,57 @@ public class LocationStep// extend step? private double dHologramLocationX; private double dHologramLocationY; private double dHologramLocationZ; - - + private Hologram instructions; private boolean bLocationSet; + private boolean bInstructionsSet; + private boolean bHologramLocationSet; - public LocationStep(int iLocationID, int iStepID) + public LocationStep(int iLocationID, int iStepID, boolean bHologramNeeded) { this.iLocationID = iLocationID; this.iStepID = iStepID; + this.szInstructions = ""; bLocationSet = false; + bInstructionsSet = false; + bHologramLocationSet = !bHologramNeeded; + + if (bHologramLocationSet) + Bukkit.getConsoleSender().sendMessage("Hologram location is set because no hologram is needed"); + //If hologram needed then we set this to false as the location is not set yet + //If a hologram is not needed then we set this to true, indicating that this does not need to be done } - public boolean isLocationSet() + public boolean isOtherInformationSet() { - return bLocationSet; + if (bLocationSet) + Bukkit.getConsoleSender().sendMessage("Location is set"); + if (bInstructionsSet) + Bukkit.getConsoleSender().sendMessage("Instruction is set"); + if (bHologramLocationSet) + Bukkit.getConsoleSender().sendMessage("Hologram location is set"); + + boolean bAllExtraInformationIsSet = (bLocationSet && bInstructionsSet) && bHologramLocationSet; + if (bAllExtraInformationIsSet) + Bukkit.getConsoleSender().sendMessage("All extra information is set"); + + return bAllExtraInformationIsSet; } + //------------------------------------------------ + //--------------------Database-------------------- + //------------------------------------------------ + /** * //Accesses the DB and fetches the information about the step location * @param iStepID The step ID of the step * @param iLocationID The location that is being played * @return */ - public static LocationStep getFromStepAndLocation(int iStepID, int iLocationID) + public static LocationStep getFromStepAndLocation(int iStepID, int iLocationID, boolean bHologramNeeded) { - LocationStep locationStep = new LocationStep(iLocationID, iStepID); + LocationStep locationStep = new LocationStep(iLocationID, iStepID, bHologramNeeded); String sql; Statement SQL = null; @@ -77,10 +103,10 @@ public static LocationStep getFromStepAndLocation(int iStepID, int iLocationID) locationStep.dStartLongitude = resultSet.getDouble("Longitude"); locationStep.fStartYaw = resultSet.getFloat("StartYaw"); locationStep.fStartPitch = resultSet.getFloat("StartPitch"); -// locationStep.szInstructions = resultSet.getString("Instructions"); -// locationStep.dHologramLocationX = resultSet.getDouble("InstructionsX"); -// locationStep.dHologramLocationY = resultSet.getDouble("InstructionsY"); -// locationStep.dHologramLocationZ = resultSet.getDouble("InstructionsZ"); + locationStep.szInstructions = resultSet.getString("Instructions"); + locationStep.dHologramLocationX = resultSet.getDouble("InstructionsX"); + locationStep.dHologramLocationY = resultSet.getDouble("InstructionsY"); + locationStep.dHologramLocationZ = resultSet.getDouble("InstructionsZ"); } } catch(SQLException se) @@ -109,13 +135,17 @@ public boolean storeDetailsInDB() try { SQL = TeachingTutorials.getInstance().getConnection().createStatement(); - sql = "INSERT INTO LocationSteps (Location, Step, Latitude, Longitude, StartYaw, StartPitch) VALUES (" + sql = "INSERT INTO LocationSteps (Location, Step, Latitude, Longitude, StartYaw, StartPitch, Instructions, InstructionsX, InstructionsY, InstructionsZ) VALUES (" + iLocationID +", " + iStepID +", " + dStartLatitude +", " + dStartLongitude +", " + fStartYaw +", " - + fStartPitch + + fStartPitch +", '" + + szInstructions +"', " + + dHologramLocationX +", " + + dHologramLocationY +", " + + dHologramLocationZ +")"; Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +sql); iCount = SQL.executeUpdate(sql); @@ -140,6 +170,10 @@ public boolean storeDetailsInDB() } } + //----------------------------------------------- + //---------------------Utils--------------------- + //----------------------------------------------- + /** * Teleports the player to the start of the step * @param player The player to teleport @@ -156,7 +190,10 @@ public Location teleportPlayerToStartOfStep(Player player, World world, Teaching Bukkit.getScheduler().runTask(plugin, () -> player.teleport(finalLocation)); } else + { location = player.getLocation(); + player.sendMessage(ChatColor.RED +"No start location for this step has been set yet"); + } return location; } @@ -189,7 +226,7 @@ public void setStartLocation(Location location) * * @return The start location for the step as a bukkit object */ - public Location getStartLocation(World world) + private Location getStartLocation(World world) { Location location = GeometricUtils.convertToBukkitLocation(world, dStartLatitude, dStartLongitude); @@ -201,4 +238,86 @@ public Location getStartLocation(World world) } return location; } + + /** + * Displays the instructions to the player + * @param displayType The way the instruction should be displayed + * @param player The player to which the instruction should be displayed + */ + public void displayInstructions(Display.DisplayType displayType, Player player, String szStepName, World world) + { + Display display; + + switch (displayType) + { + case hologram: + display = new Display(player, this.szInstructions); + instructions = display.Hologram(ChatColor.AQUA +"" +ChatColor.UNDERLINE +ChatColor.BOLD +szStepName, getHologramLocation(world)); + break; + default: + display = new Display(player, this.szInstructions); + display.Message(); + break; + } + } + + /** + * Removes the hologram from view if it is displayed + */ + public void removeInstructionsHologram() + { + if (instructions != null) + instructions.removeHologram(); + } + + /** + * Sets the location of the instructions hologram and displays the instructions to the creator + * @param player The player to which the location must be set to + * @param szStepName The name of the step, so that the instructions can then be displayed + */ + public void setHologramLocationToThatOfPlayer(Player player, String szStepName) + { + //Sets the location + Location playerLocation = player.getLocation(); + this.dHologramLocationX = playerLocation.getX(); + this.dHologramLocationY = playerLocation.getY(); + this.dHologramLocationZ = playerLocation.getZ(); + + //Displays the instructions + removeInstructionsHologram(); + displayInstructions(Display.DisplayType.hologram, player, szStepName, player.getWorld()); + + this.bHologramLocationSet = true; + } + + /** + * + * @return The instructions' hologram location for the step as a bukkit object + */ + private Location getHologramLocation(World world) + { + Location hologramLocation = new Location(world, dHologramLocationX, dHologramLocationY, dHologramLocationZ); + return hologramLocation; + } + + /** + * Sets the instructions of the step and displays the instructions + * @param szInstructions The desired instructions + * @param displayType The display type, so the instructions can be displayed + * @param player The player, so the instructions can be displayed + * @param szStepName The player, so the instructions can be displayed + */ + public void setInstruction(String szInstructions, Display.DisplayType displayType, Player player, String szStepName) + { + //Sets the instructions + this.szInstructions = szInstructions; + + //Displays the instructions + removeInstructionsHologram(); + displayInstructions(displayType, player, szStepName, player.getWorld()); + + //Instructions may be blank at this point, but this is fine and is displayed blank on the hologram + + this.bInstructionsSet = true; + } } diff --git a/src/main/java/teachingtutorials/tutorials/Step.java b/src/main/java/teachingtutorials/tutorials/Step.java index 0c86190..a12528c 100644 --- a/src/main/java/teachingtutorials/tutorials/Step.java +++ b/src/main/java/teachingtutorials/tutorials/Step.java @@ -10,7 +10,6 @@ import teachingtutorials.fundamentalTasks.TpllListener; import teachingtutorials.guis.locationcreatemenus.StepEditorMenu; import teachingtutorials.utils.Display; -import teachingtutorials.utils.Hologram; import teachingtutorials.utils.User; import java.sql.ResultSet; @@ -21,11 +20,14 @@ public class Step { private String szName; - private String szStepInstructions; - private String szInstructionDisplayType; + private Display.DisplayType instructionDisplayType; private Player player; private TeachingTutorials plugin; public Stage parentStage; + + /** + * Notes whether all tasks have been completed/set or not + */ public boolean bStepFinished; protected int iStepID; protected int iStepInStage; @@ -33,8 +35,6 @@ public class Step //Stores the location specific step data private LocationStep locationStep; - private Hologram instructions; - private int iGroupInStepLocationCreation; private Group currentGroup; @@ -51,7 +51,7 @@ public class Step private StepEditorMenu menu; //Used for creating a step for a lesson - public Step(int iStepID, int iStepInStage, String szStepName, Player player, TeachingTutorials plugin, Stage parentStage, String szStepInstructions, String szInstructionDisplayType) + public Step(int iStepID, int iStepInStage, String szStepName, Player player, TeachingTutorials plugin, Stage parentStage, String szInstructionDisplayType) { this.player = player; this.plugin = plugin; @@ -60,24 +60,22 @@ public Step(int iStepID, int iStepInStage, String szStepName, Player player, Tea this.iStepID = iStepID; this.iStepInStage = iStepInStage; this.szName = szStepName; - this.szInstructionDisplayType = szInstructionDisplayType; - this.szStepInstructions = szStepInstructions; + setInstructionDisplayType(szInstructionDisplayType); this.selectionCompleteHold = false; if (parentStage.bLocationCreation) //Initialises location step - this.locationStep = new LocationStep(parentStage.getLocationID(), iStepID); + this.locationStep = new LocationStep(parentStage.getLocationID(), iStepID, getInstructionDisplayType().equals(Display.DisplayType.hologram)); else //Gets the location specific data - this.locationStep = LocationStep.getFromStepAndLocation(this.iStepID, this.parentStage.tutorialPlaythrough.getLocation().getLocationID()); + this.locationStep = LocationStep.getFromStepAndLocation(this.iStepID, this.parentStage.tutorialPlaythrough.getLocation().getLocationID(), getInstructionDisplayType().equals(Display.DisplayType.hologram)); } //Used for adding a step to the DB - public Step(String szName, String szInstructionDisplayType, String szInstructions) + public Step(String szName, String szInstructionDisplayType) { this.szName = szName; - this.szInstructionDisplayType = szInstructionDisplayType; - this.szStepInstructions = szInstructions; + setInstructionDisplayType(szInstructionDisplayType); this.selectionCompleteHold = false; } @@ -87,14 +85,22 @@ public String getName() return szName; } - public String getInstructions() + public void setInstructionDisplayType(String szInstructionDisplayType) { - return szStepInstructions; + Display.DisplayType displayType; + try { + displayType = Display.DisplayType.valueOf(szInstructionDisplayType); + } + catch (IllegalArgumentException e) { + Bukkit.getConsoleSender().sendMessage("The step instruction display type was not properly specified ("+szInstructionDisplayType +"), reverting to chat"); + displayType = Display.DisplayType.chat; + } + this.instructionDisplayType = displayType; } - public String getInstructionDisplayType() + public Display.DisplayType getInstructionDisplayType() { - return szInstructionDisplayType; + return this.instructionDisplayType; } public boolean getSelectionCompleteHold() @@ -124,13 +130,13 @@ public void holdSelectionComplete() selectionCompleteHold = true; //Changes the hold back to false in 0.5 seconds - this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() + { public void run() { selectionCompleteHold = false; } }, 10L); - } public void calculateNearestTpllPointAfterWait() @@ -180,7 +186,7 @@ public void run() } /** - * Starts the player on this step. Sends them the title of the step, registers the fall listener + * Starts the player on this step. Sends them the title of the step, registers the fall listener, * teleports them to the start, displays the instructions and initialises the groups of tasks */ public void startStep() @@ -204,49 +210,38 @@ public void run() { display.Title(ChatColor.AQUA +"Step " +iStepInStage +" - " +szName, 10, 60, 12); } + //Fetches the details of groups and stores them in memory + fetchAndInitialiseGroups(); + Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] " +groups.size() +" groups fetched"); + + //Player is a student doing a tutorial if (!parentStage.bLocationCreation) { + //Register the start of all groups + int i; + int iGroups = groups.size(); + + for (i = 0; i < iGroups; i++) + { + groups.get(i).initialRegister(); + Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] Registered group "+(i+1)); + } + //TP to start location, and store this location for later use Location startLocation = locationStep.teleportPlayerToStartOfStep(player, parentStage.tutorialPlaythrough.getLocation().getWorld(), plugin); //Updates the fall listener parentStage.tutorialPlaythrough.setFallListenerSafeLocation(startLocation); - } - //Displays the step instructions - location is based on the start location for now - Location instructionLocation; - if (iStepInStage == 1 && parentStage.isFirstStage()) - { - instructionLocation = locationStep.getStartLocation(parentStage.tutorialPlaythrough.getLocation().getWorld()); + //Displays the step instructions + this.locationStep.displayInstructions(getInstructionDisplayType(), player, szName, parentStage.tutorialPlaythrough.getLocation().getWorld()); } - else - { - instructionLocation = locationStep.getStartLocation(parentStage.tutorialPlaythrough.getLocation().getWorld()); - if (instructionLocation == null) - instructionLocation = player.getLocation(); - } - - switch (szInstructionDisplayType) - { - case "hologram": - display = new Display(player, szStepInstructions); - instructions = display.Hologram(ChatColor.AQUA +"" +ChatColor.UNDERLINE +ChatColor.BOLD +szName, instructionLocation); - break; - case "chat": - default: - display = new Display(player, szStepInstructions); - display.Message(); - break; - } - - //Fetches the details of groups and stores them in memory - fetchAndInitialiseGroups(); - Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] " +groups.size() +" groups fetched"); - //If a location is being created, groups are made synchronous rather than asynchronous - if (parentStage.bLocationCreation) + //Player is a creator creating a new location for a tutorial + else { //Register the start of the first group + //If a location is being created, groups are made synchronous rather than asynchronous currentGroup = groups.get(0); iGroupInStepLocationCreation = 1; currentGroup.initialRegister(); @@ -259,18 +254,6 @@ public void run() { user.mainGui.delete(); user.mainGui = menu; } - else - { - //Register the start of all groups - int i; - int iGroups = groups.size(); - - for (i = 0; i < iGroups; i++) - { - groups.get(i).initialRegister(); - Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +"[TeachingTutorials] Registered group "+(i+1)); - } - } } protected void groupFinished() @@ -313,58 +296,93 @@ protected void groupFinished() if (bAllGroupsFinished == true) { - //Remove hologram - if (szInstructionDisplayType.equals("hologram")) - instructions.removeHologram(); - + //Marks the step's tasks as all finished this.bStepFinished = true; + //Player has just finished setting the answers for this step if (parentStage.bLocationCreation) { - if (locationStep.isLocationSet()) + //Checks whether the additional information is set - start location and instructions etc + if (locationStep.isOtherInformationSet()) tryNextStep(); else { - Display display = new Display(player, Component.text("You must now set the step's start location. Use the learning menu", NamedTextColor.RED)); + Display display = new Display(player, Component.text("You must now set the step's start location and instructions. Use the learning menu", NamedTextColor.RED)); display.Message(); + //Sets the player's menu as the step editor menu + this.parentStage.tutorialPlaythrough.getCreatorOrStudent().mainGui = menu; + + //Opens the step editor menu + menu.open(this.parentStage.tutorialPlaythrough.getCreatorOrStudent()); + //We wait and then perform the code in the if statement above once the location has been set, via tryNextStep() } } else { + //Remove hologram + if (getInstructionDisplayType().equals(Display.DisplayType.hologram)) + locationStep.removeInstructionsHologram(); parentStage.nextStep(); } } } /** - * Will move the player on to the next step if the current step is finished. - * This is used if the creator finished the step answer submissions before setting the start location. - * This method has one use: it is called directly after the start location is set + * Will move the player on to the next step if the current step is finished - answers AND additional information set + *

+ *

This method has two uses: it is called directly after any additional step information is set. + * It is called when the answers have just finished being set. + *

*/ public void tryNextStep() { + //Blocks any processes occurring if the method has wrongly been called from outside of location creation if (!parentStage.bLocationCreation) return; if (bStepFinished) { - locationStep.storeDetailsInDB(); - parentStage.nextStep(); + if (locationStep.isOtherInformationSet()) + { + //Remove hologram + if (getInstructionDisplayType().equals(Display.DisplayType.hologram)) + locationStep.removeInstructionsHologram(); + + //Deletes menu + menu.delete(); + menu = null; + + locationStep.storeDetailsInDB(); + parentStage.nextStep(); + } + else + { + Display display = new Display(player, ChatColor.GREEN +"Continue to set the additional information, use the learning menu"); + display.Message(); + } + } + else + { + Display display = new Display(player, ChatColor.GREEN +"Continue to set the answers"); + display.Message(); } } public void terminateEarly() { //Remove holograms - if (szInstructionDisplayType.equals("hologram")) - instructions.removeHologram(); + if (getInstructionDisplayType().equals(Display.DisplayType.hologram)) + this.locationStep.removeInstructionsHologram(); //Unregisters the current task listener if (parentStage.bLocationCreation) { currentGroup.terminateEarly(); + menu.delete(); + menu = null; + Bukkit.getConsoleSender().sendMessage(ChatColor.AQUA +" [TeachingTutorials] Unregistered group "+iGroupInStepLocationCreation); } @@ -400,7 +418,7 @@ public static ArrayList fetchStepsByStageID(Player player, TeachingTutoria resultSet = SQL.executeQuery(sql); while (resultSet.next()) { - Step step = new Step(resultSet.getInt("StepID"), resultSet.getInt("StepInStage"), resultSet.getString("StepName") ,player, plugin, stage, resultSet.getString("StepInstructions"), resultSet.getString("InstructionDisplay")); + Step step = new Step(resultSet.getInt("StepID"), resultSet.getInt("StepInStage"), resultSet.getString("StepName") ,player, plugin, stage, resultSet.getString("InstructionDisplay")); steps.add(step); } } @@ -415,6 +433,4 @@ public static ArrayList fetchStepsByStageID(Player player, TeachingTutoria } return steps; } -} - - +} \ No newline at end of file diff --git a/src/main/java/teachingtutorials/utils/Display.java b/src/main/java/teachingtutorials/utils/Display.java index 06c7fb0..770f476 100644 --- a/src/main/java/teachingtutorials/utils/Display.java +++ b/src/main/java/teachingtutorials/utils/Display.java @@ -50,4 +50,9 @@ public Hologram Hologram(String szTitle, Location location) Hologram hologram = new Hologram(location, player, szTitle, szText); return hologram; } + + public enum DisplayType + { + hologram, chat, action_bar + } }