Tic Tac Toe gadget

This commit is contained in:
Sam 2017-10-24 17:43:09 +01:00 committed by Alexander Meech
parent 9684bf7a6d
commit 20885bac4e
4 changed files with 510 additions and 66 deletions

View File

@ -126,6 +126,7 @@ import mineplex.core.gadget.gadgets.item.ItemFlowerGift;
import mineplex.core.gadget.gadgets.item.ItemFreezeCannon;
import mineplex.core.gadget.gadgets.item.ItemLovePotion;
import mineplex.core.gadget.gadgets.item.ItemMelonLauncher;
import mineplex.core.gadget.gadgets.item.ItemOAndX;
import mineplex.core.gadget.gadgets.item.ItemPaintballGun;
import mineplex.core.gadget.gadgets.item.ItemPaintbrush;
import mineplex.core.gadget.gadgets.item.ItemPartyPopper;
@ -501,6 +502,7 @@ public class GadgetManager extends MiniPlugin
addGadget(new ItemLovePotion(this));
addGadget(new ItemFlowerGift(this));
addGadget(new ItemCandy(this));
addGadget(new ItemOAndX(this));
// Costume
addGadget(new OutfitRaveSuitHelmet(this));

View File

@ -23,9 +23,10 @@ public class ItemDuelingSword extends ItemGadget
},
CostConstants.NO_LORE,
Material.GOLD_SWORD, (byte)0,
1000, new Ammo("Dueling Sword", "10 Swords", Material.WOOD_SWORD, (byte)0, new String[] { C.cWhite + "10 Swords to duel with" }, 1000, 10), true);
1000, new Ammo("Dueling Sword", "10 Swords", Material.WOOD_SWORD, (byte)0, new String[] { C.cWhite + "10 Swords to duel with" }, 1000, 10));
setHidden(true);
setPreserveStaticItem();
}
@Override

View File

