Skip to content

Commit

Permalink
Add Observer Tools
Browse files Browse the repository at this point in the history
  • Loading branch information
applenick authored Jan 29, 2020
1 parent 04a7fef commit a414a5f
Show file tree
Hide file tree
Showing 13 changed files with 798 additions and 2 deletions.
38 changes: 38 additions & 0 deletions src/main/i18n/templates/strings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,45 @@ misc.seconds.singularCompound = {0} second
# {0} = number of seconds
misc.seconds.pluralCompound = {0} seconds

misc.on = On
misc.off = Off

# {0} = the page
# {1} = the total pages
pageHeader = Page {0} of {1}
currentPage = Page {0}

observer.tools.title = Observer Tools
observer.tools.displayName = Tools
observer.tools.lore = Right-click to open the tool menu.

observer.tools.flyspeed = Fly Speed
observer.tools.nightvision = Night Vision
observer.tools.gamemode = Gamemode
observer.tools.visibility = Visibility

# {0} = the player's speed
observer.tools.flyspeed.lore = Current Speed: {0}

# {0} = the name of a gamemode
observer.tools.gamemode.lore = Current Gamemode: {0}

# {0} = the status (on/off)
observer.tools.nightvision.lore = Status: {0}

# {0} = the status of visibility setting
observer.tools.visibility.lore = Observer Visibility: {0}

# {0} = the command name
observer.tools.gamemode.warning = To toggle your gamemode back, use {0}
observer.tools.gamemode.hover = Click to open tool menu

observer.command.wrongmode = Sorry, this command is only for observers.

observer.tools.flyspeed.normal = Normal
observer.tools.flyspeed.fast = Fast
observer.tools.flyspeed.faster = Faster
observer.tools.flyspeed.hyperspeed = Hyperspeed

