From a2278297dee8ec84a4d754f8288cb580025ef57d Mon Sep 17 00:00:00 2001 From: NewGarbo Date: Mon, 19 Oct 2015 17:16:48 +0100 Subject: [PATCH] Created the base for tutorials, and created the getting started tutorial. Have all the commands and most of the functionality in here now, but still need to do the scoreboard and some tweaking. --- .../mineplex/core/common/util/UtilText.java | 18 +++ .../game/clans/clans/ClansManager.java | 6 +- .../game/clans/tutorials/Consumer.java | 6 + .../game/clans/tutorials/PlayerTutorial.java | 71 +++++++++ .../game/clans/tutorials/Tutorial.java | 146 ++++++++++++++++++ .../tutorials/TutorialGettingStarted.java | 26 ++++ .../game/clans/tutorials/TutorialManager.java | 69 +++++++++ .../game/clans/tutorials/TutorialPart.java | 49 ++++++ .../game/clans/tutorials/TutorialType.java | 32 ++++ .../commands/EndTutorialCommand.java | 31 ++++ .../tutorials/commands/TaskInfoCommand.java | 31 ++++ 11 files changed, 484 insertions(+), 1 deletion(-) create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Consumer.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/PlayerTutorial.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Tutorial.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialGettingStarted.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialManager.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialPart.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialType.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/EndTutorialCommand.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/TaskInfoCommand.java diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilText.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilText.java index 4372b6fba..2095bc1fe 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilText.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilText.java @@ -95,4 +95,22 @@ public class UtilText { public static String[] wrap(String text, int lineLength, boolean wrapLongerWords) { return WordUtils.wrap(text, lineLength, "\00D0", wrapLongerWords).split("\00D0"); } + + public static String repeat(String txt, int times) + { + return new String(new byte[times]).replace("\0", txt); + } + + public static String insertEvery(String txt, String insert, int chars) + { + StringBuilder builder = new StringBuilder(insert + txt); + if (txt.length() > chars) + { + for (int i = 0; i < txt.length() / chars; i++) + { + builder.insert(chars * i, insert); + } + } + return builder.toString(); + } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java index 1c9244a7b..113209bd4 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java @@ -53,6 +53,7 @@ import mineplex.core.npc.NpcManager; import mineplex.core.packethandler.PacketHandler; import mineplex.core.projectile.ProjectileManager; import mineplex.core.stats.StatsManager; +import mineplex.core.task.TaskManager; import mineplex.core.teleport.Teleport; import mineplex.game.clans.clans.ClansUtility.ClanRelation; import mineplex.game.clans.clans.commands.ClanManagementCommand; @@ -89,6 +90,7 @@ import mineplex.game.clans.gameplay.safelog.LoggingManager; import mineplex.game.clans.gameplay.safelog.npc.NPCManager; import mineplex.game.clans.items.GearManager; import mineplex.game.clans.spawn.Spawn; +import mineplex.game.clans.tutorials.TutorialManager; import mineplex.minecraft.game.classcombat.Class.ClassManager; import mineplex.minecraft.game.classcombat.Class.ClientClass; import mineplex.minecraft.game.classcombat.Class.IPvpClass; @@ -197,6 +199,8 @@ public class ClansManager extends MiniClientPlugin implements IRelat _scoreboard = new ClansScoreboardManager(plugin, this, _warManager, _worldEvent, clientManager, donationManager); new MurderManager(plugin, this); + + new TutorialManager(plugin, _goldManager, donationManager, new TaskManager(plugin, _clientManager, webServerAddress)); _clanAdmin = new ClansAdmin(this); _clanBlocks = new ClansBlocks(); @@ -239,7 +243,7 @@ public class ClansManager extends MiniClientPlugin implements IRelat skillManager.removeSkill("Whirlwind Axe"); skillManager.removeSkill("Shield Smash"); _classManager = new ClassManager(plugin, _clientManager, donationManager, skillManager, itemFactory, webServerAddress); - + // Register redis based server commands ServerCommandManager.getInstance().registerCommandType(ClanDeleteCommand.class, new ClanDeleteCommandHandler()); ServerCommandManager.getInstance().registerCommandType(ClanLoadCommand.class, new ClanLoadCommandHandler()); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Consumer.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Consumer.java new file mode 100644 index 000000000..6f6b625a0 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Consumer.java @@ -0,0 +1,6 @@ +package mineplex.game.clans.tutorials; + +public interface Consumer +{ + public void consume(final T t); +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/PlayerTutorial.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/PlayerTutorial.java new file mode 100644 index 000000000..4d3ea0d02 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/PlayerTutorial.java @@ -0,0 +1,71 @@ +package mineplex.game.clans.tutorials; + +import org.bukkit.entity.Player; + +import mineplex.core.task.TaskManager; + +public class PlayerTutorial +{ + private final TaskManager _taskManager; + private final Tutorial _tutorial; + private final Player _player; + + private int _currentPart=1; + + public PlayerTutorial(final Player player, final TaskManager taskManager, final Tutorial tutorial) + { + _player = player; + _taskManager = taskManager; + _tutorial = tutorial; + } + + public static PlayerTutorial create(final Player player, final TaskManager taskManager, final Tutorial tutorial) + { + PlayerTutorial user = new PlayerTutorial(player, taskManager, tutorial); + + for (int i : tutorial.getParts().keySet()) + { + if (taskManager.hasCompletedTask(player, tutorial.getType().getId() + tutorial.getPart(i).getId())) + { + user._currentPart = i; + } + } + + tutorial.getPart(user._currentPart).sendDescriptionTo(player); + + return user; + } + + public int getCurrentPart() + { + return _currentPart; + } + + public Tutorial getTutorial() + { + return _tutorial; + } + + public Player getPlayer() + { + return _player; + } + + public TaskManager getTaskManager() + { + return _taskManager; + } + + public void finishedPart(final int partID) + { + if (_currentPart == partID - 1) + { + ++_currentPart; + } + else + { + System.err.println("[CLANS TUTORIALS] FATAL ERROR, PARTS OUT OF SYNC FOR PLAYER " + _player.getName() + "!!!"); + } + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Tutorial.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Tutorial.java new file mode 100644 index 000000000..6c7143f6c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/Tutorial.java @@ -0,0 +1,146 @@ +package mineplex.game.clans.tutorials; + +import java.util.HashMap; + +import org.bukkit.Sound; +import org.bukkit.entity.Player; + +import mineplex.core.common.Pair; +import mineplex.core.common.util.Callback; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.task.TaskManager; +import mineplex.game.clans.economy.GoldManager; + +/** + * + * I call this a tutorial, even though it is more accurately, "a set of + * achievements or goals, that are in some-what of a tutorial fashion." But that + * would be too long of a class name, so I'll stick with "Tutorial" for now. + * + */ +public abstract class Tutorial +{ + protected final TutorialManager _manager; + private final TaskManager _taskManager; + private final GoldManager _goldManager; + + private final int _rewardAmount; + + private final HashMap>> _parts; + private final HashMap _inTutorial; + private final TutorialType _type; + + public Tutorial(final int rewardAmount, final GoldManager goldManager, final TaskManager taskManager, final TutorialManager manager, final TutorialType type) + { + _goldManager = goldManager; + _taskManager = taskManager; + _rewardAmount = rewardAmount; + _manager = manager; + _type = type; + _parts = new HashMap<>(); + _inTutorial = new HashMap<>(); + } + + protected Consumer addPart(final String name, final String description) + { + final Consumer consumer = new Consumer() + { + public void consume(Player player) + { + finishPart(player, _parts.size() + 1); + } + }; + + _parts.put(_parts.size() + 1, Pair.create(new TutorialPart(_parts.size() + 1, name, description), consumer)); + + return consumer; + } + + private void finishPart(final Player player, final int partID) + { + final Pair> part = _parts.get(partID); + + _inTutorial.get(player.getName()).finishedPart(partID); + + if (!_taskManager.hasCompletedTask(player, _type.getId() + part.getLeft().getId())) + { + _taskManager.completedTask(new Callback() + { + public void run(Boolean completed) + { + UtilPlayer.message(player, F.main("Tutorials", "You have completed part " + F.elem(partID + " (" + part.getLeft().getName() + ")") + ".")); + + player.playSound(player.getLocation(), Sound.LEVEL_UP, 2f, 1.5f); + } + }, player, _type.getId() + part.getLeft().getId()); + } + + if (partID == _parts.size()) + { + finishFor(player); + } + else + { + _parts.get(partID).getLeft().sendDescriptionTo(player); + } + } + + public TutorialPart getPart(final int partID) + { + return _parts.get(partID).getLeft(); + } + + public TutorialType getType() + { + return _type; + } + + private void finishFor(final Player player) + { + _inTutorial.remove(player.getName()); + + UtilPlayer.message(player, F.main("Tutorials", "You have completed the " + F.elem(_type.getFriendlyName() + " Tutorial") + ".")); + if (!_taskManager.hasCompletedTask(player, _type.getId())) + { + _taskManager.completedTask(new Callback() + { + public void run(Boolean completed) + { + _goldManager.addGold(player, _rewardAmount); + } + }, player, _type.getId()); + } + } + + public void startFor(final Player player) + { + _inTutorial.put(player.getName(), PlayerTutorial.create(player, _taskManager, this)); + } + + public void cancelTutorial(final Player player) + { + _inTutorial.remove(player.getName()); + } + + public boolean isInTutorial(final Player player) + { + return _inTutorial.containsKey(player.getName()); + } + + protected HashMap>> getParts() + { + return _parts; + } + + public boolean hasFinished(Player player) + { + return _taskManager.hasCompletedTask(player, _type.getId()); + } + + public PlayerTutorial getPlayer(Player player) + { + return _inTutorial.get(player.getName()); + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialGettingStarted.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialGettingStarted.java new file mode 100644 index 000000000..be32e7ae2 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialGettingStarted.java @@ -0,0 +1,26 @@ +package mineplex.game.clans.tutorials; + +import mineplex.core.donation.DonationManager; +import mineplex.core.task.TaskManager; +import mineplex.game.clans.economy.GoldManager; + +public class TutorialGettingStarted extends Tutorial +{ + public TutorialGettingStarted(final TutorialManager manager, final GoldManager goldManager, final DonationManager donationManager, final TaskManager taskManager) + { + super(50, goldManager, taskManager, manager, TutorialType.GETTING_STARTED); + addPart("Welcome", "Welcome to Clans! Before you start playing Clans, you should be familiar with the various commands. Type /c help now to view all of the commands for Clans!"); + addPart("Create A Clan", "To create your own clan, type /c create [name]. Don’t worry about being though, you can always disband this clan and join another later if you need to!"); + addPart("Viewing Clan Info", "Now you can view information about your clan. To do this type /c [name]! You can also use any clans name to get some information about them as well."); + addPart("Leave Spawn", "Now you can leave the Spawn Island. Don't worry, you won’t get hurt from the fall! Once you jump off though, PvP is enabled! Be careful!"); + addPart("Go To The Wilderness", "Access your map with /map and head out into the wilderness! You’ll see various other locations marked on your map later."); + addPart("Claiming Territory", "In order to claim a chunk of land for your clan you type /c claim! Notice though, your clan runs on energy! You can buy energy from the shops!"); + addPart("Visit The Shops", "At the shops you can buy most things you need! Once a day you can transfer 1000 gems to 5000 clans gold here as well!"); + addPart("Buy Armor", "Head to the PvP Gear villager and purchase a set of armor! Make sure to buy a matching set to access your class skills!"); + addPart("Equip Armor", "In order to equip a kit, you must put on the full armor set of that kit! Put on the armor set you just bought and you will have selected your kit!"); + addPart("Use An Ability", "In order to use abilities you need a sword or axe. To use your sword ability, right click with your sword! To use your axe ability, right click with your axe!"); + addPart("Class Customization", "To customize your class, right click an enchantment table! There you will find the GUI for all the skills in that class! Customize it to your liking!"); + addPart("Clan Home", "In order to set a clan home, type /c sethome. You can only use this /c home from the spawn island every 5 minutes to return home!"); + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialManager.java new file mode 100644 index 000000000..e1ececfba --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialManager.java @@ -0,0 +1,69 @@ +package mineplex.game.clans.tutorials; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.java.JavaPlugin; + +import mineplex.core.MiniPlugin; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.donation.DonationManager; +import mineplex.core.task.TaskManager; +import mineplex.game.clans.economy.GoldManager; + +public class TutorialManager extends MiniPlugin +{ + private final Tutorial _gettingStarted; + + public TutorialManager(final JavaPlugin plugin, final GoldManager goldManager, final DonationManager donationManager, final TaskManager taskManager) + { + super("Tutorials", plugin); + + _gettingStarted = new TutorialGettingStarted(this, goldManager, donationManager, taskManager); + } + + public void startTutorial(final TutorialType type, final Player player) + { + switch (type) + { + case GETTING_STARTED: + _gettingStarted.startFor(player); + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent evt) + { + if (!_gettingStarted.hasFinished(evt.getPlayer())) + { + _gettingStarted.startFor(evt.getPlayer()); + } + } + + public boolean isInTutorial(Player player) + { + return _gettingStarted.isInTutorial(player); + } + + public void cancelTutorial(Player player) + { + if (_gettingStarted.isInTutorial(player)) + { + _gettingStarted.cancelTutorial(player); + + UtilPlayer.message(player, F.main("Tutorials", "You have cancelled the " + F.elem(_gettingStarted.getType().getFriendlyName() + "Tutorial") + ".")); + } + } + + public Tutorial getTutorial(Player player) + { + if (_gettingStarted.isInTutorial(player)) + { + return _gettingStarted; + } + + return null; + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialPart.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialPart.java new file mode 100644 index 000000000..4c41f378e --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialPart.java @@ -0,0 +1,49 @@ +package mineplex.game.clans.tutorials; + +import org.bukkit.entity.Player; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilText; + +public class TutorialPart +{ + private final String _name; + private final String _description; + private final int _id; + + public TutorialPart(final int id, final String name, final String description) + { + _id = id; + _name = name; + _description = description; + } + + public int getID() + { + return _id; + } + + public String getName() + { + return _name; + } + + public String getDescription() + { + return _description; + } + + public String getId() + { + return _name.replace(" ", ""); + } + + public void sendDescriptionTo(Player player) + { + UtilPlayer.message(player, C.cGreen + "=== Pt." + _id + ": " + _name + " ==="); + UtilPlayer.message(player, UtilText.insertEvery(_description, C.cYellow, 15)); + UtilPlayer.message(player, C.cGreen + "=== " + UtilText.repeat("=", _name.length() + ("Pt." + _id + ":").length()) + " ==="); + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialType.java new file mode 100644 index 000000000..021aa0167 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/TutorialType.java @@ -0,0 +1,32 @@ +package mineplex.game.clans.tutorials; + +public enum TutorialType +{ + GETTING_STARTED(TutorialGettingStarted.class, "Getting Started", "GettingStartedTutorial"); + + private final Class _clazz; + private final String _uniqueId; + private final String _friendlyName; + + TutorialType(final Class clazz, final String friendlyName, final String uniqueId) + { + _clazz = clazz; + _uniqueId = uniqueId; + _friendlyName = friendlyName; + } + + public Class getClazz() + { + return _clazz; + } + + public String getId() + { + return _uniqueId; + } + + public String getFriendlyName() + { + return _friendlyName; + } +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/EndTutorialCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/EndTutorialCommand.java new file mode 100644 index 000000000..08fbe2852 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/EndTutorialCommand.java @@ -0,0 +1,31 @@ +package mineplex.game.clans.tutorials.commands; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.tutorials.TutorialManager; + +public class EndTutorialCommand extends CommandBase +{ + public EndTutorialCommand(TutorialManager plugin) + { + super(plugin, Rank.ALL, "endtutorial", "endtut", "et"); + } + + @Override + public void Execute(Player caller, String[] args) + { + if (Plugin.isInTutorial(caller)) + { + Plugin.cancelTutorial(caller); + } + else + { + UtilPlayer.message(caller, F.main("Tutorials", "You are not currently in a tutorial.")); + } + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/TaskInfoCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/TaskInfoCommand.java new file mode 100644 index 000000000..3fcc5b320 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorials/commands/TaskInfoCommand.java @@ -0,0 +1,31 @@ +package mineplex.game.clans.tutorials.commands; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.tutorials.TutorialManager; + +public class TaskInfoCommand extends CommandBase +{ + public TaskInfoCommand(TutorialManager plugin) + { + super(plugin, Rank.ALL, "partinfo", "pi"); + } + + @Override + public void Execute(Player caller, String[] args) + { + if (Plugin.isInTutorial(caller)) + { + Plugin.getTutorial(caller).getPart(Plugin.getTutorial(caller).getPlayer(caller).getCurrentPart()).sendDescriptionTo(caller); + } + else + { + UtilPlayer.message(caller, F.main("Tutorials", "You are not currently in a tutorial.")); + } + } + +}