@ -0,0 +1,437 @@
package mineplex.core.gadget.gadgets.item;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import mineplex.core.arcadeevents.CoreGameStartEvent;
import mineplex.core.common.Pair;
import mineplex.core.common.jsonchat.ClickEvent;
import mineplex.core.common.jsonchat.HoverEvent;
import mineplex.core.common.jsonchat.JsonMessage;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilParticle;
import mineplex.core.common.util.UtilParticle.ParticleType;
import mineplex.core.common.util.UtilParticle.ViewDist;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilTextMiddle;
import mineplex.core.common.util.UtilTime;
import mineplex.core.gadget.GadgetManager;
import mineplex.core.gadget.types.ItemGadget;
import mineplex.core.gadget.util.CostConstants;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.recharge.Recharge;
public class ItemOAndX extends ItemGadget
{
private static final long COOLDOWN_USE = TimeUnit.SECONDS.toMillis(30);
private static final long COOLDOWN_INVITE = TimeUnit.SECONDS.toMillis(8);
private static final String COMMAND = "/play-tic-tac-toe";
private static final int BOARD_SIZE = 9;
private static final int[][] TILE_LOCATIONS =
{
{
-1, -1,
},
{
-1, 0,
},
{
-1, 1
},
{
0, -1
},
{
0, 0
},
{
0, 1,
},
{
1, -1
},
{
1, 0
},
{
1, 1
}
};
private static final ItemStack FLOOR = new ItemStack(Material.WOOL);
private static final ItemStack DEFAULT_TILE = new ItemStack(Material.WOOL, 1, (short) 0, (byte) 15);
private final Map<String, Pair<String, Long>> _invites;
private final Set<GameBoard> _gameBoards;
public ItemOAndX(GadgetManager manager)
{
super(manager, "Tic Tac Toe", new String[]
{
C.cWhite + "Play Tic Tac Toe",
C.cWhite + "with other players!",
}, CostConstants.NO_LORE, Material.CARPET, (byte) 14, COOLDOWN_INVITE, null);
_invites = new HashMap<>(3);
_gameBoards = new HashSet<>(3);
Free = false;
}
@Override
public boolean activatePreprocess(Player player)
{
for (GameBoard board : _gameBoards)
{
if (board.PlayerA.equals(player) || board.PlayerB.equals(player))
{
return false;
}
}
Location location = player.getLocation();
//TODO implement space check
return true;
}
@Override
public void ActivateCustom(Player player)
{
for (Player nearby : UtilPlayer.getNearby(player.getLocation(), 3))
{
if (player.equals(nearby))
{
continue;
}
sendGameInvite(nearby, player);
}
}
private void sendGameInvite(Player invitee, Player inviter)
{
inviter.sendMessage(F.main(Manager.getName(), "You challenged " + F.name(invitee.getName()) + " to play " + F.name(getName()) + "!"));
new JsonMessage(F.main(Manager.getName(), F.color("CLICK HERE", C.cYellowB) + " to play " + F.name(getName()) + " with " + F.name(inviter.getName()) + "!"))
.hover(HoverEvent.SHOW_TEXT, C.cYellow + "Click to play " + F.name(getName()) + " with " + F.name(inviter.getName()))
.click(ClickEvent.RUN_COMMAND, COMMAND + " " + inviter.getName())
.sendToPlayer(invitee);
invitee.playSound(invitee.getLocation(), Sound.NOTE_PIANO, 1, 1);
inviter.playSound(inviter.getLocation(), Sound.NOTE_PIANO, 1, 1);
_invites.put(inviter.getName(), Pair.create(invitee.getName(), System.currentTimeMillis()));
}
private void startGame(Player invitee, Player inviter)
{
invitee.sendMessage(F.main(Manager.getName(), F.name(inviter.getName()) + " challenged you to a game of " + F.name(getName()) + "!"));
inviter.sendMessage(F.main(Manager.getName(), "You challenged " + F.name(invitee.getName()) + " to a game of " + F.name(getName()) + "!"));
Location location = inviter.getLocation();
location.setYaw(0);
{
Location teleport = location.clone().add(0, 0, 2);
teleport.setYaw(180);
inviter.teleport(teleport);
}
{
Location teleport = location.clone().subtract(0, 0, 2);
teleport.setYaw(0);
invitee.teleport(teleport);
}
String title = C.cYellowB + getName();
UtilTextMiddle.display(title, "You are " + C.cGreenB + "Green", 0, 20, 5, invitee);
UtilTextMiddle.display(title, "You are " + C.cRedB + "Red", 0, 20, 5, inviter);
location.getWorld().playSound(location, Sound.LEVEL_UP, 1, 1);
_gameBoards.add(new GameBoard(inviter, invitee, location.subtract(0, 1.4, 0)));
}
@EventHandler
public void commandProcess(PlayerCommandPreprocessEvent event)
{
String command = event.getMessage();
String[] split = command.split(" ");
if (split.length != 2 || !split[0].equals(COMMAND))
{
return;
}
event.setCancelled(true);
Player caller = event.getPlayer();
String player = split[1];
Pair<String, Long> pair = _invites.get(player);
if (pair == null || !pair.getLeft().equals(caller.getName()) || UtilTime.elapsed(pair.getRight(), COOLDOWN_INVITE))
{
return;
}
Player inviter = UtilPlayer.searchExact(player);
if (inviter == null)
{
caller.sendMessage(F.main(Manager.getName(), "Looks like the player who challenged you is no longer online."));
return;
}
_invites.remove(player);
startGame(caller, inviter);
}
@EventHandler
public void armorStandInteract(EntityDamageByEntityEvent event)
{
if (!(event.getDamager() instanceof Player))
{
return;
}
Entity entity = event.getEntity();
Player player = (Player) event.getDamager();
for (GameBoard board : _gameBoards)
{
boolean playerA = board.PlayerA.equals(player);
boolean playerB = board.PlayerB.equals(player);
boolean playerATurn = board.Turn % 2 == 0;
if (!playerA && !playerB)
{
continue;
}
else if (playerA && !playerATurn || playerB && playerATurn)
{
player.sendMessage(F.main(Manager.getName(), "It's not your turn."));
continue;
}
for (int i = 0; i < board.Pieces.length; i++)
{
ArmorStand piece = board.Pieces[i];
if (!piece.equals(entity))
{
continue;
}
int ownership = board.OwnedPieces[i];
if (ownership != 0)
{
player.sendMessage(F.main(Manager.getName(), "That piece has already been claimed."));
}
else
{
board.OwnedPieces[i] = playerATurn ? 1 : 2;
piece.setHelmet(new ItemBuilder(Material.WOOL, (byte) (playerATurn ? 14 : 5)).build());
piece.getWorld().playSound(piece.getLocation(), Sound.NOTE_STICKS, 1, 1);
UtilParticle.PlayParticleToAll(ParticleType.CRIT, piece.getLocation().add(0, 1.5, 0), 0.25F, 0.25F, 0.25F, 0.05F, 5, ViewDist.NORMAL);
board.nextTurn();
Manager.runSyncTimer(new BukkitRunnable()
{
int iterations = 0;
@Override
public void run()
{
if (++iterations == 10)
{
cancel();
return;
}
piece.teleport(piece.getLocation().subtract(0, 0.025, 0));
}
}, 1, 1);
}
}
}
}
@EventHandler
public void gameStart(CoreGameStartEvent event)
{
_gameBoards.forEach(this::cleanupBoard);
}
private void cleanupBoard(GameBoard board)
{
Recharge.Instance.use(board.PlayerA, getName(), COOLDOWN_USE, true, true);
board.cleanup();
_gameBoards.remove(board);
}
private class GameBoard
{
final Player PlayerA;
final Player PlayerB;
final int[] OwnedPieces;
final ArmorStand[] Floor;
final ArmorStand[] Pieces;
final long StartTime;
int Turn;
boolean First = true;
GameBoard(Player playerA, Player playerB, Location center)
{
PlayerA = playerA;
PlayerB = playerB;
OwnedPieces = new int[BOARD_SIZE];
Arrays.fill(OwnedPieces, 0);
Floor = new ArmorStand[BOARD_SIZE];
Pieces = new ArmorStand[BOARD_SIZE];
for (int i = 0; i < Floor.length; i++)
{
int[] cords = TILE_LOCATIONS[i];
Location location = center.clone().add(cords[0], 0, cords[1]);
{
ArmorStand stand = location.getWorld().spawn(location, ArmorStand.class);
prepareStand(stand);
stand.setHelmet(FLOOR);
Floor[i] = stand;
}
{
ArmorStand stand = location.getWorld().spawn(location.add(0, 1.25, 0), ArmorStand.class);
prepareStand(stand);
stand.setSmall(true);
stand.setHelmet(DEFAULT_TILE);
Pieces[i] = stand;
}
}
StartTime = System.currentTimeMillis();
// Starting on turn 1 will make player B go first
if (Math.random() > 0.5)
{
Turn = 1;
}
nextTurn();
}
void nextTurn()
{
boolean playerATurn = Turn % 2 == 0;
if (hasDrawn())
{
UtilTextMiddle.display(C.cRedB + "DRAW", "", 10, 30, 10, PlayerA, PlayerB);
cleanupBoard(this);
return;
}
else if (hasWon(playerATurn ? 1 : 2))
{
Player winner = playerATurn ? PlayerA : PlayerB;
Player loser = playerATurn ? PlayerB : PlayerA;
UtilTextMiddle.display(C.cYellowB + "YOU WON", "", 10, 30, 10, winner);
UtilTextMiddle.display(C.cRedB + "YOU LOST", "", 10, 30, 10, loser);
winner.getWorld().playSound(winner.getLocation(), Sound.VILLAGER_YES, 1, 1);
loser.getWorld().playSound(winner.getLocation(), Sound.VILLAGER_NO, 1, 1);
cleanupBoard(this);
return;
}
else
{
Turn++;
playerATurn = !playerATurn;
}
if (First)
{
boolean finalPlayerATurn = playerATurn;
Manager.runSyncLater(() -> informTurn(finalPlayerATurn), 20);
}
else
{
informTurn(playerATurn);
}
}
private void informTurn(boolean playerATurn)
{
UtilTextMiddle.display("", C.cYellowB + "Your Turn", 5, 15, 5, playerATurn ? PlayerA : PlayerB);
}
void cleanup()
{
for (ArmorStand piece : Pieces)
{
piece.remove();
}
for (ArmorStand floor : Floor)
{
floor.remove();
}
}
boolean hasWon(int valueToCheck)
{
return (OwnedPieces[0] == valueToCheck && OwnedPieces[1] == valueToCheck && OwnedPieces[2] == valueToCheck) ||
(OwnedPieces[3] == valueToCheck && OwnedPieces[4] == valueToCheck && OwnedPieces[5] == valueToCheck) ||
(OwnedPieces[6] == valueToCheck && OwnedPieces[7] == valueToCheck && OwnedPieces[8] == valueToCheck) ||
(OwnedPieces[0] == valueToCheck && OwnedPieces[4] == valueToCheck && OwnedPieces[8] == valueToCheck) ||
(OwnedPieces[2] == valueToCheck && OwnedPieces[4] == valueToCheck && OwnedPieces[6] == valueToCheck) ||
(OwnedPieces[0] == valueToCheck && OwnedPieces[3] == valueToCheck && OwnedPieces[6] == valueToCheck) ||
(OwnedPieces[1] == valueToCheck && OwnedPieces[4] == valueToCheck && OwnedPieces[7] == valueToCheck) ||
(OwnedPieces[2] == valueToCheck && OwnedPieces[5] == valueToCheck && OwnedPieces[8] == valueToCheck);
}
boolean hasDrawn()
{
for (int piece : OwnedPieces)
{
if (piece == 0)
{
return false;
}
}
return true;
}
private void prepareStand(ArmorStand stand)
{
stand.setGravity(false);
stand.setVisible(false);
}
}
}