observer.tools.visibility.shown = Shown
observer.tools.visibility.hidden = Hidden
3 changes: 3 additions & 0 deletions src/main/java/tc/oc/pgm/PGMImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
import tc.oc.pgm.modules.SoundsMatchModule;
import tc.oc.pgm.modules.TimeLockModule;
import tc.oc.pgm.modules.ToolRepairModule;
import tc.oc.pgm.observers.ObserverToolsMatchModule;
import tc.oc.pgm.picker.PickerModule;
import tc.oc.pgm.portals.PortalModule;
import tc.oc.pgm.prefix.PrefixRegistry;
Expand Down Expand Up @@ -422,6 +423,7 @@ private ModuleRegistry createPGMModuleFactory() throws Throwable {
factory.register(JoinMatchModule.class, new JoinMatchModule.Factory());
factory.register(CycleMatchModule.class, new CycleMatchModule.Factory());
factory.register(SoundsMatchModule.class, new SoundsMatchModule.Factory());
factory.register(ObserverToolsMatchModule.class, new ObserverToolsMatchModule.Factory());

return factory;
}
Expand Down Expand Up @@ -495,6 +497,7 @@ private void registerCommands() {
node.registerCommands(new MapPoolCommands());
node.registerCommands(new SettingCommands());
node.registerCommands(new ModerationCommands());
node.registerCommands(new ObserverCommands());

new BukkitIntake(this, graph).register();
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/tc/oc/pgm/api/player/MatchPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.UUID;
import javax.annotation.Nullable;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.PlayerInventory;
Expand Down Expand Up @@ -194,6 +195,13 @@ public interface MatchPlayer extends Audience, Named, Tickable, InventoryHolder
*/
void applyKit(Kit kit, boolean force);

/**
* Set the {@link MatchPlayer}'s {@link GameMode}.
*
* @param gameMode - The gamemode to set
*/
void setGameMode(GameMode gameMode);

/**
* Get the protocol version of the {@link MatchPlayer}'s client
*
Expand All @@ -210,6 +218,13 @@ public interface MatchPlayer extends Audience, Named, Tickable, InventoryHolder

String getPrefixedName();

/**
* Get the {@link GameMode} of the {@link MatchPlayer}.
*
* @return the current {@link GameMode}
*/
GameMode getGameMode();

@Override
PlayerInventory getInventory();

Expand Down
33 changes: 33 additions & 0 deletions src/main/java/tc/oc/pgm/commands/ObserverCommands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package tc.oc.pgm.commands;

import app.ashcon.intake.Command;
import app.ashcon.intake.CommandException;
import java.util.Optional;
import org.bukkit.command.CommandSender;
import tc.oc.component.render.ComponentRenderers;
import tc.oc.component.types.PersonalizedTranslatable;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.observers.ObserverToolsMatchModule;

public class ObserverCommands {

@Command(
aliases = {"tools", "observertools", "ot"},
desc = "Open the observer tool menu")
public static void openObserverToolMenu(CommandSender sender, MatchPlayer player)
throws CommandException {
if (player.isObserving()) {
Optional<ObserverToolsMatchModule> tools =
player.getMatch().getModule(ObserverToolsMatchModule.class);

tools.ifPresent(
ot -> {
ot.openMenu(player);
});
} else {
throw new CommandException(
ComponentRenderers.toLegacyText(
new PersonalizedTranslatable("observer.command.wrongmode"), sender));
}
}
}
2 changes: 1 addition & 1 deletion src/main/java/tc/oc/pgm/kits/GameModeKit.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public GameModeKit(GameMode mode) {

@Override
protected void applyPostEvent(MatchPlayer player, boolean force, List<ItemStack> displacedItems) {
player.getBukkit().setGameMode(gameMode);
player.setGameMode(gameMode);
}
}
12 changes: 11 additions & 1 deletion src/main/java/tc/oc/pgm/match/MatchPlayerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public void resetGamemode() {
logger.fine("Refreshing gamemode as " + (participating ? "participant" : "observer"));

if (!participating) getBukkit().leaveVehicle();
this.getBukkit().setGameMode(participating ? GameMode.SURVIVAL : GameMode.CREATIVE);
setGameMode(participating ? GameMode.SURVIVAL : GameMode.CREATIVE);
this.getBukkit().setAllowFlight(!participating);
this.getBukkit().spigot().setAffectsSpawning(participating);
this.getBukkit().spigot().setCollidesWithEntities(participating);
Expand Down Expand Up @@ -299,6 +299,11 @@ public void setFrozen(boolean yes) {
}
}

@Override
public void setGameMode(GameMode gameMode) {
getBukkit().setGameMode(gameMode);
}

/**
* When max health is lowered by an item attribute or potion effect, the client can go into an
* inconsistent state that has strange effects, like the death animation playing when the player
Expand Down Expand Up @@ -370,6 +375,11 @@ public String getPrefixedName() {
return PGM.get().getPrefixRegistry().getPrefixedName(getBukkit(), getParty());
}

@Override
public GameMode getGameMode() {
return getBukkit().getGameMode();
}

@Override
public void tick(Match match, Tick tick) {
final Player bukkit = getBukkit();
Expand Down
151 changes: 151 additions & 0 deletions src/main/java/tc/oc/pgm/menu/InventoryMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package tc.oc.pgm.menu;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.util.WeakHashMap;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import tc.oc.component.render.ComponentRenderers;
import tc.oc.component.types.PersonalizedTranslatable;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.observers.ObserverToolsMatchModule;
import tc.oc.util.StringUtils;

public abstract class InventoryMenu {

protected static final int ROW_WIDTH = 9; // Number of columns per row
protected static final int MAX_ROWS = 6; // Max allowed row size

private final WeakHashMap<MatchPlayer, InventoryMenu> viewing =
new WeakHashMap<>(); // Map of players who are viewing the gui, along with the menu
private final String title; // Title of the inventory
private final int rows; // The # of rows in the inventory

/**
* InventoryMenu: An easy way to make an GUI menu that users can interact with.
*
* <p>See {@link ObserverToolsMatchModule} for an example on implementation
*
* <p>Note: Code here was extracted from PickerMatchModule to allow for reuse
*
* @param title - A string that will be translated and made the inventory title
* @param rows - The amount of rows the inventory will be created with
*/
public InventoryMenu(String title, int rows) {
checkArgument(rows > 0 && rows <= MAX_ROWS, "Row size must be between 1 and " + MAX_ROWS);
this.title = checkNotNull(title);
this.rows = rows;
}

/** Defines how the GUI will display the layout */
public abstract ItemStack[] createWindowContents(final MatchPlayer player);

public String getTranslatedTitle(MatchPlayer player) {
return ComponentRenderers.toLegacyText(new PersonalizedTranslatable(title), player.getBukkit());
}

public boolean isViewing(MatchPlayer player) {
return viewing.containsKey(player);
}

public void display(MatchPlayer player) {
this.showWindow(player);
this.viewing.put(player, this);
}

public void remove(MatchPlayer player) {
this.viewing.remove(player);
}

public void refreshAll() {
viewing.keySet().forEach(this::refreshWindow);
}

private int getInventorySize() {
return ROW_WIDTH * rows;
}

/**
* Open the window for the given player, or refresh its contents if they already have it open, and
* return the current contents.
*
* <p>If the window is currently open but too small to hold the current contents, it will be
* closed and reopened.
*
* <p>If the player is not currently allowed to have the window open, close any window they have
* open and return null.
*/
private @Nullable Inventory showWindow(MatchPlayer player) {
ItemStack[] contents = createWindowContents(player);
Inventory inv = getOpenWindow(player);
if (inv != null && inv.getSize() < contents.length) {
inv = null;
closeWindow(player);
}
if (inv == null) {
inv = openWindow(player, contents);
} else {
inv.setContents(contents);
}
return inv;
}

/**
* If the given player currently has the window open, refresh its contents and return the updated
* inventory. The window will be closed and reopened if it is too small to hold the current
* contents.
*
* <p>If the window is open but should be closed, close it and return null.
*
* <p>If the player does not have the window open, return null.
*/
public @Nullable Inventory refreshWindow(MatchPlayer player) {
Inventory inv = getOpenWindow(player);
if (inv != null) {
ItemStack[] contents = createWindowContents(player);
if (inv.getSize() < contents.length) {
closeWindow(player);
inv = openWindow(player, contents);
} else {
inv.setContents(contents);
}
}
return inv;
}

/**
* Return the inventory of the given player's currently open window, or null if the player does
* not have the window open.
*/
private @Nullable Inventory getOpenWindow(MatchPlayer player) {
if (isViewing(player)) {
return player.getBukkit().getOpenInventory().getTopInventory();
}
return null;
}

/** Close any window that is currently open for the given player */
private void closeWindow(MatchPlayer player) {
if (isViewing(player)) {
player.getBukkit().closeInventory();
}
}

/** Open a new window for the given player displaying the given contents */
private Inventory openWindow(MatchPlayer player, ItemStack[] contents) {
closeWindow(player);
Inventory inv =
Bukkit.createInventory(
player.getBukkit(),
getInventorySize(),
StringUtils.truncate(getTranslatedTitle(player), 32));

inv.setContents(contents);
player.getBukkit().openInventory(inv);
viewing.put(player, this);
return inv;
}
}
40 changes: 40 additions & 0 deletions src/main/java/tc/oc/pgm/menu/InventoryMenuItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package tc.oc.pgm.menu;

import java.util.List;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import tc.oc.component.Component;
import tc.oc.component.render.ComponentRenderers;
import tc.oc.pgm.api.player.MatchPlayer;

public interface InventoryMenuItem {

public Component getName();

public ChatColor getColor();

public List<String> getLore(MatchPlayer player);

public Material getMaterial(MatchPlayer player);

public void onInventoryClick(InventoryMenu menu, MatchPlayer player);

default ItemStack createItem(MatchPlayer player) {
ItemStack stack = new ItemStack(getMaterial(player));
ItemMeta meta = stack.getItemMeta();

meta.setDisplayName(
getColor()
+ ChatColor.BOLD.toString()
+ ComponentRenderers.toLegacyText(getName(), player.getBukkit()));
meta.setLore(getLore(player));
meta.addItemFlags(ItemFlag.values());

stack.setItemMeta(meta);

return stack;
}
}
Loading

0 comments on commit a414a5f

Please sign in to comment.