View File

@ -2,22 +2,20 @@ package mineplex.core.gadget.types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilBlock;
import mineplex.core.common.util.UtilGear;
import mineplex.core.common.util.UtilEvent;
import mineplex.core.common.util.UtilEvent.ActionType;
import mineplex.core.common.util.UtilInv;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
@ -30,28 +28,33 @@ import mineplex.core.recharge.Recharge;
public abstract class ItemGadget extends Gadget
{
private boolean _preserveStaticItem;
private Ammo _ammo;
protected long _recharge;
public ItemGadget(GadgetManager manager, String name, String[] desc, int cost, Material mat, byte data,
long recharge, Ammo ammo)
private final Ammo _ammo;
protected final long _recharge;
private boolean _preserveStaticItem;
public ItemGadget(GadgetManager manager, String name, String[] desc, int cost, Material mat, byte data, long recharge, Ammo ammo)
{
super(manager, GadgetType.ITEM, name, desc, cost, mat, data);
_ammo = ammo;
_recharge = recharge;
Free = true;
}
public ItemGadget(GadgetManager manager, String name, String[] desc, int cost, Material mat, byte data,
long recharge, Ammo ammo, boolean preserveStaticItem)
public abstract void ActivateCustom(Player player);
public boolean activatePreprocess(Player player)
{
this(manager, name, desc, cost, mat, data, recharge, ammo);
_preserveStaticItem = preserveStaticItem;
return true;
}
protected void setPreserveStaticItem()
{
_preserveStaticItem = true;
}
@Override
public void enableCustom(Player player, boolean message)
{
@ -75,43 +78,37 @@ public abstract class ItemGadget extends Gadget
_active.add(player);
List<String> itemLore = new ArrayList<String>();
List<String> itemLore = new ArrayList<>();
itemLore.addAll(Arrays.asList(getDescription()));
itemLore.add(C.cBlack);
itemLore.add(C.cWhite + "Your Ammo : " + Manager.getInventoryManager().Get(player).getItemCount(getName()));
player.getInventory().setItem(Manager.getActiveItemSlot(), ItemStackFactory.Instance.CreateStack(getDisplayMaterial(), getDisplayData(), 1, F.item(Manager.getInventoryManager().Get(player).getItemCount(getName()) + " " + getName())));
player.getInventory().setItem(Manager.getActiveItemSlot(), ItemStackFactory.Instance.CreateStack(getDisplayMaterial(), getDisplayData(), 1, F.item(Manager.getInventoryManager().Get(player).getItemCount(getName()) + " " + getName()), itemLore));
if (inform)
UtilPlayer.message(player, F.main("Gadget", "You equipped " + F.elem(getName()) + "."));
}
@EventHandler
public void orderThatChest(PlayerDropItemEvent event)
{
if (isActive(event.getPlayer()) && event.getItemDrop().getItemStack().getType() == getDisplayMaterial())
{
if (isActive(event.getPlayer()) && event.getItemDrop().getItemStack().getType() == getDisplayMaterial() || !_preserveStaticItem)
{
if (_preserveStaticItem)
return;
final Player player = event.getPlayer();
Bukkit.getScheduler().scheduleSyncDelayedTask(Manager.getPlugin(), new Runnable()
final Player player = event.getPlayer();
Manager.runSyncLater(() ->
{
public void run()
if (player.isOnline())
{
if (player.isOnline())
{
player.getInventory().remove(getDisplayMaterial());
player.getInventory().setItem(Manager.getActiveItemSlot(), ItemStackFactory.Instance.CreateStack(getDisplayMaterial(), getDisplayData(), 1, F.item(Manager.getInventoryManager().Get(player).getItemCount(getName()) + " " + getName())));
UtilInv.Update(player);
}
player.getInventory().remove(getDisplayMaterial());
player.getInventory().setItem(Manager.getActiveItemSlot(), ItemStackFactory.Instance.CreateStack(getDisplayMaterial(), getDisplayData(), 1, F.item(Manager.getInventoryManager().Get(player).getItemCount(getName()) + " " + getName())));
UtilInv.Update(player);
}
});
}, 1);
}
}
public void RemoveItem(Player player, boolean message)
protected void RemoveItem(Player player, boolean message)
{
if (_active.remove(player))
{
@ -121,7 +118,7 @@ public abstract class ItemGadget extends Gadget
UtilPlayer.message(player, F.main("Gadget", "You unequipped " + F.elem(getName()) + "."));
}
}
public Ammo getAmmo()
{
return _ammo;
@ -135,39 +132,41 @@ public abstract class ItemGadget extends Gadget
@EventHandler
public void Activate(PlayerInteractEvent event)
{
if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK)
return;
if (UtilBlock.usable(event.getClickedBlock()))
return;
if (!UtilGear.isMat(event.getPlayer().getItemInHand(), this.getDisplayMaterial()))
if (!UtilEvent.isAction(event, ActionType.R) || UtilBlock.usable(event.getClickedBlock()))
{
return;
}
Player player = event.getPlayer();
if (!isActive(player))
return;
event.setCancelled(true);
if (!isActive(player) || !IsItem(player))
{
return;
}
event.setCancelled(true);
if (!activatePreprocess(player))
{
return;
}
//Stock
if (!hasAmmo(player))
{
UtilPlayer.message(player, F.main("Gadget", "You do not have any " + getAmmo().getName() + " left."));
UtilPlayer.message(player, F.main(Manager.getName(), "You do not have any " + getAmmo().getName() + " left."));
ItemGadgetOutOfAmmoEvent ammoEvent = new ItemGadgetOutOfAmmoEvent(event.getPlayer(), this);
Bukkit.getServer().getPluginManager().callEvent(ammoEvent);
return;
}
//Recharge
if (!Recharge.Instance.use(player, getName(), getName(), _recharge, _recharge > 1000, true, false, true, "Cosmetics"))
{
UtilInv.Update(player);
return;
return;
}
ItemGadgetUseEvent itemGadgetUseEvent = new ItemGadgetUseEvent(player, this, 1);
@ -175,21 +174,26 @@ public abstract class ItemGadget extends Gadget
if (itemGadgetUseEvent.isCancelled())
{
UtilPlayer.message(player, F.main("Item", itemGadgetUseEvent.getCancelledMessage()));
UtilPlayer.message(player, F.main(Manager.getName(), itemGadgetUseEvent.getCancelledMessage()));
return;
}
Manager.getInventoryManager().addItemToInventory(player, getName(), -1);
player.getInventory().setItem(Manager.getActiveItemSlot(), ItemStackFactory.Instance.CreateStack(getDisplayMaterial(), getDisplayData(), 1, F.item(Manager.getInventoryManager().Get(player).getItemCount(getName()) + " " + getName())));
if (isUsingAmmo())
{
Manager.getInventoryManager().addItemToInventory(player, getName(), -1);
player.getInventory().setItem(Manager.getActiveItemSlot(), ItemStackFactory.Instance.CreateStack(getDisplayMaterial(), getDisplayData(), 1, F.item(Manager.getInventoryManager().Get(player).getItemCount(getName()) + " " + getName())));
}
ActivateCustom(event.getPlayer());
}
public boolean hasAmmo(Player player)
protected boolean hasAmmo(Player player)
{
return Manager.getInventoryManager().Get(player).getItemCount(getName()) > 0;
return !isUsingAmmo() || Manager.getInventoryManager().Get(player).getItemCount(getName()) > 0;
}
public abstract void ActivateCustom(Player player);
protected boolean isUsingAmmo()
{
return _ammo != null;
}
}