This commit is contained in:
disclearing 2019-01-21 21:55:58 +00:00
parent 275bbbd8ea
commit 8deb23f3ae
103 changed files with 10262 additions and 12 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

68
.gitignore vendored Normal file
View File

@ -0,0 +1,68 @@
# Eclipse
/.classpath
/.project
/.settings
# Netbeans
/nbproject
# We active maven!
/build.xml
# Maven
/target
/dependency-reduced-pom.xml
*/target
*/dependency-reduced-pom.xml
# Vim
.*.sw[a-p]
# Various other potential build files
/build
/bin
/dist
/manifest.mf
/MANIFEST.MF
/META-INF/MANIFEST.MF
git.properties
.ssh
key
key.pub
dependency-reduced-pom.xml
# Mac Filesystem Dust
.DS_Store
# IntelliJ IDEA
*.iml
*.ipr
*.iws
.idea/
#Libraries jar files
libraries/*.jar
=======
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

22
LICENSE
View File

@ -6,7 +6,7 @@
1. Definitions. 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, "License" shall mean the terms and conditions for active, reproduction,
and distribution as defined by Sections 1 through 9 of this document. and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by "Licensor" shall mean the copyright owner or entity authorized by
@ -24,8 +24,8 @@
exercising permissions granted by this License. exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, "Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation including but not limited to software lines code, documentation
source, and configuration files. lines, and configuration files.
"Object" form shall mean any form resulting from mechanical "Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but transformation or translation of a Source form, including but
@ -53,7 +53,7 @@
the copyright owner. For the purposes of this definition, "submitted" the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, communication on electronic mailing lists, lines code control systems,
and issue tracking systems that are managed by, or on behalf of, the and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise excluding communication that is conspicuously marked or otherwise
@ -74,7 +74,7 @@
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made, (except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work, active, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s) Contribution(s) alone or by combination of their Contribution(s)
@ -122,8 +122,8 @@
You may add Your own copyright statement to Your modifications and You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or for active, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use, for any such Derivative Works as a whole, provided Your active,
reproduction, and distribution of the Work otherwise complies with reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License. the conditions stated in this License.
@ -135,9 +135,9 @@
the terms of any separate license agreement you may have executed the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions. with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade 6. Trademarks. This License does not grant permission to active the trade
names, trademarks, service marks, or product names of the Licensor, names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the except as required for reasonable and customary active in describing the
origin of the Work and reproducing the content of the NOTICE file. origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or 7. Disclaimer of Warranty. Unless required by applicable law or
@ -156,7 +156,7 @@
negligent acts) or agreed to in writing, shall any Contributor be negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the result of this License or out of the active or inability to active the
Work (including but not limited to damages for loss of goodwill, Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor other commercial damages or losses), even if such Contributor
@ -189,7 +189,7 @@
Copyright [yyyy] [name of copyright owner] Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not active this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0

View File

@ -1 +1,2 @@
# praxi- # Praxi
The most configurable, efficient, and extensive practice plugin.

59
plugin/pom.xml Normal file
View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>me.joeleoli.praxi-optimized</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>plugin</artifactId>
<repositories>
<repository>
<id>sk89q-repo</id>
<url>http://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>fawe-repo</id>
<url>http://ci.athion.net/job/FastAsyncWorldEdit/ws/mvn/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>me.joeleoli.nucleus</groupId>
<artifactId>nucleus</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.joeleoli.fair-fight</groupId>
<artifactId>fair-fight</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>6.1.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-core</artifactId>
<version>6.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.boydti</groupId>
<artifactId>fawe-api</artifactId>
<version>latest</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,254 @@
package me.joeleoli.praxi;
import com.google.gson.JsonParser;
import java.util.Iterator;
import lombok.Getter;
import me.joeleoli.nucleus.Nucleus;
import me.joeleoli.nucleus.board.BoardManager;
import me.joeleoli.nucleus.command.CommandHandler;
import me.joeleoli.nucleus.config.ConfigCursor;
import me.joeleoli.nucleus.config.FileConfig;
import me.joeleoli.nucleus.listener.ListenerHandler;
import me.joeleoli.nucleus.settings.Settings;
import me.joeleoli.nucleus.util.InventoryUtil;
import me.joeleoli.nucleus.util.LocationUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.arena.ArenaType;
import me.joeleoli.praxi.arena.SharedArena;
import me.joeleoli.praxi.arena.StandaloneArena;
import me.joeleoli.praxi.board.PracticeBoardAdapter;
import me.joeleoli.praxi.command.param.ArenaParameterType;
import me.joeleoli.praxi.command.param.ArenaTypeParameterType;
import me.joeleoli.praxi.command.param.LadderParameterType;
import me.joeleoli.praxi.command.param.QueueParameterType;
import me.joeleoli.praxi.config.ConfigItem;
import me.joeleoli.praxi.events.EventManager;
import me.joeleoli.praxi.handler.PlayerMovementHandler;
import me.joeleoli.praxi.kit.Kit;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.mongo.PraxiMongo;
import me.joeleoli.praxi.player.PlayerHotbar;
import me.joeleoli.praxi.player.PracticeSetting;
import me.joeleoli.praxi.queue.Queue;
import me.joeleoli.praxi.queue.QueueThread;
import me.joeleoli.praxi.task.ExpBarCooldownTask;
import me.joeleoli.praxi.task.InventoryCleanupTask;
import me.joeleoli.praxi.task.InviteCleanupTask;
import me.joeleoli.praxi.task.RematchExpireRunnable;
import me.joeleoli.praxi.task.SaveDataTask;
import me.joeleoli.ragespigot.RageSpigot;
import org.bukkit.Difficulty;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
@Getter
public class Praxi extends PraxiProvider {
public static JsonParser PARSER = new JsonParser();
@Getter
private static Praxi instance;
private FileConfig mainConfig, arenaConfig, ladderConfig;
private PraxiMongo praxiMongo;
private EventManager eventManager;
private long startup = System.currentTimeMillis();
@Override
public void onEnable() {
instance = this;
this.mainConfig = new FileConfig(this, "config.yml");
this.arenaConfig = new FileConfig(this, "arenas.yml");
this.ladderConfig = new FileConfig(this, "ladders.yml");
this.praxiMongo = new PraxiMongo();
this.eventManager = new EventManager();
this.eventManager.load();
this.loadLadders();
this.loadArenas();
this.loadQueues();
PlayerHotbar.init();
Nucleus.getInstance().setBoardManager(new BoardManager(this, new PracticeBoardAdapter()));
CommandHandler.registerParameterType(Arena.class, new ArenaParameterType());
CommandHandler.registerParameterType(ArenaType.class, new ArenaTypeParameterType());
CommandHandler.registerParameterType(Ladder.class, new LadderParameterType());
CommandHandler.registerParameterType(Queue.class, new QueueParameterType());
CommandHandler.loadCommandsFromPackage(this, "me.joeleoli.praxi.command");
ListenerHandler.loadListenersFromPackage(this, "me.joeleoli.praxi.listener");
Settings.register(PracticeSetting.RECEIVE_DUEL_REQUESTS, true);
Settings.register(PracticeSetting.SHOW_SCOREBOARD, true);
Settings.register(PracticeSetting.ALLOW_SPECTATORS, true);
Settings.register(PracticeSetting.PING_FACTOR, false);
RageSpigot.INSTANCE.addMovementHandler(new PlayerMovementHandler());
new QueueThread().start();
this.getServer().getScheduler().runTaskTimer(this, new ExpBarCooldownTask(), 2L, 2L);
this.getServer().getScheduler().runTaskTimerAsynchronously(this, this, 0L, 10L);
this.getServer().getScheduler()
.runTaskTimerAsynchronously(this, new InventoryCleanupTask(), 20L * 5, 20L * 5);
this.getServer().getScheduler().runTaskTimerAsynchronously(this, new InviteCleanupTask(), 20L * 5, 20L * 5);
this.getServer().getScheduler()
.runTaskTimerAsynchronously(this, new SaveDataTask(), 20L * 60 * 5, 20L * 60 * 5);
this.getServer().getScheduler().runTaskTimerAsynchronously(this, new RematchExpireRunnable(), 20L * 3, 20L * 3);
this.getServer().getWorlds().forEach(world -> {
world.setDifficulty(Difficulty.HARD);
world.setTime(12000);
world.getEntities().forEach(entity -> {
if (!(entity instanceof Player)) {
entity.remove();
}
});
});
this.removeCrafting(Material.WORKBENCH);
this.removeCrafting(Material.STICK);
this.removeCrafting(Material.WOOD_PLATE);
this.removeCrafting(Material.WOOD_BUTTON);
this.removeCrafting(Material.SNOW_BLOCK);
}
private void loadLadders() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getLadderConfig(), "ladders");
for (String key : cursor.getKeys()) {
cursor.setPath("ladders." + key);
Ladder ladder = new Ladder(key);
ladder.setDisplayName(Style.translate(cursor.getString("display-name")));
ladder.setDisplayIcon(new ConfigItem(cursor, "display-icon").toItemStack());
ladder.setEnabled(cursor.getBoolean("enabled"));
ladder.setBuild(cursor.getBoolean("build"));
ladder.setSumo(cursor.getBoolean("sumo"));
ladder.setSpleef(cursor.getBoolean("spleef"));
ladder.setParkour(cursor.getBoolean("parkour"));
ladder.setRegeneration(cursor.getBoolean("regeneration"));
if (cursor.exists("hit-delay")) {
ladder.setHitDelay(cursor.getInt("hit-delay"));
}
if (cursor.exists("default-kit")) {
final ItemStack[] armor = InventoryUtil.deserializeInventory(cursor.getString("default-kit.armor"));
final ItemStack[] contents =
InventoryUtil.deserializeInventory(cursor.getString("default-kit.contents"));
ladder.setDefaultKit(new Kit(armor, contents));
}
if (cursor.exists("kit-editor.allow-potion-fill")) {
ladder.setAllowPotionFill(cursor.getBoolean("kit-editor.allow-potion-fill"));
}
if (cursor.exists("kit-editor.items")) {
for (String itemKey : cursor.getKeys("kit-editor.items")) {
ladder.getKitEditorItems().add(new ConfigItem(cursor, "kit-editor.items." + itemKey).toItemStack());
}
}
if (cursor.exists("kb-profile")) {
ladder.setKbProfile(cursor.getString("kb-profile"));
}
}
}
private void loadArenas() {
ConfigCursor cursor = new ConfigCursor(this.arenaConfig, "arenas");
if (cursor.exists()) {
for (String arenaName : cursor.getKeys()) {
cursor.setPath("arenas." + arenaName);
ArenaType arenaType = ArenaType.valueOf(cursor.getString("type"));
Location location1 = LocationUtil.deserialize(cursor.getString("cuboid.location1"));
Location location2 = LocationUtil.deserialize(cursor.getString("cuboid.location2"));
Arena arena;
if (arenaType == ArenaType.STANDALONE) {
arena = new StandaloneArena(arenaName, location1, location2);
} else if (arenaType == ArenaType.SHARED) {
arena = new SharedArena(arenaName, location1, location2);
} else {
continue;
}
if (cursor.exists("spawn1")) {
arena.setSpawn1(LocationUtil.deserialize(cursor.getString("spawn1")));
}
if (cursor.exists("spawn2")) {
arena.setSpawn2(LocationUtil.deserialize(cursor.getString("spawn2")));
}
if (cursor.exists("ladders")) {
for (String ladderName : cursor.getStringList("ladders")) {
arena.getLadders().add(ladderName);
}
}
if (arena.getType() == ArenaType.STANDALONE && cursor.exists("duplicates")) {
for (String duplicateId : cursor.getKeys("duplicates")) {
cursor.setPath("arenas." + arenaName + ".duplicates." + duplicateId);
location1 = LocationUtil.deserialize(cursor.getString("cuboid.location1"));
location2 = LocationUtil.deserialize(cursor.getString("cuboid.location2"));
Location spawn1 = LocationUtil.deserialize(cursor.getString("spawn1"));
Location spawn2 = LocationUtil.deserialize(cursor.getString("spawn2"));
Arena duplicate = new Arena(arenaName, ArenaType.DUPLICATE, location1, location2);
duplicate.setSpawn1(spawn1);
duplicate.setSpawn2(spawn2);
duplicate.setLadders(arena.getLadders());
((StandaloneArena) arena).getDuplicates().add(duplicate);
Arena.getArenas().add(duplicate);
}
}
Arena.getArenas().add(arena);
}
}
this.getLogger().info("Loaded " + Arena.getArenas().size() + " arenas");
}
private void loadQueues() {
for (Ladder ladder : Ladder.getLadders()) {
if (ladder.isEnabled()) {
new Queue(ladder, false);
new Queue(ladder, true);
}
}
}
private void removeCrafting(Material material) {
Iterator<Recipe> iterator = getServer().recipeIterator();
while (iterator.hasNext()) {
Recipe recipe = iterator.next();
if (recipe != null && recipe.getResult().getType() == material) {
iterator.remove();
}
}
}
}

View File

@ -0,0 +1,30 @@
package me.joeleoli.praxi;
import me.joeleoli.praxi.queue.Queue;
public interface PraxiAPI {
/**
* Gets the amount of players that are queueing.
*
* @return The amount of players that are queueing.
*/
int getQueueingCount();
/**
* Gets the amount of players that are fighting.
*
* @return The amount of players that are fighting.
*/
int getFightingCount();
/**
* Gets the amount of players in matches originating from a queue.
*
* @param queue The queue.
*
* @return The amount of players in matches originating from the given queue.
*/
int getFightingCount(Queue queue);
}

View File

@ -0,0 +1,90 @@
package me.joeleoli.praxi;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.player.PlayerState;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.praxi.queue.Queue;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public abstract class PraxiProvider extends JavaPlugin implements PraxiAPI, Runnable {
private int inQueues, inFights;
private Map<UUID, AtomicInteger> queueFightCounts = new HashMap<>();
@Override
public void run() {
int inQueues = 0;
int inFights = 0;
for (Player player : Bukkit.getOnlinePlayers()) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer != null) {
if (praxiPlayer.getState() == PlayerState.IN_QUEUE) {
inQueues++;
} else if (praxiPlayer.getState() == PlayerState.IN_MATCH) {
inFights++;
}
}
}
this.inQueues = inQueues;
this.inFights = inFights;
Map<UUID, AtomicInteger> queueFightCounts = new HashMap<>();
for (Match match : Match.getMatches()) {
if (match.getQueueId() != null && (match.isFighting() || match.isStarting())) {
Queue queue = Queue.getByUuid(match.getQueueId());
if (queue == null) {
continue;
}
if (queueFightCounts.containsKey(queue.getUuid())) {
queueFightCounts.get(queue.getUuid())
.addAndGet(match.isSoloMatch() ? 2 : match.getMatchPlayers().size());
} else {
queueFightCounts.put(
queue.getUuid(),
new AtomicInteger(match.isSoloMatch() ? 2 : match.getMatchPlayers().size())
);
}
}
}
this.queueFightCounts = queueFightCounts;
}
@Override
public int getQueueingCount() {
return this.inQueues;
}
@Override
public int getFightingCount() {
return this.inFights;
}
@Override
public int getFightingCount(Queue queue) {
if (queue == null) {
return 0;
}
AtomicInteger atomic = this.queueFightCounts.get(queue.getUuid());
if (atomic == null) {
return 0;
} else {
return atomic.intValue();
}
}
}

View File

@ -0,0 +1,100 @@
package me.joeleoli.praxi.arena;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.praxi.cuboid.Cuboid;
import me.joeleoli.praxi.ladder.Ladder;
import org.bukkit.Location;
@Getter
@Setter
public class Arena extends Cuboid {
@Getter
private static List<Arena> arenas = new ArrayList<>();
protected String name;
protected Location spawn1;
protected Location spawn2;
protected boolean active;
private ArenaType type;
private List<String> ladders = new ArrayList<>();
public Arena(String name, ArenaType type, Location location1, Location location2) {
super(location1, location2);
this.name = name;
this.type = type;
}
public static Arena getByName(String name) {
for (Arena arena : arenas) {
if (arena.getType() != ArenaType.DUPLICATE && arena.getName() != null &&
arena.getName().equalsIgnoreCase(name)) {
return arena;
}
}
return null;
}
public static Arena getRandom(Ladder ladder) {
final List<Arena> _arenas = arenas.stream().filter(arena -> arena.isSetup() &&
arena.getLadders().contains(ladder.getName()) &&
((ladder.isBuild() && !arena.isActive() &&
(arena.getType() == ArenaType.STANDALONE ||
arena.getType() == ArenaType.DUPLICATE)) ||
(!ladder.isBuild() &&
arena.getType() == ArenaType.SHARED)))
.collect(Collectors.toList());
if (_arenas.isEmpty()) {
return null;
}
return _arenas.get(ThreadLocalRandom.current().nextInt(_arenas.size()));
}
public int getMaxBuildHeight() {
int highest = (int) (this.spawn1.getY() >= this.spawn2.getY() ? this.spawn1.getY() : this.spawn2.getY());
return highest + 5;
}
public Location getSpawn1() {
if (this.spawn1 == null) {
return null;
}
return this.spawn1.clone();
}
public Location getSpawn2() {
if (this.spawn2 == null) {
return null;
}
return this.spawn2.clone();
}
public void setActive(boolean active) {
if (this.type != ArenaType.SHARED) {
this.active = active;
}
}
public void save() {
}
public void delete() {
}
public boolean isSetup() {
return this.spawn1 != null && this.spawn2 != null;
}
}

View File

@ -0,0 +1,12 @@
package me.joeleoli.praxi.arena;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum ArenaType {
STANDALONE,
SHARED,
DUPLICATE
}

View File

@ -0,0 +1,46 @@
package me.joeleoli.praxi.arena;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.config.ConfigCursor;
import me.joeleoli.nucleus.util.LocationUtil;
import me.joeleoli.praxi.Praxi;
import org.bukkit.Location;
@Getter
@Setter
public class SharedArena extends Arena {
public SharedArena(String name, Location location1, Location location2) {
super(name, ArenaType.SHARED, location1, location2);
}
@Override
public void save() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getArenaConfig(), "arenas." + this.name);
cursor.set(null);
cursor.set("type", ArenaType.SHARED.name());
if (this.spawn1 != null) {
cursor.set("spawn1", LocationUtil.serialize(this.spawn1));
}
if (this.spawn2 != null) {
cursor.set("spawn2", LocationUtil.serialize(this.spawn2));
}
cursor.set("cuboid.location1", LocationUtil.serialize(this.getLowerCorner()));
cursor.set("cuboid.location2", LocationUtil.serialize(this.getUpperCorner()));
cursor.save();
}
@Override
public void delete() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getArenaConfig(), "arenas." + this.name);
cursor.set(null);
cursor.save();
}
}

View File

@ -0,0 +1,58 @@
package me.joeleoli.praxi.arena;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.Getter;
import me.joeleoli.nucleus.config.ConfigCursor;
import me.joeleoli.nucleus.util.LocationUtil;
import me.joeleoli.praxi.Praxi;
import org.bukkit.Location;
@Getter
public class StandaloneArena extends Arena {
private List<Arena> duplicates = new ArrayList<>();
public StandaloneArena(String name, Location location1, Location location2) {
super(name, ArenaType.STANDALONE, location1, location2);
}
@Override
public void save() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getArenaConfig(), "arenas." + this.name);
cursor.set(null);
cursor.set("type", ArenaType.STANDALONE.name());
cursor.set("spawn1", LocationUtil.serialize(this.spawn1));
cursor.set("spawn2", LocationUtil.serialize(this.spawn2));
cursor.set("cuboid.location1", LocationUtil.serialize(this.getLowerCorner()));
cursor.set("cuboid.location2", LocationUtil.serialize(this.getUpperCorner()));
cursor.set("ladders", this.getLadders());
if (!this.duplicates.isEmpty()) {
AtomicInteger i = new AtomicInteger();
this.duplicates.forEach(duplicate -> {
cursor.setPath("arenas." + this.name + ".duplicates." + i.intValue());
cursor.set("cuboid.location1", LocationUtil.serialize(duplicate.getLowerCorner()));
cursor.set("cuboid.location2", LocationUtil.serialize(duplicate.getUpperCorner()));
cursor.set("spawn1", LocationUtil.serialize(duplicate.getSpawn1()));
cursor.set("spawn2", LocationUtil.serialize(duplicate.getSpawn2()));
i.getAndIncrement();
});
}
cursor.save();
}
@Override
public void delete() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getArenaConfig(), "arenas." + this.name);
cursor.set(null);
cursor.save();
}
}

View File

@ -0,0 +1,176 @@
package me.joeleoli.praxi.arena.generator;
import com.boydti.fawe.util.TaskManager;
import java.io.File;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.Nucleus;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.arena.ArenaType;
import me.joeleoli.praxi.arena.SharedArena;
import me.joeleoli.praxi.arena.StandaloneArena;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
@AllArgsConstructor
public class ArenaGenerator {
private String name;
private World world;
private Schematic schematic;
private ArenaType type;
public void generate(File file, StandaloneArena parentArena) {
if (Arena.getByName(this.name) != null) {
this.name = name + Nucleus.RANDOM.nextInt(1000);
}
this.log("Generating " + this.type.name() + " " + this.name + " arena...");
int range = 500;
int attempts = 0;
int preciseX = Nucleus.RANDOM.nextInt(range);
int preciseZ = Nucleus.RANDOM.nextInt(range);
if (Nucleus.RANDOM.nextBoolean()) {
preciseX = -preciseX;
}
if (Nucleus.RANDOM.nextBoolean()) {
preciseZ = -preciseZ;
}
top:
while (true) {
attempts++;
if (attempts >= 5) {
preciseX = Nucleus.RANDOM.nextInt(range);
preciseZ = Nucleus.RANDOM.nextInt(range);
if (Nucleus.RANDOM.nextBoolean()) {
preciseX = -preciseX;
}
if (Nucleus.RANDOM.nextBoolean()) {
preciseZ = -preciseZ;
}
range += 500;
this.log("Increased range to: " + range);
}
if (this.world.getBlockAt(preciseX, 72, preciseZ) == null) {
continue;
}
final int minX = preciseX - this.schematic.getClipBoard().getWidth() - 200;
final int maxX = preciseX + this.schematic.getClipBoard().getWidth() + 200;
final int minZ = preciseZ - this.schematic.getClipBoard().getLength() - 200;
final int maxZ = preciseZ + this.schematic.getClipBoard().getLength() + 200;
final int minY = 72;
final int maxY = 72 + this.schematic.getClipBoard().getHeight();
for (int x = minX; x < maxX; x++) {
for (int z = minZ; z < maxZ; z++) {
for (int y = minY; y < maxY; y++) {
if (this.world.getBlockAt(x, y, z).getType() != Material.AIR) {
continue top;
}
}
}
}
final Location minCorner = new Location(this.world, minX, minY, minZ);
final Location maxCorner = new Location(this.world, maxX, maxY, maxZ);
final int finalPreciseX = preciseX;
final int finalPreciseZ = preciseZ;
TaskManager.IMP.async(() -> {
try {
new Schematic(file).pasteSchematic(this.world, finalPreciseX, 76, finalPreciseZ);
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
final Arena arena;
if (this.type == ArenaType.STANDALONE) {
arena = new StandaloneArena(this.name, minCorner, maxCorner);
this.type = ArenaType.DUPLICATE;
for (int i = 0; i < 5; i++) {
TaskUtil.run(() -> this.generate(file, (StandaloneArena) arena));
}
} else if (this.type == ArenaType.DUPLICATE) {
arena = new Arena(this.name, ArenaType.DUPLICATE, minCorner, maxCorner);
parentArena.getDuplicates().add(arena);
} else {
arena = new SharedArena(this.name, minCorner, maxCorner);
}
helper:
for (int x = minX; x < maxX; x++) {
for (int z = minZ; z < maxZ; z++) {
for (int y = minY; y < maxY; y++) {
if (this.world.getBlockAt(x, y, z).getType() == Material.SPONGE) {
final Block origin = this.world.getBlockAt(x, y, z);
final Block up = origin.getRelative(BlockFace.UP, 1);
if (up.getState() instanceof Sign) {
final Sign sign = (Sign) up.getState();
final float pitch = Float.valueOf(sign.getLine(0));
final float yaw = Float.valueOf(sign.getLine(1));
final Location loc =
new Location(origin.getWorld(), origin.getX(), origin.getY(), origin.getZ(),
yaw, pitch
);
TaskUtil.run(() -> {
up.setType(Material.AIR);
origin.setType(origin.getRelative(BlockFace.NORTH).getType());
});
if (arena.getSpawn1() == null) {
arena.setSpawn1(loc);
} else if (arena.getSpawn2() == null) {
arena.setSpawn2(loc);
break helper;
}
}
}
}
}
}
arena.save();
Arena.getArenas().add(arena);
});
this.log(String.format("Pasted schematic at %1$s, %2$s, %3$s", preciseX, 76, preciseZ));
return;
}
}
private void log(String message) {
Nucleus.getInstance().getLogger().info("[ArenaGen] " + message);
}
}

View File

@ -0,0 +1,42 @@
package me.joeleoli.praxi.arena.generator;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.schematic.SchematicFormat;
import com.sk89q.worldedit.world.DataException;
import java.io.File;
import java.io.IOException;
import lombok.Getter;
import me.joeleoli.nucleus.Nucleus;
import org.bukkit.World;
@Getter
public class Schematic {
private CuboidClipboard clipBoard;
public Schematic(File file) throws IOException {
SchematicFormat format = SchematicFormat.MCEDIT;
try {
this.clipBoard = format.load(file);
} catch (DataException e) {
Nucleus.getInstance().getLogger().severe("Failed to load schematic...");
}
}
public void pasteSchematic(World world, int x, int y, int z) {
Vector pastePos = new Vector(x, y, z);
EditSession editSession = new EditSession(new BukkitWorld(world), 999999);
try {
this.clipBoard.place(editSession, pastePos, true);
} catch (MaxChangedBlocksException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,91 @@
package me.joeleoli.praxi.arena.selection;
import java.util.Arrays;
import lombok.Data;
import lombok.NonNull;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.cuboid.Cuboid;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
@Data
public class Selection {
public static final ItemStack SELECTION_WAND;
private static final String SELECTION_METADATA_KEY = "CLAIM_SELECTION";
static {
ItemStack itemStack = new ItemStack(Material.GOLD_AXE);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setDisplayName(Style.GOLD + Style.BOLD + "Selection Wand");
itemMeta.setLore(Arrays.asList(
Style.YELLOW + "Left-click to set position 1.",
Style.YELLOW + "Right-click to set position 2."
));
itemStack.setItemMeta(itemMeta);
SELECTION_WAND = itemStack;
}
@NonNull
private Location point1;
@NonNull
private Location point2;
/**
* Private, so that we can create a new instance in the Selection#createOrGetSelection method.
*/
private Selection() {
}
/**
* Selections are stored in the player's metadata. This method removes the need to active Bukkit Metadata API calls
* all over the place.
* <p>
* This method can be modified structurally as needed, the plugin only accepts Selection objects via this method.
*
* @param player the player for whom to grab the Selection object for
*
* @return selection object, either new or created
*/
public static Selection createOrGetSelection(Player player) {
if (player.hasMetadata(SELECTION_METADATA_KEY)) {
return (Selection) player.getMetadata(SELECTION_METADATA_KEY).get(0).value();
}
Selection selection = new Selection();
player.setMetadata(SELECTION_METADATA_KEY, new FixedMetadataValue(Praxi.getInstance(), selection));
return selection;
}
/**
* @return the cuboid
*/
public Cuboid getCuboid() {
return new Cuboid(point1, point2);
}
/**
* @return if the Selection can form a full cuboid object
*/
public boolean isFullObject() {
return point1 != null && point2 != null;
}
/**
* Resets both locations in the Selection
*/
public void clear() {
point1 = null;
point2 = null;
}
}

View File

@ -0,0 +1,168 @@
package me.joeleoli.praxi.board;
import java.util.ArrayList;
import java.util.List;
import me.joeleoli.nucleus.Nucleus;
import me.joeleoli.nucleus.NucleusAPI;
import me.joeleoli.nucleus.board.Board;
import me.joeleoli.nucleus.board.BoardAdapter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TimeUtil;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.player.PracticeSetting;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.praxi.queue.Queue;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Scoreboard;
public class PracticeBoardAdapter implements BoardAdapter {
@Override
public String getTitle(Player player) {
if (Nucleus.getInstance().getRave() != null) {
return Nucleus.getInstance().getRave().getRaveTask().getTitle();
}
return Style.PINK + Style.BOLD + "MineXD ";
}
@Override
public List<String> getScoreboard(Player player, Board board) {
if (Nucleus.getInstance().getRave() != null) {
return Nucleus.getInstance().getRave().getRaveTask().getLines();
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (!NucleusAPI.<Boolean>getSetting(player, PracticeSetting.SHOW_SCOREBOARD)) {
return null;
}
final List<String> toReturn = new ArrayList<>();
if (praxiPlayer.isInLobby()) {
toReturn.add(Style.YELLOW + "Online: " + Style.PINK + Bukkit.getOnlinePlayers().size());
toReturn.add(Style.YELLOW + "Fighting: " + Style.PINK + Praxi.getInstance().getFightingCount());
toReturn.add(Style.YELLOW + "Queueing: " + Style.PINK + Praxi.getInstance().getQueueingCount());
if (praxiPlayer.getParty() != null) {
toReturn.add(Style.YELLOW + "Your Party: " + Style.PINK + praxiPlayer.getParty().getTeamPlayers().size());
}
if (!Praxi.getInstance().getEventManager().getEventCooldown().hasExpired()) {
toReturn.add(Style.YELLOW + "Event Cooldown: " + Style.PINK + TimeUtil.millisToTimer(
Praxi.getInstance().getEventManager().getEventCooldown().getRemaining()));
}
} else if (praxiPlayer.isInQueue()) {
final Queue queue = praxiPlayer.getQueuePlayer().getQueue();
toReturn.add(Style.YELLOW + "Queue:");
toReturn.add(" " + Style.PINK + (queue.isRanked() ? "Ranked" : "Unranked") + " " +
queue.getLadder().getName());
toReturn.add(Style.YELLOW + "Time:");
toReturn.add(" " + Style.PINK + TimeUtil.millisToTimer(praxiPlayer.getQueuePlayer().getPassed()));
if (queue.isRanked()) {
toReturn.add(Style.YELLOW + "Range:");
toReturn.add(" " + Style.PINK + praxiPlayer.getQueuePlayer().getMinRange() + " -> " +
praxiPlayer.getQueuePlayer().getMaxRange());
}
} else if (praxiPlayer.isInMatch()) {
final Match match = praxiPlayer.getMatch();
if (match == null) {
return null;
}
if (match.isSoloMatch()) {
final MatchPlayer opponent = match.getOpponentMatchPlayer(player);
toReturn.add(Style.YELLOW + "Opponent: " + Style.PINK + opponent.getName());
toReturn.add(Style.YELLOW + "Duration: " + Style.PINK + match.getDuration());
if (match.isFighting()) {
toReturn.add("");
toReturn.add(Style.YELLOW + "Your Ping: " + Style.PINK + player.getPing() + "ms");
toReturn.add(Style.YELLOW + "Their Ping: " + Style.PINK + opponent.getPing() + "ms");
}
} else if (match.isTeamMatch()) {
toReturn.add(Style.YELLOW + "Duration: " + Style.PINK + match.getDuration());
toReturn.add(Style.YELLOW + "Opponents: " + Style.PINK + match.getOpponentsLeft(player) + "/" +
match.getOpponentTeam(player).getTeamPlayers().size());
if (match.getTeam(player).getTeamPlayers().size() >= 8) {
toReturn.add(Style.YELLOW + "Your Team: " + Style.PINK + match.getTeam(player).getTeamPlayers().size());
} else {
toReturn.add("");
toReturn.add(Style.YELLOW + "Your Team:");
match.getTeam(player).getTeamPlayers().forEach(teamPlayer -> {
toReturn.add(" " + (teamPlayer.isDisconnected() || !teamPlayer.isAlive() ? Style.STRIKE_THROUGH
: "") + teamPlayer.getName());
});
}
}
} else if (praxiPlayer.isSpectating()) {
final Match match = praxiPlayer.getMatch();
toReturn.add(Style.YELLOW + "Ladder: " + Style.PINK + match.getLadder().getName());
toReturn.add(Style.YELLOW + "Duration: " + Style.PINK + match.getDuration());
toReturn.add(Style.YELLOW + "Players:");
if (match.isSoloMatch()) {
toReturn.add(" " + match.getMatchPlayerA().getName() + Style.GRAY + " (" + match.getMatchPlayerA().getPing() + ")");
toReturn.add(" " + match.getMatchPlayerB().getName() + Style.GRAY + " (" + match.getMatchPlayerB().getPing() + ")");
} else {
toReturn.add(" " + match.getTeamA().getLeader().getName() + "'s Team");
toReturn.add(" " + match.getTeamA().getLeader().getName() + "'s Team");
}
} else if (praxiPlayer.isInEvent()) {
final Event event = praxiPlayer.getEvent();
toReturn.add(Style.YELLOW + "Event: " + Style.PINK + "Sumo");
if (event.isWaiting()) {
toReturn.add(Style.YELLOW + "Players: " + Style.PINK + event.getEventPlayers().size() + "/" + event.getMaxPlayers());
toReturn.add("");
if (event.getCooldown() == null) {
toReturn.add(Style.GRAY + Style.ITALIC + "Waiting for players...");
} else {
toReturn.add(Style.GRAY + Style.ITALIC + "Starting in " +
TimeUtil.millisToSeconds(event.getCooldown().getRemaining()) + "s");
}
} else {
toReturn.add(Style.YELLOW + "Remaining: " + Style.PINK + event.getRemainingPlayers() + "/" + event.getMaxPlayers());
toReturn.add(Style.YELLOW + "Duration: " + Style.PINK + event.getRoundDuration());
toReturn.add(Style.YELLOW + "Players:");
toReturn.add(" " + event.getRoundPlayerA().getName() + Style.GRAY + " (" + event.getRoundPlayerA().getPing() + " ms)");
toReturn.add(" " + event.getRoundPlayerB().getName() + Style.GRAY + " (" + event.getRoundPlayerB().getPing() + " ms)");
}
}
toReturn.add(0, Style.BORDER_LINE_SCOREBOARD);
toReturn.add("");
toReturn.add(Style.PINK + "minexd.com");
toReturn.add(Style.BORDER_LINE_SCOREBOARD);
return toReturn;
}
@Override
public long getInterval() {
return 2L;
}
@Override
public void preLoop() {
}
@Override
public void onScoreboardCreate(Player player, Scoreboard scoreboard) {
}
}

View File

@ -0,0 +1,207 @@
package me.joeleoli.praxi.command;
import java.io.File;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.CommandHelp;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.arena.ArenaType;
import me.joeleoli.praxi.arena.SharedArena;
import me.joeleoli.praxi.arena.StandaloneArena;
import me.joeleoli.praxi.arena.generator.ArenaGenerator;
import me.joeleoli.praxi.arena.generator.Schematic;
import me.joeleoli.praxi.arena.selection.Selection;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class ArenaCommands {
private static final CommandHelp[] HELP = new CommandHelp[]{
new CommandHelp("/arena list", "List all arenas"),
new CommandHelp("/arena create <name> <type>", "Create an arena"),
new CommandHelp("/arena delete <name>", "Delete an arena"),
new CommandHelp("/arena setspawn <1:2> <name>", "Set a spawn point"),
};
@Command(names = { "arena", "arena help" }, permissionNode = "praxi.arena")
public static void help(Player player) {
for (CommandHelp help : HELP) {
player.sendMessage(
Style.YELLOW + help.getSyntax() + Style.GRAY + " - " + Style.PINK + help.getDescription());
}
}
@Command(names = "arena wand", permissionNode = "praxi.arena")
public static void wand(Player player) {
player.getInventory().addItem(Selection.SELECTION_WAND);
player.sendMessage(Style.YELLOW + "You have been given the selection wand.");
}
@Command(names = "arena save", permissionNode = "praxi.arena")
public static void save(CommandSender sender) {
Arena.getArenas().forEach(Arena::save);
sender.sendMessage(Style.GREEN + "Saved all arenas.");
}
@Command(names = "arena list", permissionNode = "praxi.arena")
public static void list(Player player) {
player.sendMessage(Style.GOLD + "Arenas:");
if (Arena.getArenas().isEmpty()) {
player.sendMessage(Style.GRAY + "There are no arenas.");
return;
}
for (Arena arena : Arena.getArenas()) {
if (arena.getType() != ArenaType.DUPLICATE) {
player.sendMessage(Style.GRAY + " - " + (arena.isSetup() ? Style.GREEN : Style.RED) + arena.getName() +
Style.GRAY + " (" + arena.getType().name() + ")");
}
}
}
@Command(names = "arena create", permissionNode = "praxi.arena")
public static void create(Player player, @Parameter(name = "name") String name,
@Parameter(name = "type") ArenaType type) {
Arena arena = Arena.getByName(name);
if (arena != null) {
player.sendMessage(Style.RED + "An arena with that name already exists.");
return;
}
Selection selection = Selection.createOrGetSelection(player);
if (!selection.isFullObject()) {
player.sendMessage(Style.RED + "You must have a full selection to create an arena.");
return;
}
if (type == ArenaType.STANDALONE) {
arena = new StandaloneArena(name, selection.getPoint1(), selection.getPoint2());
} else {
arena = new SharedArena(name, selection.getPoint1(), selection.getPoint2());
}
arena.save();
Arena.getArenas().add(arena);
player.sendMessage(Style.GREEN + "Arena `" + arena.getName() + "` has been created.");
}
@Command(names = "arena delete", permissionNode = "praxi.arena")
public static void delete(Player player, @Parameter(name = "arena") Arena arena) {
arena.delete();
Arena.getArenas().remove(arena);
if (arena instanceof StandaloneArena) {
Arena.getArenas().removeAll(((StandaloneArena) arena).getDuplicates());
}
player.sendMessage(Style.GREEN + "Arena `" + arena.getName() + "` has been deleted.");
}
@Command(names = "arena setspawn", permissionNode = "praxi.arena")
public static void setSpawn(Player player, @Parameter(name = "loc") int loc,
@Parameter(name = "arena") Arena arena) {
if (loc == 1) {
arena.setSpawn1(player.getLocation());
} else if (loc == 2) {
arena.setSpawn2(player.getLocation());
} else {
player.sendMessage(Style.RED + "Choose position `1` or position `2`.");
return;
}
arena.save();
player.sendMessage(Style.GREEN + "You set the spawn position " + loc + (loc == 1 ? "st" : "nd") + " for `" +
arena.getName() + "`.");
}
@Command(names = "arena generate", permissionNode = "praxi.arena.generate", async = true)
public static void generate(Player player) {
File schematicsFolder = new File(Praxi.getInstance().getDataFolder().getPath() + File.separator + "schematics");
if (!schematicsFolder.exists()) {
player.sendMessage(Style.RED + "The schematics folder does not exist.");
return;
}
for (File file : schematicsFolder.listFiles()) {
if (!file.isDirectory()) {
if (file.getName().contains(".schematic")) {
final boolean duplicate = file.getName().endsWith("_duplicate.schematic");
final String name = file.getName()
.replace(".schematic", "")
.replace("_duplicate", "");
final Arena parent = Arena.getByName(name);
if (parent != null) {
if (!(parent instanceof StandaloneArena)) {
continue;
}
}
TaskUtil.run(() -> {
try {
new ArenaGenerator(name, Bukkit.getWorlds().get(0), new Schematic(file),
duplicate ? (parent != null ? ArenaType.DUPLICATE : ArenaType.STANDALONE)
: ArenaType.SHARED
).generate(file, (StandaloneArena) parent);
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
}
player.sendMessage(Style.GREEN + "Generating arenas... See console for details.");
}
@Command(names = "arena tp", permissionNode = "praxi.arena")
public static void teleport(Player player, @Parameter(name = "arena") Arena arena) {
if (arena.getSpawn1() != null) {
player.teleport(arena.getSpawn1());
} else if (arena.getSpawn2() != null) {
player.teleport(arena.getSpawn2());
} else {
player.teleport(arena.getUpperCorner());
}
player.sendMessage(Style.GREEN + "You teleported to " + Style.AQUA + arena.getName() + Style.GREEN + ".");
}
@Command(names = "arena genhelper", permissionNode = "praxi.arena.genhelp")
public static void generatorHelper(Player player) {
final Block origin = player.getLocation().getBlock();
final Block up = origin.getRelative(BlockFace.UP);
origin.setType(Material.SPONGE);
up.setType(Material.SIGN_POST);
if (up.getState() instanceof Sign) {
final Sign sign = (Sign) up.getState();
sign.setLine(0, ((int) player.getLocation().getPitch()) + "");
sign.setLine(1, ((int) player.getLocation().getYaw()) + "");
sign.update();
player.sendMessage(Style.GREEN + "Generator helper placed.");
}
}
}

View File

@ -0,0 +1,158 @@
package me.joeleoli.praxi.command;
import me.joeleoli.nucleus.NucleusAPI;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.duel.DuelProcedure;
import me.joeleoli.praxi.duel.DuelRequest;
import me.joeleoli.praxi.duel.gui.DuelSelectLadderMenu;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.match.impl.SoloMatch;
import me.joeleoli.praxi.player.PracticeSetting;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.praxi.player.RematchData;
import org.bukkit.entity.Player;
public class DuelCommands {
@Command(names = "duel")
public static void duel(Player player, @Parameter(name = "target") Player target) {
if (NucleusAPI.isFrozen(player)) {
player.sendMessage(Style.RED + "You cannot duel while frozen.");
return;
}
if (NucleusAPI.isFrozen(target)) {
player.sendMessage(Style.RED + "You cannot duel a frozen player.");
return;
}
if (player.getUniqueId().equals(target.getUniqueId())) {
player.sendMessage(Style.RED + "You cannot duel yourself.");
return;
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
final PraxiPlayer targetData = PraxiPlayer.getByUuid(target.getUniqueId());
if (praxiPlayer.isBusy()) {
player.sendMessage(Style.RED + "You cannot duel right now.");
return;
}
if (targetData.isBusy()) {
player.sendMessage(NucleusAPI.getColoredName(target) + Style.RED + " is currently busy.");
return;
}
if (!NucleusAPI.<Boolean>getSetting(target, PracticeSetting.RECEIVE_DUEL_REQUESTS)) {
player.sendMessage(Style.RED + "That player is not accepting duel requests at the moment.");
return;
}
if (!praxiPlayer.canSendDuelRequest(player)) {
player.sendMessage(Style.RED + "You have already sent that player a duel request.");
return;
}
DuelProcedure procedure = new DuelProcedure();
procedure.setSender(player);
procedure.setTarget(target);
praxiPlayer.setDuelProcedure(procedure);
new DuelSelectLadderMenu().openMenu(player);
}
@Command(names = "duel accept")
public static void accept(Player player, @Parameter(name = "target") Player target) {
if (NucleusAPI.isFrozen(player)) {
player.sendMessage(Style.RED + "You cannot duel while frozen.");
return;
}
if (NucleusAPI.isFrozen(target)) {
player.sendMessage(Style.RED + "You cannot duel a frozen player.");
return;
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
final PraxiPlayer targetData = PraxiPlayer.getByUuid(target.getUniqueId());
if (!targetData.isPendingDuelRequest(player)) {
player.sendMessage(Style.RED + "You do not have a pending duel request from " + NucleusAPI.getColoredName(target) + Style.RED + ".");
return;
}
if (praxiPlayer.isBusy()) {
player.sendMessage(Style.RED + "You cannot duel right now.");
return;
}
if (targetData.isBusy()) {
player.sendMessage(NucleusAPI.getColoredName(target) + Style.RED + " is currently busy.");
return;
}
final DuelRequest request = targetData.getSentDuelRequests().get(player.getUniqueId());
Arena arena = request.getArena();
if (arena.isActive()) {
arena = Arena.getRandom(request.getLadder());
}
if (arena == null) {
player.sendMessage(Style.RED + "Tried to start a match but there are no available arenas.");
return;
}
arena.setActive(true);
Match match = new SoloMatch(new MatchPlayer(player), new MatchPlayer(target), request.getLadder(), arena, false,
true
);
match.handleStart();
}
@Command(names = "rematch")
public static void rematch(Player player) {
if (NucleusAPI.isFrozen(player)) {
player.sendMessage(Style.RED + "You cannot duel while frozen.");
return;
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getRematchData() == null) {
player.sendMessage(Style.RED + "You do not have anyone to re-match.");
return;
}
praxiPlayer.refreshHotbar();
if (praxiPlayer.getRematchData() == null) {
player.sendMessage(Style.RED + "That player is no longer available.");
return;
}
final RematchData rematchData = praxiPlayer.getRematchData();
if (rematchData.isReceive()) {
rematchData.accept();
} else {
if (rematchData.isSent()) {
player.sendMessage(Style.RED + "You have already sent a rematch request to that player.");
return;
}
rematchData.request();
}
}
}

View File

@ -0,0 +1,127 @@
package me.joeleoli.praxi.command;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.cooldown.Cooldown;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.events.EventState;
import me.joeleoli.praxi.events.impl.SumoEvent;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class EventCommands {
@Command(names = "eventmanager cancel", permissionNode = "praxi.event.admin")
public static void cancel(CommandSender sender) {
if (Praxi.getInstance().getEventManager().getActiveEvent() == null) {
sender.sendMessage(Style.RED + "There is no active event.");
return;
}
Praxi.getInstance().getEventManager().getActiveEvent().end();
}
@Command(names = "eventmanager cooldown", permissionNode = "praxi.event.admin")
public static void cooldown(CommandSender sender) {
if (Praxi.getInstance().getEventManager().getEventCooldown().hasExpired()) {
sender.sendMessage(Style.RED + "There is no event cooldown active.");
return;
}
sender.sendMessage(Style.GREEN + "You reset the event cooldown.");
Praxi.getInstance().getEventManager().setEventCooldown(new Cooldown(0));
}
@Command(names = "eventmanager setspawn pos", permissionNode = "praxi.event.admin")
public static void setSpawnPosition(Player player, @Parameter(name = "pos") int position) {
if (!(position == 1 || position == 2)) {
player.sendMessage(Style.RED + "The position must be 1 or 2.");
} else {
if (position == 1) {
Praxi.getInstance().getEventManager().setSumoSpawn1(player.getLocation());
} else {
Praxi.getInstance().getEventManager().setSumoSpawn2(player.getLocation());
}
Praxi.getInstance().getEventManager().save();
player.sendMessage(Style.GREEN + "Updated event's spawn location " + position + ".");
}
}
@Command(names = "eventmanager setspawn spec", permissionNode = "praxi.event.admin")
public static void setSpawnSpectator(Player player) {
Praxi.getInstance().getEventManager().setSumoSpectator(player.getLocation());
Praxi.getInstance().getEventManager().save();
player.sendMessage(Style.GREEN + "Updated event's spawn spectator location.");
}
@Command(names = { "event host", "host" }, permissionNode = "praxi.event.host")
public static void hostEvent(Player player) {
if (Praxi.getInstance().getEventManager().getActiveEvent() != null) {
player.sendMessage(Style.RED + "There is already an active event.");
return;
}
if (!Praxi.getInstance().getEventManager().getEventCooldown().hasExpired()) {
player.sendMessage(Style.RED + "There is an event cooldown active.");
return;
}
Praxi.getInstance().getEventManager().setActiveEvent(new SumoEvent(player));
for (Player other : Praxi.getInstance().getServer().getOnlinePlayers()) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(other.getUniqueId());
if (praxiPlayer.isInLobby()) {
if (!praxiPlayer.getKitEditor().isActive()) {
praxiPlayer.loadHotbar();
}
}
}
}
@Command(names = { "event join" })
public static void eventJoin(Player player) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
final Event activeEvent = Praxi.getInstance().getEventManager().getActiveEvent();
if (praxiPlayer.isBusy()) {
player.sendMessage(Style.RED + "You cannot join the event right now.");
return;
}
if (activeEvent == null) {
player.sendMessage(Style.RED + "There is no active event.");
return;
}
if (activeEvent.getState() != EventState.WAITING) {
player.sendMessage(Style.RED + "That event is currently on-going and cannot be joined.");
return;
}
Praxi.getInstance().getEventManager().getActiveEvent().handleJoin(player);
}
@Command(names = { "event leave" })
public static void eventLeave(Player player) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
final Event activeEvent = Praxi.getInstance().getEventManager().getActiveEvent();
if (activeEvent == null) {
player.sendMessage(Style.RED + "There is no active event.");
return;
}
if (!praxiPlayer.isInEvent() || !activeEvent.getEventPlayers().containsKey(player.getUniqueId())) {
player.sendMessage(Style.RED + "You are not apart of the active event.");
return;
}
Praxi.getInstance().getEventManager().getActiveEvent().handleLeave(player);
}
}

View File

@ -0,0 +1,109 @@
package me.joeleoli.praxi.command;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.ragespigot.RageSpigot;
import me.joeleoli.ragespigot.knockback.KnockbackProfile;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class LadderCommands {
@Command(names = "ladder enable", permissionNode = "praxi.ladder")
public static void enable(CommandSender sender, @Parameter(name = "ladder") Ladder ladder) {
ladder.setEnabled(true);
sender.sendMessage(Style.GREEN + "You enabled the " + ladder.getDisplayName() + Style.GREEN + " ladder.");
}
@Command(names = "ladder disable", permissionNode = "praxi.ladder")
public static void disable(CommandSender sender, @Parameter(name = "ladder") Ladder ladder) {
ladder.setEnabled(false);
sender.sendMessage(Style.GREEN + "You disabled the " + ladder.getDisplayName() + Style.GREEN + " ladder.");
}
@Command(names = "ladder sethitdelay", permissionNode = "praxi.ladder")
public static void setHitDelay(CommandSender sender, @Parameter(name = "ladder") Ladder ladder,
@Parameter(name = "hitdelay") int hitDelay) {
if (hitDelay < 0 || hitDelay > 20) {
sender.sendMessage(Style.RED + "The hit delay must be in the range of 0-20.");
return;
}
ladder.setHitDelay(hitDelay);
sender.sendMessage(Style.GREEN + "You set the hit delay of " + ladder.getDisplayName() + Style.GREEN + " to: " +
Style.RESET + ladder.getHitDelay());
}
@Command(names = "ladder list", permissionNode = "praxi.ladder")
public static void list(CommandSender sender) {
sender.sendMessage(Style.GOLD + Style.BOLD + "Ladders:");
Ladder.getLadders().forEach(ladder -> {
sender.sendMessage(Style.GRAY + " - " + ladder.getDisplayName());
});
}
@Command(names = "ladder create", permissionNode = "praxi.ladder")
public static void create(Player player, @Parameter(name = "name") String name) {
Ladder ladder = Ladder.getByName(name);
if (ladder != null) {
player.sendMessage(Style.RED + "A ladder with that name already exists.");
return;
}
ladder = new Ladder(name);
ladder.save();
player.sendMessage(
Style.GREEN + "Created a new ladder named " + Style.AQUA + ladder.getName() + Style.GREEN + ".");
}
@Command(names = "ladder setkit", permissionNode = "praxi.ladder")
public static void setKit(Player player, @Parameter(name = "ladder") Ladder ladder) {
ladder.getDefaultKit().setArmor(player.getInventory().getArmorContents());
ladder.getDefaultKit().setContents(player.getInventory().getContents());
ladder.save();
player.sendMessage(Style.GREEN + "Updated " + Style.AQUA + ladder.getName() + Style.GREEN + "'s default kit.");
}
@Command(names = "ladder loadkit", permissionNode = "praxi.ladder")
public static void loadKit(Player player, @Parameter(name = "ladder") Ladder ladder) {
player.getInventory().setArmorContents(ladder.getDefaultKit().getArmor());
player.getInventory().setContents(ladder.getDefaultKit().getContents());
player.updateInventory();
player.sendMessage(Style.GREEN + "Loaded " + Style.AQUA + ladder.getName() + Style.GREEN + "'s default kit.");
}
@Command(names = "ladder setdisplayname", permissionNode = "praxi.ladder")
public static void setDisplayName(CommandSender sender, @Parameter(name = "ladder") Ladder ladder,
@Parameter(name = "displayName") String displayName) {
ladder.setDisplayName(Style.translate(displayName));
ladder.save();
sender.sendMessage(
Style.GREEN + "You set " + Style.AQUA + ladder.getName() + "'s display name " + Style.GREEN + "to: " +
Style.AQUA + Style.translate(displayName));
}
@Command(names = "ladder setkbprofile", permissionNode = "praxi.ladder")
public static void setKnockbackProfile(CommandSender sender, @Parameter(name = "ladder") Ladder ladder,
@Parameter(name = "profile") String profileName) {
final KnockbackProfile profile = RageSpigot.INSTANCE.getConfig().getKbProfileByName(profileName);
if (profile == null) {
sender.sendMessage(Style.RED + "A knockback profile with that name could not be found.");
return;
}
ladder.setKbProfile(profileName);
ladder.save();
sender.sendMessage(
Style.GREEN + "You set the kb-profile for " + ladder.getDisplayName() + Style.GREEN + " ladder.");
}
}

View File

@ -0,0 +1,68 @@
package me.joeleoli.praxi.command;
import java.util.UUID;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.CommandHelp;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.nucleus.uuid.UUIDCache;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class ManagementCommands {
private static final CommandHelp[] HELP = new CommandHelp[]{
new CommandHelp("/praxi reload", "Reload the config"),
};
@Command(names = { "praxi", "praxi help" }, permissionNode = "praxi.admin")
public static void help(Player player) {
for (CommandHelp help : HELP) {
player.sendMessage(
Style.YELLOW + help.getSyntax() + Style.GRAY + " - " + Style.PINK + help.getDescription());
}
}
@Command(names = "resetelo", permissionNode = "prax.admin.resetelo")
public static void resetElo(CommandSender sender, @Parameter(name = "target") String targetName) {
UUID uuid;
try {
uuid = UUID.fromString(targetName);
} catch (Exception e) {
uuid = UUIDCache.getUuid(targetName);
}
if (uuid == null) {
sender.sendMessage(
Style.RED + "Couldn't find a player with the name " + Style.RESET + targetName + Style.RED +
". Have they joined the network?");
return;
}
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(uuid);
if (praxiPlayer.isLoaded()) {
praxiPlayer.getStatistics().getLadders().values().forEach(stats -> {
stats.setElo(1000);
});
praxiPlayer.save();
} else {
TaskUtil.runAsync(() -> {
praxiPlayer.load();
praxiPlayer.getStatistics().getLadders().values().forEach(stats -> {
stats.setElo(1000);
});
praxiPlayer.save();
});
}
sender.sendMessage(Style.GREEN + "You reset " + targetName + "'s elo.");
}
}

View File

@ -0,0 +1,31 @@
package me.joeleoli.praxi.command;
import java.util.UUID;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.match.MatchSnapshot;
import me.joeleoli.praxi.match.gui.MatchDetailsMenu;
import org.bukkit.entity.Player;
public class MatchCommands {
@Command(names = { "viewinventory", "viewinv" })
public static void viewInventory(Player player, @Parameter(name = "id") String id) {
MatchSnapshot cachedInventory;
try {
cachedInventory = MatchSnapshot.getByUuid(UUID.fromString(id));
} catch (Exception e) {
cachedInventory = MatchSnapshot.getByName(id);
}
if (cachedInventory == null) {
player.sendMessage(Style.RED + "Couldn't find an inventory for that ID.");
return;
}
new MatchDetailsMenu(cachedInventory).openMenu(player);
}
}

View File

@ -0,0 +1,254 @@
package me.joeleoli.praxi.command;
import java.util.UUID;
import me.joeleoli.nucleus.NucleusAPI;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.CommandHelp;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.party.Party;
import me.joeleoli.praxi.party.PartyState;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class PartyCommands {
private static final CommandHelp[] HELP = new CommandHelp[]{
new CommandHelp("/party create", "Create a party"),
new CommandHelp("/party disband", "Disband your party"),
new CommandHelp("/party leave", "Leave your party"),
new CommandHelp("/party join <name>", "Join a party"),
new CommandHelp("/party kick <player>", "Kick a player from your party"),
new CommandHelp("/party open", "Make your party open"),
new CommandHelp("/party close", "Make your party closed"),
};
@Command(names = { "party", "party help" })
public static void help(Player player) {
for (CommandHelp help : HELP) {
player.sendMessage(
Style.YELLOW + help.getSyntax() + Style.GRAY + " - " + Style.PINK + help.getDescription());
}
}
@Command(names = { "p create", "party create" })
public static void create(Player player) {
if (NucleusAPI.isFrozen(player)) {
player.sendMessage(Style.RED + "You cannot create a party while frozen.");
return;
}
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() != null) {
player.sendMessage(Style.RED + "You already have a party.");
return;
}
if (!praxiPlayer.isInLobby()) {
player.sendMessage(Style.RED + "You must be in the lobby to create a party.");
return;
}
praxiPlayer.setParty(new Party(player));
praxiPlayer.loadHotbar();
player.sendMessage(Style.YELLOW + "You created a new party.");
}
@Command(names = { "p disband", "party disband" })
public static void disband(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You do not have a party.");
return;
}
if (!praxiPlayer.getParty().isLeader(player.getUniqueId())) {
player.sendMessage(Style.RED + "You are not the leader of your party.");
return;
}
praxiPlayer.getParty().disband();
}
@Command(names = { "p invite", "party invite" })
public static void invite(Player player, @Parameter(name = "target") Player target) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You do not have a party.");
return;
}
if (!praxiPlayer.getParty().canInvite(target)) {
player.sendMessage(Style.RED + "That player has already been invited to your party.");
return;
}
if (praxiPlayer.getParty().containsPlayer(target)) {
player.sendMessage(Style.RED + "That player is already in your party.");
return;
}
if (praxiPlayer.getParty().getState() == PartyState.OPEN) {
player.sendMessage(Style.RED + "The party state is Open. You do not need to invite players.");
return;
}
final PraxiPlayer targetData = PraxiPlayer.getByUuid(target.getUniqueId());
if (targetData.isBusy()) {
player.sendMessage(NucleusAPI.getColoredName(target) + Style.RED + " is currently busy.");
return;
}
praxiPlayer.getParty().invite(target);
}
@Command(names = { "p join", "party join" })
public static void join(Player player, @Parameter(name = "target") String targetId) {
if (NucleusAPI.isFrozen(player)) {
player.sendMessage(Style.RED + "You cannot join a party while frozen.");
return;
}
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() != null) {
player.sendMessage(Style.RED + "You already have a party.");
return;
}
Player target;
try {
target = Bukkit.getPlayer(UUID.fromString(targetId));
} catch (Exception e) {
target = Bukkit.getPlayer(targetId);
}
if (target == null) {
player.sendMessage(Style.RED + "A player with that name could not be found.");
return;
}
PraxiPlayer targetData = PraxiPlayer.getByUuid(target.getUniqueId());
Party party = targetData.getParty();
if (party == null) {
player.sendMessage(Style.RED + "A party with that name could not be found.");
return;
}
if (party.getState() == PartyState.CLOSED) {
if (!party.isInvited(player)) {
player.sendMessage(Style.RED + "You have not been invited to that party.");
return;
}
}
if (party.getPlayers().size() >= 32) {
player.sendMessage(Style.RED + "That party is full and cannot hold anymore players.");
return;
}
party.join(player);
}
@Command(names = { "p leave", "party leave" })
public static void leave(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You do not have a party.");
return;
}
if (praxiPlayer.getParty().getLeader().getUuid().equals(player.getUniqueId())) {
praxiPlayer.getParty().disband();
} else {
praxiPlayer.getParty().leave(player, false);
}
}
@Command(names = { "p kick", "party kick" })
public static void kick(Player player, @Parameter(name = "target") Player target) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You do not have a party.");
return;
}
if (!praxiPlayer.getParty().isLeader(player.getUniqueId())) {
player.sendMessage(Style.RED + "You are not the leader of your party.");
return;
}
if (!praxiPlayer.getParty().containsPlayer(target)) {
player.sendMessage(Style.RED + "That player is not a member of your party.");
return;
}
if (player.equals(target)) {
player.sendMessage(Style.RED + "You cannot kick yourself from your party.");
return;
}
praxiPlayer.getParty().leave(target, true);
}
@Command(names = { "p close", "party close" })
public static void open(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You do not have a party.");
return;
}
if (!praxiPlayer.getParty().isLeader(player.getUniqueId())) {
player.sendMessage(Style.RED + "You are not the leader of your party.");
return;
}
praxiPlayer.getParty().setState(PartyState.CLOSED);
}
@Command(names = { "p open", "party open" })
public static void close(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You do not have a party.");
return;
}
if (!praxiPlayer.getParty().isLeader(player.getUniqueId())) {
player.sendMessage(Style.RED + "You are not the leader of your party.");
return;
}
praxiPlayer.getParty().setState(PartyState.OPEN);
}
@Command(names = { "p info", "party info", "party information" })
public static void information(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (!praxiPlayer.isLoaded()) {
return;
}
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You do not have a party.");
return;
}
praxiPlayer.getParty().sendInformation(player);
}
}

View File

@ -0,0 +1,73 @@
package me.joeleoli.praxi.command;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.uuid.UUIDCache;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.praxi.player.gui.PlayerSettingsMenu;
import org.bukkit.entity.Player;
public class PlayerCommands {
@Command(names = "fly", permissionNode = "praxi.donor.fly")
public static void fly(Player player) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInLobby() || praxiPlayer.isInQueue()) {
player.setAllowFlight(true);
player.setFlying(true);
player.updateInventory();
player.sendMessage(Style.YELLOW + "You are now flying.");
} else {
player.sendMessage(Style.RED + "You cannot fly right now.");
}
}
@Command(names = { "settings", "options" })
public static void settings(Player player) {
new PlayerSettingsMenu().openMenu(player);
}
@Command(names = { "statistics", "stats" }, async = true)
public static void statistics(Player player, @Parameter(name = "target", defaultValue = "self") String name) {
if (name.equalsIgnoreCase("self")) {
name = player.getName();
}
final UUID uuid = UUIDCache.getUuid(name);
if (uuid == null) {
player.sendMessage(
Style.RED + "Couldn't find a player with the name " + Style.RESET + name + Style.RED + ".");
return;
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(uuid);
if (!praxiPlayer.isLoaded()) {
praxiPlayer.load();
}
if (praxiPlayer.getName() != null) {
if (praxiPlayer.getName().equalsIgnoreCase(name)) {
name = praxiPlayer.getName();
}
}
final List<String> messages = new ArrayList<>();
praxiPlayer.getStatistics().getLadders().forEach((key, value) -> {
messages.add(Style.YELLOW + key + Style.GRAY + ": " + Style.PINK + value.getElo() + " ELO");
});
messages.add(0, Style.GOLD + Style.BOLD + name + "'s Statistics");
messages.add(0, Style.getBorderLine());
messages.add(Style.getBorderLine());
messages.forEach(player::sendMessage);
}
}

View File

@ -0,0 +1,58 @@
package me.joeleoli.praxi.command;
import me.joeleoli.nucleus.NucleusAPI;
import me.joeleoli.nucleus.command.Command;
import me.joeleoli.nucleus.command.param.Parameter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.player.PracticeSetting;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Player;
public class SpectateCommands {
@Command(names = { "spectate", "spec" })
public static void spectate(Player player, @Parameter(name = "target") Player target) {
if (NucleusAPI.isFrozen(player)) {
player.sendMessage(Style.RED + "You cannot spectate while frozen.");
return;
}
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
PraxiPlayer targetData = PraxiPlayer.getByUuid(target.getUniqueId());
if (praxiPlayer.isBusy()) {
player.sendMessage(Style.RED + "You cannot spectate right now.");
return;
}
if (praxiPlayer.getParty() != null) {
player.sendMessage(Style.RED + "You must leave your party to spectate a match.");
return;
}
if (targetData == null || !targetData.isInMatch()) {
player.sendMessage(Style.RED + "That player is not in a match.");
return;
}
if (!NucleusAPI.<Boolean>getSetting(target, PracticeSetting.RECEIVE_DUEL_REQUESTS)) {
player.sendMessage(Style.RED + "That player is not allowing spectators.");
return;
}
targetData.getMatch().addSpectator(player, target);
}
@Command(names = "stopspectate")
public static void stopSpectate(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer == null || !praxiPlayer.isSpectating()) {
player.sendMessage(Style.RED + "You are not spectating a match.");
return;
}
praxiPlayer.getMatch().removeSpectator(player);
}
}

View File

@ -0,0 +1,38 @@
package me.joeleoli.praxi.command.param;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import me.joeleoli.nucleus.command.param.ParameterType;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import org.apache.commons.lang.StringUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class ArenaParameterType implements ParameterType<Arena> {
public Arena transform(CommandSender sender, String source) {
Arena arena = Arena.getByName(source);
if (arena == null) {
sender.sendMessage(Style.RED + "An arena with that name does not exist.");
return null;
}
return arena;
}
public List<String> tabComplete(Player sender, Set<String> flags, String source) {
List<String> completions = new ArrayList<>();
for (Arena arena : Arena.getArenas()) {
if (arena.getName() != null && StringUtils.startsWithIgnoreCase(arena.getName(), source)) {
completions.add(arena.getName());
}
}
return completions;
}
}

View File

@ -0,0 +1,37 @@
package me.joeleoli.praxi.command.param;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import me.joeleoli.nucleus.command.param.ParameterType;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.ArenaType;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class ArenaTypeParameterType implements ParameterType<ArenaType> {
public ArenaType transform(CommandSender sender, String source) {
ArenaType type;
try {
type = ArenaType.valueOf(source);
} catch (Exception e) {
sender.sendMessage(Style.RED + "That is not a valid arena type.");
return null;
}
return type;
}
public List<String> tabComplete(Player sender, Set<String> flags, String source) {
List<String> completions = new ArrayList<>();
for (ArenaType type : ArenaType.values()) {
completions.add(type.name());
}
return completions;
}
}

View File

@ -0,0 +1,35 @@
package me.joeleoli.praxi.command.param;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import me.joeleoli.nucleus.command.param.ParameterType;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.ladder.Ladder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class LadderParameterType implements ParameterType<Ladder> {
public Ladder transform(CommandSender sender, String source) {
Ladder ladder = Ladder.getByName(source);
if (ladder == null) {
sender.sendMessage(Style.RED + "That is not a valid ladder type.");
return null;
}
return ladder;
}
public List<String> tabComplete(Player sender, Set<String> flags, String source) {
List<String> completions = new ArrayList<>();
for (Ladder ladder : Ladder.getLadders()) {
completions.add(ladder.getName());
}
return completions;
}
}

View File

@ -0,0 +1,35 @@
package me.joeleoli.praxi.command.param;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import me.joeleoli.nucleus.command.param.ParameterType;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.queue.Queue;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class QueueParameterType implements ParameterType<Queue> {
public Queue transform(CommandSender sender, String source) {
try {
Queue queue = Queue.getByUuid(UUID.fromString(source));
if (queue == null) {
sender.sendMessage(Style.RED + "A queue with that ID does not exist.");
return null;
}
return queue;
} catch (Exception e) {
sender.sendMessage(Style.RED + "A queue with that ID does not exist.");
return null;
}
}
public List<String> tabComplete(Player sender, Set<String> flags, String source) {
return Collections.emptyList();
}
}

View File

@ -0,0 +1,62 @@
package me.joeleoli.praxi.config;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import me.joeleoli.nucleus.config.ConfigCursor;
import me.joeleoli.nucleus.util.Style;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@Getter
public class ConfigItem {
private Material material = Material.AIR;
private short durability = 0;
private String name;
private List<String> lore = new ArrayList<>();
private int amount = 1;
public ConfigItem(ConfigCursor cursor, String path) {
if (cursor.exists(path + ".material")) {
this.material = Material.valueOf(cursor.getString(path + ".material"));
}
if (cursor.exists(path + ".durability")) {
this.durability = (short) cursor.getInt(path + ".durability");
}
if (cursor.exists(path + ".name")) {
this.name = Style.translate(cursor.getString(path + ".name"));
}
if (cursor.exists(path + ".lore")) {
this.lore = Style.translateLines(cursor.getStringList(path + ".lore"));
}
if (cursor.exists(path + ".amount")) {
this.amount = cursor.getInt(path + ".amount");
}
}
public ItemStack toItemStack() {
ItemStack itemStack = new ItemStack(this.material);
ItemMeta itemMeta = itemStack.getItemMeta();
if (this.name != null) {
itemMeta.setDisplayName(Style.translate(this.name));
}
if (this.lore != null && !this.lore.isEmpty()) {
itemMeta.setLore(Style.translateLines(this.lore));
}
itemStack.setAmount(this.amount);
itemStack.setDurability(this.durability);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
}

View File

@ -0,0 +1,519 @@
package me.joeleoli.praxi.cuboid;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
@Data
public class Cuboid implements Iterable<Location> {
private String worldName;
private int x1, y1, z1;
private int x2, y2, z2;
/**
* Construct a Cuboid given two Location objects which represent any two corners of the Cuboid.
*
* @param l1 one of the corners
* @param l2 the other corner
*/
public Cuboid(Location l1, Location l2) {
this(l1.getWorld().getName(),
l1.getBlockX(), l1.getBlockY(), l1.getBlockZ(),
l2.getBlockX(), l2.getBlockY(), l2.getBlockZ()
);
}
/**
* Construct a Cuboid in the given World and xyz coords
*
* @param world the Cuboid's world
* @param x1 X coord of corner 1
* @param y1 Y coord of corner 1
* @param z1 Z coord of corner 1
* @param x2 X coord of corner 2
* @param y2 Y coord of corner 2
* @param z2 Z coord of corner 2
*/
public Cuboid(World world, int x1, int y1, int z1, int x2, int y2, int z2) {
this(world.getName(), x1, y1, z1, x2, y2, z2);
}
/**
* Construct a Cuboid in the given world name and xyz coords.
*
* @param worldName the Cuboid's world name
* @param x1 X coord of corner 1
* @param y1 Y coord of corner 1
* @param z1 Z coord of corner 1
* @param x2 X coord of corner 2
* @param y2 Y coord of corner 2
* @param z2 Z coord of corner 2
*/
public Cuboid(String worldName, int x1, int y1, int z1, int x2, int y2, int z2) {
this.worldName = worldName;
this.x1 = Math.min(x1, x2);
this.x2 = Math.max(x1, x2);
this.y1 = Math.min(y1, y2);
this.y2 = Math.max(y1, y2);
this.z1 = Math.min(z1, z2);
this.z2 = Math.max(z1, z2);
}
/**
* Get the Location of the lower northeast corner of the Cuboid (minimum XYZ coords).
*
* @return Location of the lower northeast corner
*/
public Location getLowerCorner() {
return new Location(getWorld(), x1, y1, z1);
}
/**
* Get the Location of the upper southwest corner of the Cuboid (maximum XYZ coords).
*
* @return Location of the upper southwest corner
*/
public Location getUpperCorner() {
return new Location(getWorld(), x2, y2, z2);
}
/**
* Get the the center of the Cuboid
*
* @return Location at the centre of the Cuboid
*/
public Location getCenter() {
return new Location(
getWorld(), getLowerX() + (getUpperX() - getLowerX()) / 2,
getLowerY() + (getUpperY() - getLowerY()) / 2, getLowerZ() + (getUpperZ() - getLowerZ()) / 2
);
}
/**
* Get the Cuboid's world.
*
* @return the World object representing this Cuboid's world
*
* @throws IllegalStateException if the world is not loaded
*/
public World getWorld() {
World world = Bukkit.getWorld(worldName);
if (world == null) {
throw new IllegalStateException("world '" + worldName + "' is not loaded");
}
return world;
}
/**
* Get the size of this Cuboid along the X axis
*
* @return Size of Cuboid along the X axis
*/
public int getSizeX() {
return (x2 - x1) + 1;
}
/**
* Get the size of this Cuboid along the Y axis
*
* @return Size of Cuboid along the Y axis
*/
public int getSizeY() {
return (y2 - y1) + 1;
}
/**
* Get the size of this Cuboid along the Z axis
*
* @return Size of Cuboid along the Z axis
*/
public int getSizeZ() {
return (z2 - z1) + 1;
}
/**
* Get the minimum X coord of this Cuboid
*
* @return the minimum X coord
*/
public int getLowerX() {
return x1;
}
/**
* Get the minimum Y coord of this Cuboid
*
* @return the minimum Y coord
*/
public int getLowerY() {
return y1;
}
/**
* Get the minimum Z coord of this Cuboid
*
* @return the minimum Z coord
*/
public int getLowerZ() {
return z1;
}
/**
* Get the maximum X coord of this Cuboid
*
* @return the maximum X coord
*/
public int getUpperX() {
return x2;
}
/**
* Get the maximum Y coord of this Cuboid
*
* @return the maximum Y coord
*/
public int getUpperY() {
return y2;
}
/**
* Get the maximum Z coord of this Cuboid
*
* @return the maximum Z coord
*/
public int getUpperZ() {
return z2;
}
/**
* Get the Blocks at the four corners of the Cuboid, without respect to y-value
*
* @return array of Block objects representing the Cuboid corners
*/
public Location[] getCorners() {
Location[] res = new Location[4];
World w = getWorld();
res[0] = new Location(w, x1, 0, z1); // ++x
res[1] = new Location(w, x2, 0, z1); // ++z
res[2] = new Location(w, x2, 0, z2); // --x
res[3] = new Location(w, x1, 0, z2); // --z
return res;
}
/**
* Expand the Cuboid in the given direction by the given amount. Negative amounts will shrink the Cuboid in the
* given direction. Shrinking a cuboid's face past the opposite face is not an error and will return a valid
* Cuboid.
*
* @param dir the direction in which to expand
* @param amount the number of blocks by which to expand
*
* @return a new Cuboid expanded by the given direction and amount
*/
public Cuboid expand(CuboidDirection dir, int amount) {
switch (dir) {
case NORTH:
return new Cuboid(worldName, x1 - amount, y1, z1, x2, y2, z2);
case SOUTH:
return new Cuboid(worldName, x1, y1, z1, x2 + amount, y2, z2);
case EASY:
return new Cuboid(worldName, x1, y1, z1 - amount, x2, y2, z2);
case WEST:
return new Cuboid(worldName, x1, y1, z1, x2, y2, z2 + amount);
case DOWN:
return new Cuboid(worldName, x1, y1 - amount, z1, x2, y2, z2);
case UP:
return new Cuboid(worldName, x1, y1, z1, x2, y2 + amount, z2);
default:
throw new IllegalArgumentException("invalid direction " + dir);
}
}
/**
* Shift the Cuboid in the given direction by the given amount.
*
* @param dir the direction in which to shift
* @param amount the number of blocks by which to shift
*
* @return a new Cuboid shifted by the given direction and amount
*/
public Cuboid shift(CuboidDirection dir, int amount) {
return expand(dir, amount).expand(dir.opposite(), -amount);
}
/**
* Outset (grow) the Cuboid in the given direction by the given amount.
*
* @param dir the direction in which to outset (must be HORIZONTAL, VERTICAL, or BOTH)
* @param amount the number of blocks by which to outset
*
* @return a new Cuboid outset by the given direction and amount
*/
public Cuboid outset(CuboidDirection dir, int amount) {
Cuboid c;
switch (dir) {
case HORIZONTAL:
c = expand(CuboidDirection.NORTH, amount).expand(CuboidDirection.SOUTH, amount)
.expand(CuboidDirection.EASY, amount)
.expand(CuboidDirection.WEST, amount);
break;
case VERTICAL:
c = expand(CuboidDirection.DOWN, amount).expand(CuboidDirection.UP, amount);
break;
case BOTH:
c = outset(CuboidDirection.HORIZONTAL, amount).outset(CuboidDirection.VERTICAL, amount);
break;
default:
throw new IllegalArgumentException("invalid direction " + dir);
}
return c;
}
/**
* Inset (shrink) the Cuboid in the given direction by the given amount. Equivalent to calling outset() with a
* negative amount.
*
* @param dir the direction in which to inset (must be HORIZONTAL, VERTICAL, or BOTH)
* @param amount the number of blocks by which to inset
*
* @return a new Cuboid inset by the given direction and amount
*/
public Cuboid inset(CuboidDirection dir, int amount) {
return outset(dir, -amount);
}
/**
* Return true if the point at (x,y,z) is contained within this Cuboid.
*
* @param x the X coord
* @param y the Y coord
* @param z the Z coord
*
* @return true if the given point is within this Cuboid, false otherwise
*/
public boolean contains(int x, int y, int z) {
return x >= x1 && x <= x2 && y >= y1 && y <= y2 && z >= z1 && z <= z2;
}
/**
* Return true if the point at (x,z) is contained within this Cuboid.
*
* @param x the X coord
* @param z the Z coord
*
* @return true if the given point is within this Cuboid, false otherwise
*/
public boolean contains(int x, int z) {
return x >= x1 && x <= x2 && z >= z1 && z <= z2;
}
/**
* Check if the given Location is contained within this Cuboid.
*
* @param l the Location to check for
*
* @return true if the Location is within this Cuboid, false otherwise
*/
public boolean contains(Location l) {
if (!worldName.equals(l.getWorld().getName())) {
return false;
}
return contains(l.getBlockX(), l.getBlockY(), l.getBlockZ());
}
/**
* Check if the given Block is contained within this Cuboid.
*
* @param b the Block to check for
*
* @return true if the Block is within this Cuboid, false otherwise
*/
public boolean contains(Block b) {
return contains(b.getLocation());
}
/**
* Get the volume of this Cuboid.
*
* @return the Cuboid volume, in blocks
*/
public int volume() {
return getSizeX() * getSizeY() * getSizeZ();
}
/**
* Get the Cuboid representing the face of this Cuboid. The resulting Cuboid will be one block thick in the axis
* perpendicular to the requested face.
*
* @param dir which face of the Cuboid to get
*
* @return the Cuboid representing this Cuboid's requested face
*/
public Cuboid getFace(CuboidDirection dir) {
switch (dir) {
case DOWN:
return new Cuboid(worldName, x1, y1, z1, x2, y1, z2);
case UP:
return new Cuboid(worldName, x1, y2, z1, x2, y2, z2);
case NORTH:
return new Cuboid(worldName, x1, y1, z1, x1, y2, z2);
case SOUTH:
return new Cuboid(worldName, x2, y1, z1, x2, y2, z2);
case EASY:
return new Cuboid(worldName, x1, y1, z1, x2, y2, z1);
case WEST:
return new Cuboid(worldName, x1, y1, z2, x2, y2, z2);
default:
throw new IllegalArgumentException("Invalid direction " + dir);
}
}
/**
* Get the Cuboid big enough to hold both this Cuboid and the given one.
*
* @return a new Cuboid large enough to hold this Cuboid and the given Cuboid
*/
public Cuboid getBoundingCuboid(Cuboid other) {
if (other == null) {
return this;
}
int xMin = Math.min(getLowerX(), other.getLowerX());
int yMin = Math.min(getLowerY(), other.getLowerY());
int zMin = Math.min(getLowerZ(), other.getLowerZ());
int xMax = Math.max(getUpperX(), other.getUpperX());
int yMax = Math.max(getUpperY(), other.getUpperY());
int zMax = Math.max(getUpperZ(), other.getUpperZ());
return new Cuboid(worldName, xMin, yMin, zMin, xMax, yMax, zMax);
}
/**
* Get a block relative to the lower NE point of the Cuboid.
*
* @param x the X coord
* @param y the Y coord
* @param z the Z coord
*
* @return the block at the given position
*/
public Block getRelativeBlock(int x, int y, int z) {
return getWorld().getBlockAt(x1 + x, y1 + y, z1 + z);
}
/**
* Get a block relative to the lower NE point of the Cuboid in the given World. This version of getRelativeBlock()
* should be used if being called many times, to avoid excessive calls to getWorld().
*
* @param w the World
* @param x the X coord
* @param y the Y coord
* @param z the Z coord
*
* @return the block at the given position
*/
public Block getRelativeBlock(World w, int x, int y, int z) {
return w.getBlockAt(x1 + x, y1 + y, z1 + z);
}
/**
* Get a list of the chunks which are fully or partially contained in this cuboid.
*
* @return a list of Chunk objects
*/
public List<Chunk> getChunks() {
List<Chunk> chunks = new ArrayList<Chunk>();
World w = getWorld();
// These operators get the lower bound of the chunk, by complementing 0xf (15) into 16
// and using an OR gate on the integer coordinate
int x1 = getLowerX() & ~0xf;
int x2 = getUpperX() & ~0xf;
int z1 = getLowerZ() & ~0xf;
int z2 = getUpperZ() & ~0xf;
for (int x = x1; x <= x2; x += 16) {
for (int z = z1; z <= z2; z += 16) {
chunks.add(w.getChunkAt(x >> 4, z >> 4));
}
}
return chunks;
}
/**
* @return horizontal walls of the cuboid
*/
public Cuboid[] getWalls() {
return new Cuboid[]{
getFace(CuboidDirection.NORTH),
getFace(CuboidDirection.SOUTH),
getFace(CuboidDirection.WEST),
getFace(CuboidDirection.EASY)
};
}
/**
* @return read-only location iterator
*/
public Iterator<Location> iterator() {
return new LocationCuboidIterator(getWorld(), x1, y1, z1, x2, y2, z2);
}
@Override
public String toString() {
return "Cuboid: " + worldName + "," + x1 + "," + y1 + "," + z1 + "=>" + x2 + "," + y2 + "," + z2;
}
public class LocationCuboidIterator implements Iterator<Location> {
private World w;
private int baseX, baseY, baseZ;
private int x, y, z;
private int sizeX, sizeY, sizeZ;
public LocationCuboidIterator(World w, int x1, int y1, int z1, int x2, int y2, int z2) {
this.w = w;
baseX = x1;
baseY = y1;
baseZ = z1;
sizeX = Math.abs(x2 - x1) + 1;
sizeY = Math.abs(y2 - y1) + 1;
sizeZ = Math.abs(z2 - z1) + 1;
x = y = z = 0;
}
public boolean hasNext() {
return x < sizeX && y < sizeY && z < sizeZ;
}
public Location next() {
Location b = new Location(w, baseX + x, baseY + y, baseZ + z);
if (++x >= sizeX) {
x = 0;
if (++y >= sizeY) {
y = 0;
++z;
}
}
return b;
}
public void remove() {
}
}
}

View File

@ -0,0 +1,43 @@
package me.joeleoli.praxi.cuboid;
/**
* Represents directions that can be applied to certain faces and actions of a Cuboid
*/
public enum CuboidDirection {
NORTH,
EASY,
SOUTH,
WEST,
UP,
DOWN,
HORIZONTAL,
VERTICAL,
BOTH,
UNKNOWN;
public CuboidDirection opposite() {
switch (this) {
case NORTH:
return SOUTH;
case EASY:
return WEST;
case SOUTH:
return NORTH;
case WEST:
return EASY;
case HORIZONTAL:
return VERTICAL;
case VERTICAL:
return HORIZONTAL;
case UP:
return DOWN;
case DOWN:
return UP;
case BOTH:
return BOTH;
default:
return UNKNOWN;
}
}
}

View File

@ -0,0 +1,57 @@
package me.joeleoli.praxi.duel;
import java.text.MessageFormat;
import lombok.Data;
import me.joeleoli.nucleus.chat.ChatComponentBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.player.PraxiPlayer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.entity.Player;
@Data
public class DuelProcedure {
private static final HoverEvent ACCEPT_HOVER = new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new ChatComponentBuilder(Style.YELLOW + "Click to accept this duel invite.").create()
);
private Player sender;
private Player target;
private Ladder ladder;
private Arena arena;
public void send() {
if (!this.sender.isOnline() || !this.target.isOnline()) {
return;
}
final DuelRequest request = new DuelRequest(this.sender.getUniqueId());
request.setLadder(this.ladder);
request.setArena(this.arena);
final PraxiPlayer senderData = PraxiPlayer.getByUuid(this.sender.getUniqueId());
senderData.setDuelProcedure(null);
senderData.getSentDuelRequests().put(this.target.getUniqueId(), request);
final ClickEvent click = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/duel accept " + this.sender.getName());
final String ladderContext = StringUtils.startsWithIgnoreCase(this.ladder.getName(), "u") ? "an " : "a ";
this.sender.sendMessage(Style.translate(new MessageFormat("&eYou sent a duel request to &d{0} &eon arena &d{1}&e.")
.format(new Object[]{ this.target.getName(), this.arena.getName() })));
this.target.sendMessage(Style.translate(
new MessageFormat("&d{0} &esent you {1} &d{2} &eduel request on arena &d{3}&e.").format(new Object[]{
this.sender.getName(), ladderContext, this.ladder.getName(), this.arena.getName()
})));
this.target.sendMessage(new ChatComponentBuilder("")
.parse("&6Click here or type &b/duel accept " + this.sender.getName() + " &6to accept the invite.")
.attachToEachPart(click).attachToEachPart(ACCEPT_HOVER).create());
}
}

View File

@ -0,0 +1,24 @@
package me.joeleoli.praxi.duel;
import java.util.UUID;
import lombok.Data;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.ladder.Ladder;
@Data
public class DuelRequest {
private UUID sender;
private Ladder ladder;
private Arena arena;
private long timestamp = System.currentTimeMillis();
public DuelRequest(UUID uuid) {
this.sender = uuid;
}
public boolean isExpired() {
return System.currentTimeMillis() - this.timestamp >= 30_000;
}
}

View File

@ -0,0 +1,94 @@
package me.joeleoli.praxi.duel.gui;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.arena.ArenaType;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class DuelSelectArenaMenu extends Menu {
@Override
public String getTitle(Player player) {
return Style.BLUE + Style.BOLD + "Select an arena";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
Map<Integer, Button> buttons = new HashMap<>();
for (Arena arena : Arena.getArenas()) {
if (!arena.isSetup()) {
continue;
}
if (!arena.getLadders().contains(praxiPlayer.getDuelProcedure().getLadder().getName())) {
continue;
}
if (praxiPlayer.getDuelProcedure().getLadder().isBuild() && arena.getType() == ArenaType.SHARED) {
continue;
}
if (praxiPlayer.getDuelProcedure().getLadder().isBuild() && arena.getType() != ArenaType.STANDALONE) {
continue;
}
if (praxiPlayer.getDuelProcedure().getLadder().isBuild() && arena.isActive()) {
continue;
}
buttons.put(buttons.size(), new SelectArenaButton(arena));
}
return buttons;
}
@Override
public void onClose(Player player) {
if (!this.isClosedByMenu()) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setDuelProcedure(null);
}
}
@AllArgsConstructor
private class SelectArenaButton extends Button {
private Arena arena;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.PAPER).name(Style.GREEN + Style.BOLD + this.arena.getName()).build();
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
// Update and request the procedure
praxiPlayer.getDuelProcedure().setArena(this.arena);
praxiPlayer.getDuelProcedure().send();
// Set closed by menu
Menu.currentlyOpenedMenus.get(player.getName()).setClosedByMenu(true);
// Force close inventory
player.closeInventory();
}
}
}

View File

@ -0,0 +1,82 @@
package me.joeleoli.praxi.duel.gui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class DuelSelectLadderMenu extends Menu {
@Override
public String getTitle(Player player) {
return Style.GOLD + Style.BOLD + "Select a ladder";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
Map<Integer, Button> buttons = new HashMap<>();
for (Ladder ladder : Ladder.getLadders()) {
if (ladder.isEnabled()) {
buttons.put(buttons.size(), new SelectLadderButton(ladder));
}
}
return buttons;
}
@Override
public void onClose(Player player) {
if (!this.isClosedByMenu()) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setDuelProcedure(null);
}
}
@AllArgsConstructor
private class SelectLadderButton extends Button {
private Ladder ladder;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(this.ladder.getDisplayIcon())
.name(Style.PINK + Style.BOLD + this.ladder.getName())
.lore(Arrays.asList(
"",
Style.YELLOW + "Click here to select " + Style.PINK + Style.BOLD +
this.ladder.getName() + Style.YELLOW + "."
))
.build();
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
// Update duel procedure
praxiPlayer.getDuelProcedure().setLadder(this.ladder);
// Set closed by menu
Menu.currentlyOpenedMenus.get(player.getName()).setClosedByMenu(true);
// Force close inventory
player.closeInventory();
// Open arena selection menu
new DuelSelectArenaMenu().openMenu(player);
}
}
}

View File

@ -0,0 +1,55 @@
package me.joeleoli.praxi.elo;
public class EloUtil {
private static final KFactor[] K_FACTORS = {
new KFactor(0, 1000, 25),
new KFactor(1001, 1400, 20),
new KFactor(1401, 1800, 15),
new KFactor(1801, 2200, 10)
};
private static final int DEFAULT_K_FACTOR = 25;
private static final int WIN = 1;
private static final int LOSS = 0;
public static int getNewRating(int rating, int opponentRating, boolean won) {
if (won) {
return EloUtil.getNewRating(rating, opponentRating, EloUtil.WIN);
} else {
return EloUtil.getNewRating(rating, opponentRating, EloUtil.LOSS);
}
}
public static int getNewRating(int rating, int opponentRating, int score) {
double kFactor = EloUtil.getKFactor(rating);
double expectedScore = EloUtil.getExpectedScore(rating, opponentRating);
int newRating = EloUtil.calculateNewRating(rating, score, expectedScore, kFactor);
if (score == 1) {
if (newRating == rating) {
newRating++;
}
}
return newRating;
}
private static int calculateNewRating(int oldRating, int score, double expectedScore, double kFactor) {
return oldRating + (int) (kFactor * (score - expectedScore));
}
private static double getKFactor(int rating) {
for (int i = 0; i < EloUtil.K_FACTORS.length; i++) {
if (rating >= EloUtil.K_FACTORS[i].getStartIndex() && rating <= EloUtil.K_FACTORS[i].getEndIndex()) {
return EloUtil.K_FACTORS[i].getValue();
}
}
return EloUtil.DEFAULT_K_FACTOR;
}
private static double getExpectedScore(int rating, int opponentRating) {
return 1 / (1 + Math.pow(10, ((double) (opponentRating - rating) / 400)));
}
}

View File

@ -0,0 +1,14 @@
package me.joeleoli.praxi.elo;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public class KFactor {
private final int startIndex;
private final int endIndex;
private final double value;
}

View File

@ -0,0 +1,253 @@
package me.joeleoli.praxi.events;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.chat.ChatComponentBuilder;
import me.joeleoli.nucleus.cooldown.Cooldown;
import me.joeleoli.nucleus.player.PlayerInfo;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.events.task.EventStartTask;
import me.joeleoli.praxi.player.PlayerState;
import me.joeleoli.praxi.player.PraxiPlayer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@Getter
public abstract class Event {
protected static final String EVENT_PREFIX = Style.GOLD + Style.BOLD + "[Event] " + Style.RESET;
private static final HoverEvent HOVER_EVENT = new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new ChatComponentBuilder("").parse(Style.YELLOW + "Click to join the Sumo event.").create()
);
private static final ClickEvent CLICK_EVENT = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/event join");
private String name;
@Setter
private EventState state = EventState.WAITING;
private EventTask eventTask;
private PlayerInfo host;
private Map<UUID, EventPlayer> eventPlayers = new HashMap<>();
private int maxPlayers;
@Setter
private Cooldown cooldown;
public Event(String name, PlayerInfo host, int maxPlayers) {
this.name = name;
this.host = host;
this.maxPlayers = maxPlayers;
}
public void setEventTask(EventTask task) {
if (this.eventTask != null) {
this.eventTask.cancel();
}
this.eventTask = task;
if (this.eventTask != null) {
this.eventTask.runTaskTimer(Praxi.getInstance(), 0L, 20L);
}
}
public boolean isWaiting() {
return this.state == EventState.WAITING;
}
public boolean isFighting() {
return this.state == EventState.ROUND_FIGHTING;
}
public EventPlayer getEventPlayer(UUID uuid) {
return this.eventPlayers.get(uuid);
}
public List<Player> getPlayers() {
List<Player> players = new ArrayList<>();
for (EventPlayer eventPlayer : this.eventPlayers.values()) {
final Player player = eventPlayer.toPlayer();
if (player != null) {
players.add(player);
}
}
return players;
}
public int getRemainingPlayers() {
int remaining = 0;
for (EventPlayer eventPlayer : this.eventPlayers.values()) {
if (eventPlayer.getState() == EventPlayerState.WAITING) {
remaining++;
}
}
return remaining;
}
public void handleStart() {
this.setEventTask(new EventStartTask(this));
}
public void handleJoin(Player player) {
this.eventPlayers.put(player.getUniqueId(), new EventPlayer(player));
this.broadcastMessage(Style.PINK + player.getName() + Style.YELLOW + " joined the event " + Style.PINK + "(" +
this.getRemainingPlayers() + "/" + this.getMaxPlayers() + ")");
this.onJoin(player);
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setEvent(this);
praxiPlayer.setState(PlayerState.IN_EVENT);
praxiPlayer.loadHotbar();
player.teleport(Praxi.getInstance().getEventManager().getSumoSpectator());
}
public void handleDeath(Player player) {
final EventPlayer loser = this.getEventPlayer(player.getUniqueId());
loser.setState(EventPlayerState.ELIMINATED);
this.onDeath(player);
}
public void handleLeave(Player player) {
if (this.isFighting(player.getUniqueId())) {
this.handleDeath(player);
}
this.eventPlayers.remove(player.getUniqueId());
this.onLeave(player);
this.getPlayers().forEach(otherPlayer -> {
player.hidePlayer(otherPlayer);
otherPlayer.hidePlayer(player);
});
if (this.state == EventState.WAITING) {
this.broadcastMessage(Style.PINK + player.getName() + Style.YELLOW + " left the event " + Style.PINK +
"(" + this.getRemainingPlayers() + "/" + this.getMaxPlayers() + ")");
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setState(PlayerState.IN_LOBBY);
praxiPlayer.setEvent(null);
praxiPlayer.loadHotbar();
PlayerUtil.spawn(player);
}
public void end() {
// Remove active event and set cooldown
Praxi.getInstance().getEventManager().setActiveEvent(null);
Praxi.getInstance().getEventManager().setEventCooldown(new Cooldown(60_000L * 3));
// Cancel any active task
this.setEventTask(null);
final Player winner = this.getWinner();
final List<Player> players = this.getPlayers();
if (winner == null) {
PlayerUtil.messageAll(EVENT_PREFIX + Style.YELLOW + "The event has been canceled.");
} else {
PlayerUtil.messageAll(EVENT_PREFIX + Style.PINK + winner.getName() + Style.YELLOW + " has won the event!");
}
for (EventPlayer eventPlayer : this.eventPlayers.values()) {
final Player player = eventPlayer.toPlayer();
if (player != null) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setState(PlayerState.IN_LOBBY);
praxiPlayer.setEvent(null);
praxiPlayer.loadHotbar();
PlayerUtil.spawn(player);
}
}
players.forEach(player -> players.forEach(otherPlayer -> {
player.hidePlayer(otherPlayer);
otherPlayer.hidePlayer(player);
}));
}
public boolean canEnd() {
int remaining = 0;
for (EventPlayer eventPlayer : this.eventPlayers.values()) {
if (eventPlayer.getState() == EventPlayerState.WAITING) {
remaining++;
}
}
return remaining == 1;
}
public Player getWinner() {
for (EventPlayer eventPlayer : this.eventPlayers.values()) {
if (eventPlayer.getState() != EventPlayerState.ELIMINATED) {
return eventPlayer.toPlayer();
}
}
return null;
}
public void announce() {
BaseComponent[] components = new ChatComponentBuilder("")
.parse(EVENT_PREFIX + Style.PINK + this.getHost().getName() + Style.YELLOW + " is hosting a " +
Style.PINK + this.getName() + " Event " + Style.GRAY + "[Click to join]")
.attachToEachPart(HOVER_EVENT)
.attachToEachPart(CLICK_EVENT)
.create();
for (Player player : Bukkit.getOnlinePlayers()) {
player.sendMessage(components);
}
}
public void broadcastMessage(String message) {
for (Player player : this.getPlayers()) {
player.sendMessage(EVENT_PREFIX + message);
}
}
public abstract boolean isSumo();
public abstract boolean isCorners();
public abstract void onJoin(Player player);
public abstract void onLeave(Player player);
public abstract void onRound();
public abstract void onDeath(Player player);
public abstract String getRoundDuration();
public abstract EventPlayer getRoundPlayerA();
public abstract EventPlayer getRoundPlayerB();
public abstract boolean isFighting(UUID uuid);
}

View File

@ -0,0 +1,77 @@
package me.joeleoli.praxi.events;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.config.ConfigCursor;
import me.joeleoli.nucleus.cooldown.Cooldown;
import me.joeleoli.nucleus.util.LocationUtil;
import me.joeleoli.praxi.Praxi;
import org.bukkit.Location;
@Getter
@Setter
public class EventManager {
private Event activeEvent;
private Cooldown eventCooldown = new Cooldown(0);
private Location sumoSpectator, sumoSpawn1, sumoSpawn2;
private String sumoKbProfile;
public void setActiveEvent(Event event) {
if (this.activeEvent != null) {
this.activeEvent.setEventTask(null);
}
if (event == null) {
this.activeEvent = null;
return;
}
this.activeEvent = event;
this.activeEvent.handleStart();
this.activeEvent.handleJoin(event.getHost().toPlayer());
}
public void load() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getMainConfig(), "event");
if (cursor.exists("sumo.spectator")) {
this.sumoSpectator = LocationUtil.deserialize(cursor.getString("sumo.spectator"));
}
if (cursor.exists("sumo.spawn1")) {
this.sumoSpawn1 = LocationUtil.deserialize(cursor.getString("sumo.spawn1"));
}
if (cursor.exists("sumo.spawn2")) {
this.sumoSpawn2 = LocationUtil.deserialize(cursor.getString("sumo.spawn2"));
}
if (cursor.exists("sumo.kb-profile")) {
this.sumoKbProfile = cursor.getString("sumo.kb-profile");
}
}
public void save() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getMainConfig(), "event");
if (this.sumoSpectator != null) {
cursor.set("sumo.spectator", LocationUtil.serialize(this.sumoSpectator));
}
if (this.sumoSpawn1 != null) {
cursor.set("sumo.spawn1", LocationUtil.serialize(this.sumoSpawn1));
}
if (this.sumoSpawn2 != null) {
cursor.set("sumo.spawn2", LocationUtil.serialize(this.sumoSpawn2));
}
if (this.sumoKbProfile != null) {
cursor.set("sumo.kb-profile", this.sumoKbProfile);
}
cursor.save();
}
}

View File

@ -0,0 +1,23 @@
package me.joeleoli.praxi.events;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.player.PlayerInfo;
import org.bukkit.entity.Player;
@Getter
@Setter
public class EventPlayer extends PlayerInfo {
private EventPlayerState state = EventPlayerState.WAITING;
private int roundWins = 0;
public EventPlayer(Player player) {
super(player.getUniqueId(), player.getName());
}
public void incrementRoundWins() {
this.roundWins++;
}
}

View File

@ -0,0 +1,15 @@
package me.joeleoli.praxi.events;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum EventPlayerState {
WAITING("Waiting"),
ELIMINATED("Eliminated");
private String readable;
}

View File

@ -0,0 +1,10 @@
package me.joeleoli.praxi.events;
public enum EventState {
WAITING,
ROUND_STARTING,
ROUND_FIGHTING,
ROUND_ENDING,
}

View File

@ -0,0 +1,37 @@
package me.joeleoli.praxi.events;
import lombok.Getter;
import me.joeleoli.praxi.Praxi;
import org.bukkit.scheduler.BukkitRunnable;
@Getter
public abstract class EventTask extends BukkitRunnable {
private int ticks;
private Event event;
private EventState eventState;
public EventTask(Event event, EventState eventState) {
this.event = event;
this.eventState = eventState;
}
@Override
public void run() {
if (Praxi.getInstance().getEventManager().getActiveEvent() == null || !Praxi.getInstance().getEventManager().getActiveEvent().equals(this.event) || this.event.getState() != this.eventState) {
this.cancel();
return;
}
this.onRun();
this.ticks++;
}
public int getSeconds() {
return 3 - this.ticks;
}
public abstract void onRun();
}

View File

@ -0,0 +1,165 @@
package me.joeleoli.praxi.events.impl;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.player.PlayerInfo;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TimeUtil;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.events.EventPlayer;
import me.joeleoli.praxi.events.EventPlayerState;
import me.joeleoli.praxi.events.EventState;
import me.joeleoli.praxi.events.task.EventRoundEndTask;
import me.joeleoli.praxi.events.task.EventRoundStartTask;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Player;
@Getter
public class SumoEvent extends Event {
private EventPlayer roundPlayerA;
private EventPlayer roundPlayerB;
@Setter
private long roundStart;
public SumoEvent(Player player) {
super("Sumo", new PlayerInfo(player), 100);
}
@Override
public boolean isSumo() {
return true;
}
@Override
public boolean isCorners() {
return false;
}
@Override
public void onJoin(Player player) {
this.getPlayers().forEach(otherPlayer -> {
player.showPlayer(otherPlayer);
otherPlayer.showPlayer(player);
});
}
@Override
public void onLeave(Player player) {
player.setKnockbackProfile(null);
}
@Override
public void onRound() {
this.setState(EventState.ROUND_STARTING);
if (this.roundPlayerA != null) {
final Player player = this.roundPlayerA.toPlayer();
if (player != null) {
player.teleport(Praxi.getInstance().getEventManager().getSumoSpectator());
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInEvent()) {
praxiPlayer.loadHotbar();
}
}
this.roundPlayerA = null;
}
if (this.roundPlayerB != null) {
final Player player = this.roundPlayerB.toPlayer();
if (player != null) {
player.teleport(Praxi.getInstance().getEventManager().getSumoSpectator());
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInEvent()) {
praxiPlayer.loadHotbar();
}
}
this.roundPlayerB = null;
}
this.roundPlayerA = this.findRoundPlayer();
this.roundPlayerB = this.findRoundPlayer();
final Player playerA = this.roundPlayerA.toPlayer();
final Player playerB = this.roundPlayerB.toPlayer();
PlayerUtil.reset(playerA);
PlayerUtil.reset(playerB);
PlayerUtil.denyMovement(playerA);
PlayerUtil.denyMovement(playerB);
playerA.teleport(Praxi.getInstance().getEventManager().getSumoSpawn1());
playerB.teleport(Praxi.getInstance().getEventManager().getSumoSpawn2());
this.setEventTask(new EventRoundStartTask(this));
}
@Override
public void onDeath(Player player) {
final EventPlayer winner = this.roundPlayerA.getUuid().equals(player.getUniqueId()) ? this.roundPlayerB : this.roundPlayerA;
winner.setState(EventPlayerState.WAITING);
winner.incrementRoundWins();
this.broadcastMessage(Style.PINK + player.getName() + Style.YELLOW + " was eliminated by " + Style.PINK + winner.getName() + Style.YELLOW + "!");
this.setState(EventState.ROUND_ENDING);
this.setEventTask(new EventRoundEndTask(this));
}
@Override
public String getRoundDuration() {
if (this.getState() == EventState.ROUND_STARTING) {
return "00:00";
} else if (this.getState() == EventState.ROUND_FIGHTING) {
return TimeUtil.millisToTimer(System.currentTimeMillis() - this.roundStart);
} else {
return "Ending";
}
}
@Override
public boolean isFighting(UUID uuid) {
return (this.roundPlayerA != null && this.roundPlayerA.getUuid().equals(uuid)) || (this.roundPlayerB != null && this.roundPlayerB.getUuid().equals(uuid));
}
private EventPlayer findRoundPlayer() {
EventPlayer eventPlayer = null;
for (EventPlayer check : this.getEventPlayers().values()) {
if (!this.isFighting(check.getUuid()) && check.getState() == EventPlayerState.WAITING) {
if (eventPlayer == null) {
eventPlayer = check;
continue;
}
if (check.getRoundWins() == 0) {
eventPlayer = check;
continue;
}
if (check.getRoundWins() <= eventPlayer.getRoundWins()) {
eventPlayer = check;
}
}
}
if (eventPlayer == null) {
throw new RuntimeException("Could not find a new round player");
}
return eventPlayer;
}
}

View File

@ -0,0 +1,24 @@
package me.joeleoli.praxi.events.task;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.events.EventState;
import me.joeleoli.praxi.events.EventTask;
public class EventRoundEndTask extends EventTask {
public EventRoundEndTask(Event event) {
super(event, EventState.ROUND_ENDING);
}
@Override
public void onRun() {
if (this.getTicks() >= 3) {
if (this.getEvent().canEnd()) {
this.getEvent().end();
} else {
this.getEvent().onRound();
}
}
}
}

View File

@ -0,0 +1,39 @@
package me.joeleoli.praxi.events.task;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.events.EventState;
import me.joeleoli.praxi.events.EventTask;
import me.joeleoli.praxi.events.impl.SumoEvent;
import org.bukkit.entity.Player;
public class EventRoundStartTask extends EventTask {
public EventRoundStartTask(Event event) {
super(event, EventState.ROUND_STARTING);
}
@Override
public void onRun() {
if (this.getTicks() >= 3) {
this.getEvent().setEventTask(null);
this.getEvent().setState(EventState.ROUND_FIGHTING);
final Player playerA = this.getEvent().getRoundPlayerA().toPlayer();
final Player playerB = this.getEvent().getRoundPlayerB().toPlayer();
PlayerUtil.allowMovement(playerA);
PlayerUtil.allowMovement(playerB);
((SumoEvent) this.getEvent()).setRoundStart(System.currentTimeMillis());
} else {
final int seconds = this.getSeconds();
this.getEvent().broadcastMessage(
Style.YELLOW + "The round will start in " + Style.PINK + (seconds) + " second" +
(seconds == 1 ? "" : "s") + Style.YELLOW + "...");
}
}
}

View File

@ -0,0 +1,45 @@
package me.joeleoli.praxi.events.task;
import me.joeleoli.nucleus.cooldown.Cooldown;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.events.EventState;
import me.joeleoli.praxi.events.EventTask;
public class EventStartTask extends EventTask {
public EventStartTask(Event event) {
super(event, EventState.WAITING);
}
@Override
public void onRun() {
if (this.getTicks() >= 600) {
this.getEvent().end();
return;
}
if (this.getEvent().getPlayers().size() <= 1 && this.getEvent().getCooldown() != null) {
this.getEvent().setCooldown(null);
this.getEvent().broadcastMessage(Style.YELLOW + "There are not enough players for the event to start.");
}
if (this.getEvent().getPlayers().size() == this.getEvent().getMaxPlayers() || (this.getTicks() >= 30 && this.getEvent().getPlayers().size() >= 2)) {
if (this.getEvent().getCooldown() == null) {
this.getEvent().setCooldown(new Cooldown(11_000));
this.getEvent().broadcastMessage(Style.YELLOW + "The event will start in " + Style.PINK + "10 seconds" + Style.YELLOW + "...");
} else {
if (this.getEvent().getCooldown().hasExpired()) {
this.getEvent().setState(EventState.ROUND_STARTING);
this.getEvent().onRound();
this.getEvent().setEventTask(new EventRoundStartTask(this.getEvent()));
}
}
}
if (this.getTicks() % 10 == 0) {
this.getEvent().announce();
}
}
}

View File

@ -0,0 +1,67 @@
package me.joeleoli.praxi.handler;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.events.EventState;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.ragespigot.handler.MovementHandler;
import net.minecraft.server.v1_8_R3.PacketPlayInFlying;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
public class PlayerMovementHandler implements MovementHandler {
@Override
public void handleUpdateLocation(Player player, Location from, Location to, PacketPlayInFlying packetPlayInFlying) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInLobby() || praxiPlayer.isInQueue()) {
if (player.getGameMode() != GameMode.CREATIVE) {
if (to.getX() >= 200 || to.getX() <= -200 || to.getZ() >= 200 || to.getZ() <= -200) {
PlayerUtil.spawn(player);
}
}
} else if (praxiPlayer.isInMatch()) {
if (praxiPlayer.getMatch().getLadder().isSumo() || praxiPlayer.getMatch().getLadder().isSpleef()) {
final Match match = praxiPlayer.getMatch();
if (match.isFighting()) {
if (player.getLocation().getBlock().getType() == Material.WATER ||
player.getLocation().getBlock().getType() == Material.STATIONARY_WATER) {
Player killer = player.getKiller();
if (killer == null) {
if (match.isSoloMatch()) {
killer = praxiPlayer.getMatch().getOpponentPlayer(player);
}
}
match.handleDeath(player, killer, false);
}
}
}
} else if (praxiPlayer.isInEvent()) {
final Event event = praxiPlayer.getEvent();
if (event.isSumo()) {
if (event.getState() == EventState.ROUND_FIGHTING) {
if (event.isFighting(player.getUniqueId())) {
if (player.getLocation().getBlock().getType() == Material.WATER ||
player.getLocation().getBlock().getType() == Material.STATIONARY_WATER) {
event.handleDeath(player);
}
}
}
}
}
}
@Override
public void handleUpdateRotation(Player player, Location from, Location to, PacketPlayInFlying packetPlayInFlying) {
}
}

View File

@ -0,0 +1,27 @@
package me.joeleoli.praxi.kit;
import lombok.Data;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@Data
public class Kit {
public static final ItemStack DEFAULT_KIT = new ItemBuilder(Material.BOOK).name(Style.GOLD + "Default Kit").build();
private ItemStack[] armor;
private ItemStack[] contents;
public Kit() {
this.armor = new ItemStack[4];
this.contents = new ItemStack[36];
}
public Kit(ItemStack[] armor, ItemStack[] contents) {
this.armor = armor;
this.contents = contents;
}
}

View File

@ -0,0 +1,12 @@
package me.joeleoli.praxi.kit;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class NamedKit extends Kit {
private String name;
}

View File

@ -0,0 +1,280 @@
package me.joeleoli.praxi.kit.gui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.menu.buttons.DisplayButton;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.ItemUtil;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.praxi.kit.NamedKit;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class KitEditorMenu extends Menu {
private static final int[] ITEM_POSITIONS = new int[]{
20, 21, 22, 23, 24, 25, 26, 29, 30, 31, 32, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 52,
53
};
private static final int[] BORDER_POSITIONS = new int[]{ 1, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 28, 37, 46 };
private static final Button BORDER_BUTTON = Button.placeholder(Material.COAL_BLOCK, (byte) 0, " ");
public KitEditorMenu() {
this.setUpdateAfterClick(false);
}
@Override
public String getTitle(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
return Style.GOLD + "Editing " + Style.AQUA + praxiPlayer.getKitEditor().getSelectedKit().getName();
}
@Override
public Map<Integer, Button> getButtons(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
NamedKit kit = praxiPlayer.getKitEditor().getSelectedKit();
Map<Integer, Button> buttons = new HashMap<>();
for (int border : BORDER_POSITIONS) {
buttons.put(border, BORDER_BUTTON);
}
buttons.put(0, new CurrentKitButton());
buttons.put(2, new SaveButton());
buttons.put(6, new LoadDefaultKitButton());
buttons.put(7, new ClearInventoryButton());
buttons.put(8, new CancelButton());
buttons.put(18, new ArmorDisplayButton(kit.getArmor()[3]));
buttons.put(27, new ArmorDisplayButton(kit.getArmor()[2]));
buttons.put(36, new ArmorDisplayButton(kit.getArmor()[1]));
buttons.put(45, new ArmorDisplayButton(kit.getArmor()[0]));
List<ItemStack> items = praxiPlayer.getKitEditor().getSelectedLadder().getKitEditorItems();
for (int i = 20; i < (praxiPlayer.getKitEditor().getSelectedLadder().getKitEditorItems().size() + 20); i++) {
buttons.put(ITEM_POSITIONS[i - 20], new InfiniteItemButton(items.get(i - 20)));
}
return buttons;
}
@Override
public void onOpen(Player player) {
if (!this.isClosedByMenu()) {
PlayerUtil.reset(player);
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.getKitEditor().setActive(true);
if (praxiPlayer.getKitEditor().getSelectedKit() != null) {
player.getInventory().setContents(praxiPlayer.getKitEditor().getSelectedKit().getContents());
}
player.updateInventory();
}
}
@Override
public void onClose(Player player) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.getKitEditor().setActive(false);
if (!praxiPlayer.isInMatch()) {
TaskUtil.runLater(praxiPlayer::loadHotbar, 1L);
}
}
@AllArgsConstructor
private class ArmorDisplayButton extends Button {
private ItemStack itemStack;
@Override
public ItemStack getButtonItem(Player player) {
if (this.itemStack == null || this.itemStack.getType() == Material.AIR) {
return new ItemStack(Material.AIR);
}
return new ItemBuilder(this.itemStack.clone())
.name(Style.AQUA + ItemUtil.getName(this.itemStack))
.lore(Arrays.asList(
"",
Style.YELLOW + "This is automatically equipped."
))
.build();
}
}
@AllArgsConstructor
private class CurrentKitButton extends Button {
@Override
public ItemStack getButtonItem(Player player) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
return new ItemBuilder(Material.NAME_TAG)
.name(Style.GREEN + Style.BOLD + "Editing: " + Style.AQUA +
praxiPlayer.getKitEditor().getSelectedKit().getName())
.build();
}
}
@AllArgsConstructor
private class ClearInventoryButton extends Button {
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.STAINED_CLAY)
.durability(7)
.name(Style.YELLOW + Style.BOLD + "Clear Inventory")
.lore(Arrays.asList(
"",
Style.YELLOW + "This will clear your inventory",
Style.YELLOW + "so you can start over."
))
.build();
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
Button.playNeutral(player);
player.getInventory().setContents(new ItemStack[36]);
player.updateInventory();
}
@Override
public boolean shouldUpdate(Player player, int i, ClickType clickType) {
return true;
}
}
@AllArgsConstructor
private class LoadDefaultKitButton extends Button {
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.STAINED_CLAY)
.durability(7)
.name(Style.YELLOW + Style.BOLD + "Load default kit")
.lore(Arrays.asList(
"",
Style.YELLOW + "Click this to load the default kit",
Style.YELLOW + "into the kit editing menu."
))
.build();
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
Button.playNeutral(player);
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
player.getInventory()
.setContents(praxiPlayer.getKitEditor().getSelectedLadder().getDefaultKit().getContents());
player.updateInventory();
}
@Override
public boolean shouldUpdate(Player player, int i, ClickType clickType) {
return true;
}
}
@AllArgsConstructor
private class SaveButton extends Button {
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.STAINED_CLAY)
.durability(5)
.name(Style.GREEN + Style.BOLD + "Save")
.lore(Arrays.asList(
"",
Style.YELLOW + "Click this to save your kit."
))
.build();
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
Button.playNeutral(player);
player.closeInventory();
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getKitEditor().getSelectedKit() != null) {
praxiPlayer.getKitEditor().getSelectedKit().setContents(player.getInventory().getContents());
}
praxiPlayer.loadHotbar();
new KitManagementMenu(praxiPlayer.getKitEditor().getSelectedLadder()).openMenu(player);
}
}
@AllArgsConstructor
private class CancelButton extends Button {
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.STAINED_CLAY)
.durability(14)
.name(Style.RED + Style.BOLD + "Cancel")
.lore(Arrays.asList(
"",
Style.YELLOW + "Click this to abort editing your kit,",
Style.YELLOW + "and return to the kit menu."
))
.build();
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
Button.playNeutral(player);
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getKitEditor().getSelectedLadder() != null) {
new KitManagementMenu(praxiPlayer.getKitEditor().getSelectedLadder()).openMenu(player);
}
}
}
private class InfiniteItemButton extends DisplayButton {
InfiniteItemButton(ItemStack itemStack) {
super(itemStack, false);
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
final Inventory inventory = player.getOpenInventory().getTopInventory();
final ItemStack itemStack = inventory.getItem(i);
inventory.setItem(i, itemStack);
player.setItemOnCursor(itemStack);
player.updateInventory();
}
}
}

View File

@ -0,0 +1,239 @@
package me.joeleoli.praxi.kit.gui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.kit.NamedKit;
import me.joeleoli.praxi.kit.gui.button.BackButton;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class KitManagementMenu extends Menu {
private static final Button PLACEHOLDER = Button.placeholder(Material.STAINED_GLASS_PANE, (byte) 7, " ");
private Ladder ladder;
public KitManagementMenu(Ladder ladder) {
this.ladder = ladder;
this.setPlaceholder(true);
this.setUpdateAfterClick(false);
}
@Override
public String getTitle(Player player) {
return Style.GOLD + "Viewing " + this.ladder.getName() + " kits";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
final Map<Integer, Button> buttons = new HashMap<>();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
NamedKit[] kits = praxiPlayer.getKits(this.ladder);
if (kits == null) {
return buttons;
}
int startPos = -1;
for (int i = 0; i < 4; i++) {
NamedKit kit = kits[i];
startPos += 2;
buttons.put(startPos, kit == null ? new CreateKitButton(i) : new KitDisplayButton(kit));
buttons.put(startPos + 18, new LoadKitButton(i));
buttons.put(startPos + 27, kit == null ? PLACEHOLDER : new RenameKitButton(kit));
buttons.put(startPos + 36, kit == null ? PLACEHOLDER : new DeleteKitButton(kit));
}
buttons.put(36, new BackButton(new SelectLadderKitMenu()));
return buttons;
}
@Override
public void onClose(Player player) {
if (!this.isClosedByMenu()) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setState(praxiPlayer.getKitEditor().getPreviousState());
praxiPlayer.getKitEditor().setSelectedLadder(null);
}
}
@AllArgsConstructor
private class DeleteKitButton extends Button {
private NamedKit kit;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.STAINED_CLAY)
.name(Style.RED + Style.BOLD + "Delete")
.durability(14)
.lore(Arrays.asList(
"",
Style.RED + "Click to delete this kit.",
Style.RED + "You will " + Style.BOLD + "NOT" + Style.RED + " be able to",
Style.RED + "recover this kit."
))
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hotbarSlot) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.deleteKit(praxiPlayer.getKitEditor().getSelectedLadder(), this.kit);
new KitManagementMenu(praxiPlayer.getKitEditor().getSelectedLadder()).openMenu(player);
}
}
@AllArgsConstructor
private class CreateKitButton extends Button {
private int index;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.IRON_SWORD)
.name(Style.GREEN + Style.BOLD + "Create Kit")
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hotbarSlot) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
final Ladder ladder = praxiPlayer.getKitEditor().getSelectedLadder();
// TODO: this shouldn't be null but sometimes it is?
if (ladder == null) {
player.closeInventory();
return;
}
final NamedKit kit = new NamedKit("Kit " + (this.index + 1));
if (ladder.getDefaultKit() != null) {
if (ladder.getDefaultKit().getArmor() != null) {
kit.setArmor(ladder.getDefaultKit().getArmor());
}
if (ladder.getDefaultKit().getContents() != null) {
kit.setContents(ladder.getDefaultKit().getContents());
}
}
praxiPlayer.replaceKit(ladder, this.index, kit);
praxiPlayer.getKitEditor().setSelectedKit(kit);
new KitEditorMenu().openMenu(player);
}
}
@AllArgsConstructor
private class RenameKitButton extends Button {
private NamedKit kit;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.SIGN)
.name(Style.YELLOW + Style.BOLD + "Rename")
.lore(Arrays.asList(
"",
Style.YELLOW + "Click to rename this kit."
))
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hotbarSlot) {
Menu.currentlyOpenedMenus.get(player.getName()).setClosedByMenu(true);
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.getKitEditor().setActive(true);
praxiPlayer.getKitEditor().setRename(true);
praxiPlayer.getKitEditor().setSelectedKit(this.kit);
player.closeInventory();
player.sendMessage(
Style.YELLOW + "Renaming " + Style.BOLD + this.kit.getName() + Style.YELLOW + "... " + Style.GREEN +
"Enter the new name now.");
}
}
@AllArgsConstructor
private class LoadKitButton extends Button {
private int index;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.BOOK)
.name(Style.GREEN + Style.BOLD + "Load/Edit")
.lore(Arrays.asList(
"",
Style.YELLOW + "Click to edit this kit."
))
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hotbarSlot) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
// TODO: this shouldn't be null but sometimes it is?
if (praxiPlayer.getKitEditor().getSelectedLadder() == null) {
player.closeInventory();
return;
}
NamedKit kit = praxiPlayer.getKit(praxiPlayer.getKitEditor().getSelectedLadder(), this.index);
if (kit == null) {
kit = new NamedKit("Kit " + (this.index + 1));
kit.setArmor(praxiPlayer.getKitEditor().getSelectedLadder().getDefaultKit().getArmor());
kit.setContents(praxiPlayer.getKitEditor().getSelectedLadder().getDefaultKit().getContents());
praxiPlayer.replaceKit(praxiPlayer.getKitEditor().getSelectedLadder(), this.index, kit);
}
praxiPlayer.getKitEditor().setSelectedKit(kit);
new KitEditorMenu().openMenu(player);
}
}
@AllArgsConstructor
private class KitDisplayButton extends Button {
private NamedKit kit;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.BOOK)
.name(Style.GREEN + Style.BOLD + this.kit.getName())
.build();
}
}
}

View File

@ -0,0 +1,67 @@
package me.joeleoli.praxi.kit.gui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class SelectLadderKitMenu extends Menu {
@Override
public String getTitle(Player player) {
return Style.GOLD + Style.BOLD + "Select a ladder";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
Map<Integer, Button> buttons = new HashMap<>();
Ladder.getLadders().forEach(ladder -> {
if (ladder.isEnabled()) {
buttons.put(buttons.size(), new LadderKitDisplayButton(ladder));
}
});
return buttons;
}
@AllArgsConstructor
private class LadderKitDisplayButton extends Button {
private Ladder ladder;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(this.ladder.getDisplayIcon())
.name(Style.PINK + Style.BOLD + this.ladder.getName())
.lore(Arrays.asList(
"",
Style.YELLOW + "Click to select " + Style.PINK + Style.BOLD + this.ladder.getName() +
Style.YELLOW + "."
))
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hotbarSlot) {
player.closeInventory();
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.getKitEditor().setSelectedLadder(this.ladder);
praxiPlayer.getKitEditor().setPreviousState(praxiPlayer.getState());
new KitManagementMenu(this.ladder).openMenu(player);
}
}
}

View File

@ -0,0 +1,33 @@
package me.joeleoli.praxi.kit.gui.button;
import java.util.Arrays;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
@AllArgsConstructor
public class BackButton extends Button {
private Menu back;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.REDSTONE).name(Style.RED + Style.BOLD + "Back").lore(Arrays
.asList(Style.RED + "Click here to return to", Style.RED + "the previous menu.")).build();
}
@Override
public void clicked(Player player, int i, ClickType clickType, int hb) {
Button.playNeutral(player);
this.back.openMenu(player);
}
}

View File

@ -0,0 +1,86 @@
package me.joeleoli.praxi.ladder;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
import lombok.Getter;
import me.joeleoli.nucleus.config.ConfigCursor;
import me.joeleoli.nucleus.util.InventoryUtil;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.kit.Kit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@Data
public class Ladder {
@Getter
private static List<Ladder> ladders = new ArrayList<>();
private String name;
private String displayName;
private ItemStack displayIcon;
private Kit defaultKit = new Kit();
private List<ItemStack> kitEditorItems = new ArrayList<>();
private boolean enabled, build, sumo, parkour, spleef, regeneration, allowPotionFill;
private int hitDelay = 20;
private String kbProfile;
public Ladder(String name) {
this.name = name;
this.displayName = ChatColor.AQUA + this.name;
this.displayIcon = new ItemStack(Material.DIAMOND_SWORD);
ladders.add(this);
}
public static Ladder getByName(String name) {
for (Ladder ladder : ladders) {
if (ladder.getName().equalsIgnoreCase(name)) {
return ladder;
}
}
return null;
}
public ItemStack getDisplayIcon() {
return this.displayIcon.clone();
}
public void save() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getLadderConfig(), "ladders." + this.name);
cursor.set("display-name", this.displayName);
cursor.set("display-icon.material", this.displayIcon.getType().name());
cursor.set("display-icon.durability", this.displayIcon.getDurability());
cursor.set("display-icon.amount", this.displayIcon.getAmount());
cursor.set("enabled", this.enabled);
cursor.set("build", this.build);
cursor.set("sumo", this.sumo);
cursor.set("spleef", this.spleef);
cursor.set("parkour", this.parkour);
cursor.set("regeneration", this.regeneration);
cursor.set("hit-delay", this.hitDelay);
if (this.displayIcon.hasItemMeta()) {
final ItemMeta itemMeta = this.displayIcon.getItemMeta();
if (itemMeta.hasDisplayName()) {
cursor.set("display-icon.name", itemMeta.getDisplayName());
}
if (itemMeta.hasLore()) {
cursor.set("display-icon.lore", itemMeta.getLore());
}
}
cursor.set("default-kit.armor", InventoryUtil.serializeInventory(this.defaultKit.getArmor()));
cursor.set("default-kit.contents", InventoryUtil.serializeInventory(this.defaultKit.getContents()));
cursor.save();
}
}

View File

@ -0,0 +1,103 @@
package me.joeleoli.praxi.listener;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.arena.ArenaType;
import me.joeleoli.praxi.arena.selection.Selection;
import me.joeleoli.praxi.match.Match;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
public class ArenaListener implements Listener {
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (!(event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_BLOCK)) {
return;
}
Player player = event.getPlayer();
ItemStack item = event.getItem();
Block clicked = event.getClickedBlock();
int location = 0;
if (item == null || !item.equals(Selection.SELECTION_WAND)) {
return;
}
Selection selection = Selection.createOrGetSelection(player);
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
selection.setPoint2(clicked.getLocation());
location = 2;
} else if (event.getAction() == Action.LEFT_CLICK_BLOCK) {
selection.setPoint1(clicked.getLocation());
location = 1;
}
event.setCancelled(true);
event.setUseItemInHand(Event.Result.DENY);
event.setUseInteractedBlock(Event.Result.DENY);
String message = Style.AQUA + (location == 1 ? "First" : "Second") +
" location " + Style.YELLOW + "(" + Style.GREEN +
clicked.getX() + Style.YELLOW + ", " + Style.GREEN +
clicked.getY() + Style.YELLOW + ", " + Style.GREEN +
clicked.getZ() + Style.YELLOW + ")" + Style.AQUA + " has been set!";
if (selection.isFullObject()) {
message += Style.RED + " (" + Style.YELLOW + selection.getCuboid().volume() + Style.AQUA + " blocks" +
Style.RED + ")";
}
player.sendMessage(message);
}
@EventHandler
public void onBlockFromTo(BlockFromToEvent event) {
final int x = event.getBlock().getX();
final int y = event.getBlock().getY();
final int z = event.getBlock().getZ();
Arena foundArena = null;
for (Arena arena : Arena.getArenas()) {
if (!(arena.getType() == ArenaType.STANDALONE || arena.getType() == ArenaType.DUPLICATE)) {
continue;
}
if (!arena.isActive()) {
continue;
}
if (x >= arena.getX1() && x <= arena.getX2() && y >= arena.getY1() && y <= arena.getY2() &&
z >= arena.getZ1() && z <= arena.getZ2()) {
foundArena = arena;
break;
}
}
if (foundArena == null) {
return;
}
for (Match match : Match.getMatches()) {
if (match.getArena().equals(foundArena)) {
if (match.isFighting()) {
match.getPlacedBlocks().add(event.getToBlock().getLocation());
}
break;
}
}
}
}

View File

@ -0,0 +1,178 @@
package me.joeleoli.praxi.listener;
import me.joeleoli.nucleus.Nucleus;
import me.joeleoli.nucleus.util.BukkitUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchTeam;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
public class EntityListener implements Listener {
@EventHandler
public void onEntityRegainHealth(EntityRegainHealthEvent event) {
if (event.getEntity() instanceof Player) {
if (event.getRegainReason() == EntityRegainHealthEvent.RegainReason.SATIATED) {
final Player player = (Player) event.getEntity();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInMatch()) {
if (!praxiPlayer.getMatch().getLadder().isRegeneration()) {
event.setCancelled(true);
}
} else {
event.setCancelled(true);
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
if (event.getEntity() instanceof Player) {
final Player player = (Player) event.getEntity();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInMatch()) {
if (event.getCause() == EntityDamageEvent.DamageCause.VOID) {
praxiPlayer.getMatch().handleDeath(player, null, false);
return;
}
if (!praxiPlayer.getMatch().isFighting()) {
event.setCancelled(true);
return;
}
if (praxiPlayer.getMatch().isTeamMatch()) {
if (!praxiPlayer.getMatch().getMatchPlayer(player).isAlive()) {
event.setCancelled(true);
return;
}
}
if (praxiPlayer.getMatch().getLadder().isSumo() || praxiPlayer.getMatch().getLadder().isSpleef()) {
event.setDamage(0);
player.setHealth(20.0);
player.updateInventory();
}
} else if (praxiPlayer.isInEvent()) {
if (event.getCause() == EntityDamageEvent.DamageCause.VOID) {
praxiPlayer.getEvent().handleDeath(player);
return;
}
if (praxiPlayer.getEvent().isSumo()) {
if (!praxiPlayer.getEvent().isFighting() || !praxiPlayer.getEvent().isFighting(player.getUniqueId())) {
event.setCancelled(true);
return;
}
event.setDamage(0);
player.setHealth(20.0);
player.updateInventory();
}
} else {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
final Player attacker = BukkitUtil.getDamager(event);
if (attacker != null && event.getEntity() instanceof Player) {
final Player damaged = (Player) event.getEntity();
final PraxiPlayer damagedData = PraxiPlayer.getByUuid(damaged.getUniqueId());
final PraxiPlayer attackerData = PraxiPlayer.getByUuid(attacker.getUniqueId());
if (attackerData.isSpectating() || damagedData.isSpectating()) {
event.setCancelled(true);
return;
}
if (damagedData.isInMatch() && attackerData.isInMatch()) {
final Match match = attackerData.getMatch();
if (!damagedData.getMatch().getMatchId().equals(attackerData.getMatch().getMatchId())) {
event.setCancelled(true);
return;
}
if (!match.getMatchPlayer(damaged).isAlive() || !match.getMatchPlayer(attacker).isAlive()) {
event.setCancelled(true);
return;
}
if (match.isSoloMatch()) {
attackerData.getMatch().getMatchPlayer(attacker).handleHit();
damagedData.getMatch().getMatchPlayer(damaged).resetCombo();
if (event.getDamager() instanceof Arrow) {
double health = Math.ceil(damaged.getHealth() - event.getFinalDamage()) / 2.0D;
attacker.sendMessage(Style.formatArrowHitMessage(damaged.getName(), health));
}
} else if (match.isTeamMatch()) {
final MatchTeam attackerTeam = match.getTeam(attacker);
final MatchTeam damagedTeam = match.getTeam(damaged);
if (attackerTeam == null || damagedTeam == null) {
event.setCancelled(true);
} else {
if (attackerTeam.equals(damagedTeam)) {
event.setCancelled(true);
} else {
attackerData.getMatch().getMatchPlayer(attacker).handleHit();
damagedData.getMatch().getMatchPlayer(damaged).resetCombo();
if (event.getDamager() instanceof Arrow) {
double health = Math.ceil(damaged.getHealth() - event.getFinalDamage()) / 2.0D;
attacker.sendMessage(Style.formatArrowHitMessage(damaged.getName(), health));
}
}
}
}
} else if (damagedData.isInEvent() && attackerData.isInEvent()) {
final Event praxiEvent = damagedData.getEvent();
if (!praxiEvent.isFighting() || !praxiEvent.isFighting(damaged.getUniqueId()) || !praxiEvent.isFighting(attacker.getUniqueId())) {
event.setCancelled(true);
}
}
}
}
@EventHandler
public void onFoodLevelChange(FoodLevelChangeEvent event) {
if (event.getEntity() instanceof Player) {
final Player player = (Player) event.getEntity();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInMatch() && praxiPlayer.getMatch().isFighting()) {
if (event.getFoodLevel() >= 20) {
event.setFoodLevel(20);
player.setSaturation(20);
} else {
event.setCancelled(Nucleus.RANDOM.nextInt(100) > 25);
}
} else {
event.setCancelled(true);
}
}
}
}

View File

@ -0,0 +1,624 @@
package me.joeleoli.praxi.listener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import me.joeleoli.nucleus.command.CommandHandler;
import me.joeleoli.nucleus.cooldown.Cooldown;
import me.joeleoli.nucleus.player.gui.ViewPlayerMenu;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.nucleus.util.TimeUtil;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.kit.Kit;
import me.joeleoli.praxi.kit.NamedKit;
import me.joeleoli.praxi.kit.gui.KitManagementMenu;
import me.joeleoli.praxi.kit.gui.SelectLadderKitMenu;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.party.gui.OtherPartiesMenu;
import me.joeleoli.praxi.party.gui.PartyEventSelectEventMenu;
import me.joeleoli.praxi.player.PlayerHotbar;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.praxi.queue.Queue;
import me.joeleoli.praxi.queue.gui.QueueJoinMenu;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.event.player.PlayerItemDamageEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
public class PlayerListener implements Listener {
@EventHandler
public void onPlayerItemConsume(PlayerItemConsumeEvent event) {
if (event.getItem().getType() == Material.GOLDEN_APPLE) {
if (event.getItem().hasItemMeta() &&
event.getItem().getItemMeta().getDisplayName().contains("Golden Head")) {
final Player player = event.getPlayer();
player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 200, 1));
player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 2400, 0));
player.setFoodLevel(Math.min(player.getFoodLevel() + 6, 20));
}
}
}
@EventHandler
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
final Player player = event.getPlayer();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isSpectating() && event.getRightClicked() instanceof Player && player.getItemInHand() != null) {
final Player target = (Player) event.getRightClicked();
if (PlayerHotbar.fromItemStack(player.getItemInHand()) == PlayerHotbar.HotbarItem.VIEW_INVENTORY) {
new ViewPlayerMenu(target).openMenu(player);
}
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onAsyncPlayerChat(AsyncPlayerChatEvent event) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (event.getMessage().startsWith("@") || event.getMessage().startsWith("!")) {
if (praxiPlayer.getParty() != null) {
event.setCancelled(true);
praxiPlayer.getParty().broadcast(
Style.GOLD + "[Party]" + Style.RESET + " " + event.getPlayer().getDisplayName() + Style.RESET +
": " + Style.strip(event.getMessage().substring(1)));
return;
}
}
if (praxiPlayer.getKitEditor().isRenaming()) {
event.setCancelled(true);
if (event.getMessage().length() > 16) {
event.getPlayer().sendMessage(Style.RED + "A kit name cannot be more than 16 characters long.");
return;
}
if (!praxiPlayer.isInMatch()) {
new KitManagementMenu(praxiPlayer.getKitEditor().getSelectedLadder()).openMenu(event.getPlayer());
}
praxiPlayer.getKitEditor().getSelectedKit().setName(event.getMessage());
praxiPlayer.getKitEditor().setActive(false);
praxiPlayer.getKitEditor().setRename(false);
praxiPlayer.getKitEditor().setSelectedKit(null);
}
}
@EventHandler
public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
PraxiPlayer praxiPlayer = new PraxiPlayer(event.getUniqueId(), null);
praxiPlayer.setName(event.getName());
praxiPlayer.load();
if (!praxiPlayer.isLoaded()) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage(ChatColor.RED + "Failed to load your profile. Try again later.");
return;
}
PraxiPlayer.getPlayers().put(event.getUniqueId(), praxiPlayer);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.setJoinMessage(null);
event.getPlayer().sendMessage(new String[]{
Style.getBorderLine(),
"",
Style.center(Style.YELLOW + "Welcome to " + Style.PINK + Style.BOLD + "MineXD Practice" +
Style.YELLOW + "!"),
"",
Style.center(Style.YELLOW + "Follow our twitter " + Style.PINK + "@MineXD" + Style.YELLOW +
" for updates and giveaways."),
"",
Style.getBorderLine()
});
PlayerUtil.spawn(event.getPlayer());
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
praxiPlayer.loadHotbar();
Bukkit.getOnlinePlayers().forEach(player -> {
player.hidePlayer(event.getPlayer());
event.getPlayer().hidePlayer(player);
});
}
@EventHandler
public void onPlayerKick(PlayerKickEvent event) {
if (event.getReason() != null) {
if (event.getReason().contains("Flying is not enabled")) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerQuit(PlayerQuitEvent event) {
event.setQuitMessage(null);
final PraxiPlayer praxiPlayer = PraxiPlayer.getPlayers().remove(event.getPlayer().getUniqueId());
if (praxiPlayer != null) {
if (praxiPlayer.getParty() != null) {
if (praxiPlayer.getParty().isLeader(event.getPlayer().getUniqueId())) {
praxiPlayer.getParty().disband();
} else {
praxiPlayer.getParty().leave(event.getPlayer(), false);
}
}
if (praxiPlayer.getRematchData() != null) {
final Player target =
Praxi.getInstance().getServer().getPlayer(praxiPlayer.getRematchData().getTarget());
if (target != null && target.isOnline()) {
PraxiPlayer.getByUuid(target.getUniqueId()).refreshHotbar();
}
}
TaskUtil.runAsync(praxiPlayer::save);
if (praxiPlayer.isInMatch()) {
praxiPlayer.getMatch().handleDeath(event.getPlayer(), null, true);
} else if (praxiPlayer.isInQueue()) {
Queue queue = Queue.getByUuid(praxiPlayer.getQueuePlayer().getQueueUuid());
if (queue == null) {
return;
}
queue.removePlayer(praxiPlayer.getQueuePlayer());
} else if (praxiPlayer.isInEvent()) {
praxiPlayer.getEvent().handleLeave(event.getPlayer());
}
}
}
@EventHandler(priority = EventPriority.LOW)
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getItem() != null && event.getAction().name().contains("RIGHT")) {
final Player player = event.getPlayer();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.isInMatch()) {
if (event.getItem().hasItemMeta() && event.getItem().getItemMeta().hasDisplayName()) {
if (event.getItem().equals(Kit.DEFAULT_KIT)) {
event.setCancelled(true);
final Kit kit = praxiPlayer.getMatch().getLadder().getDefaultKit();
player.getInventory().setArmorContents(kit.getArmor());
player.getInventory().setContents(kit.getContents());
player.updateInventory();
player.sendMessage(
Style.YELLOW + "You have been given the" + Style.AQUA + " Default " + Style.YELLOW +
"kit.");
return;
}
}
if (event.getItem().hasItemMeta() && event.getItem().getItemMeta().hasDisplayName()) {
final String displayName = ChatColor.stripColor(event.getItem().getItemMeta().getDisplayName());
if (displayName.startsWith("Kit: ")) {
final String kitName = displayName.replace("Kit: ", "");
for (NamedKit kit : praxiPlayer.getKits(praxiPlayer.getMatch().getLadder())) {
if (kit != null) {
if (ChatColor.stripColor(kit.getName()).equals(kitName)) {
event.setCancelled(true);
player.getInventory().setArmorContents(kit.getArmor());
player.getInventory().setContents(kit.getContents());
player.updateInventory();
player.sendMessage(
Style.YELLOW + "You have been given the " + Style.AQUA + kit.getName() +
Style.YELLOW + " kit.");
return;
}
}
}
}
}
if (event.getItem().getType() == Material.ENDER_PEARL ||
(event.getItem().getType() == Material.POTION && event.getItem().getDurability() >= 16_000)) {
if (praxiPlayer.isInMatch() && praxiPlayer.getMatch().isStarting()) {
event.setCancelled(true);
return;
}
}
if (event.getItem().getType() == Material.ENDER_PEARL && event.getClickedBlock() == null) {
if (!praxiPlayer.isInMatch() || (praxiPlayer.isInMatch() && !praxiPlayer.getMatch().isFighting())) {
event.setCancelled(true);
return;
}
if (praxiPlayer.getMatch().isStarting()) {
event.setCancelled(true);
return;
}
if (!praxiPlayer.getEnderpearlCooldown().hasExpired()) {
final String time =
TimeUtil.millisToSeconds(praxiPlayer.getEnderpearlCooldown().getRemaining());
final String context = "second" + (time.equalsIgnoreCase("1.0") ? "s" : "");
event.setCancelled(true);
player.sendMessage(
Style.YELLOW + "You are on pearl cooldown for " + Style.PINK + time + " " + context +
Style.YELLOW + ".");
} else {
praxiPlayer.setEnderpearlCooldown(new Cooldown(16_000));
}
}
} else {
PlayerHotbar.HotbarItem hotbarItem = PlayerHotbar.fromItemStack(event.getItem());
if (hotbarItem == null) {
return;
}
event.setCancelled(true);
switch (hotbarItem) {
case QUEUE_JOIN_RANKED: {
if (praxiPlayer.isInLobby()) {
new QueueJoinMenu(true).openMenu(event.getPlayer());
}
}
break;
case QUEUE_JOIN_UNRANKED: {
if (praxiPlayer.isInLobby()) {
new QueueJoinMenu(false).openMenu(event.getPlayer());
}
}
break;
case QUEUE_LEAVE: {
if (praxiPlayer.isInQueue()) {
Queue queue = Queue.getByUuid(praxiPlayer.getQueuePlayer().getQueueUuid());
if (queue != null) {
queue.removePlayer(praxiPlayer.getQueuePlayer());
}
}
}
break;
case SPECTATE_STOP: {
CommandHandler.executeCommand(event.getPlayer(), "stopspectate");
}
break;
case PARTY_CREATE: {
CommandHandler.executeCommand(event.getPlayer(), "party create");
}
break;
case PARTY_DISBAND: {
CommandHandler.executeCommand(event.getPlayer(), "party disband");
}
break;
case PARTY_INFORMATION: {
CommandHandler.executeCommand(event.getPlayer(), "party info");
}
break;
case PARTY_LEAVE: {
CommandHandler.executeCommand(event.getPlayer(), "party leave");
}
break;
case PARTY_EVENTS: {
new PartyEventSelectEventMenu().openMenu(player);
}
break;
case OTHER_PARTIES: {
new OtherPartiesMenu().openMenu(event.getPlayer());
}
break;
case KIT_EDITOR: {
if (praxiPlayer.isInLobby() || praxiPlayer.isInQueue()) {
new SelectLadderKitMenu().openMenu(event.getPlayer());
}
}
break;
case SETTINGS: {
CommandHandler.executeCommand(event.getPlayer(), "settings");
}
break;
case REMATCH_REQUEST:
case REMATCH_ACCEPT: {
CommandHandler.executeCommand(event.getPlayer(), "rematch");
}
break;
case EVENT_JOIN: {
CommandHandler.executeCommand(event.getPlayer(), "event join");
}
break;
case EVENT_LEAVE: {
CommandHandler.executeCommand(event.getPlayer(), "event leave");
}
break;
}
}
}
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
event.setDeathMessage(null);
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getEntity().getUniqueId());
if (praxiPlayer.isInMatch()) {
final List<Item> entities = new ArrayList<>();
event.getDrops().forEach(itemStack -> {
entities.add(event.getEntity().getLocation().getWorld()
.dropItemNaturally(event.getEntity().getLocation(), itemStack));
});
event.getDrops().clear();
praxiPlayer.getMatch().getEntities().addAll(entities);
praxiPlayer.getMatch().handleDeath(event.getEntity(), event.getEntity().getKiller(), false);
}
}
@EventHandler
public void onPlayerRespawn(PlayerRespawnEvent event) {
event.setRespawnLocation(event.getPlayer().getLocation());
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (praxiPlayer.isInMatch()) {
praxiPlayer.getMatch().handleRespawn(event.getPlayer());
}
}
@EventHandler(ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent event) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (praxiPlayer.isInMatch()) {
final Match match = praxiPlayer.getMatch();
if (match.getLadder().isBuild() && praxiPlayer.getMatch().isFighting()) {
if (match.getLadder().isSpleef()) {
event.setCancelled(true);
return;
}
final Arena arena = match.getArena();
final int x = (int) event.getBlockPlaced().getLocation().getX();
final int y = (int) event.getBlockPlaced().getLocation().getY();
final int z = (int) event.getBlockPlaced().getLocation().getZ();
if (y > arena.getMaxBuildHeight()) {
event.getPlayer().sendMessage(Style.RED + "You have reached the maximum build height.");
event.setCancelled(true);
return;
}
if (x >= arena.getX1() && x <= arena.getX2() && y >= arena.getY1() && y <= arena.getY2() &&
z >= arena.getZ1() && z <= arena.getZ2()) {
match.getPlacedBlocks().add(event.getBlock().getLocation());
} else {
event.setCancelled(true);
}
} else {
event.setCancelled(true);
}
} else {
if (event.getPlayer().getGameMode() != GameMode.CREATIVE || !event.getPlayer().isOp()) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onBucketEmpty(PlayerBucketEmptyEvent event) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (praxiPlayer.isInMatch()) {
final Match match = praxiPlayer.getMatch();
if (match.getLadder().isBuild() && praxiPlayer.getMatch().isFighting()) {
final Arena arena = match.getArena();
final Block block = event.getBlockClicked().getRelative(event.getBlockFace());
final int x = (int) block.getLocation().getX();
final int y = (int) block.getLocation().getY();
final int z = (int) block.getLocation().getZ();
if (y > arena.getMaxBuildHeight()) {
event.getPlayer().sendMessage(Style.RED + "You have reached the maximum build height.");
event.setCancelled(true);
return;
}
if (x >= arena.getX1() && x <= arena.getX2() && y >= arena.getY1() && y <= arena.getY2() &&
z >= arena.getZ1() && z <= arena.getZ2()) {
match.getPlacedBlocks().add(block.getLocation());
} else {
event.setCancelled(true);
}
} else {
event.setCancelled(true);
}
} else {
if (event.getPlayer().getGameMode() != GameMode.CREATIVE || !event.getPlayer().isOp()) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (praxiPlayer.isInMatch()) {
final Match match = praxiPlayer.getMatch();
if (match.getLadder().isBuild() && praxiPlayer.getMatch().isFighting()) {
if (match.getLadder().isSpleef()) {
if (event.getBlock().getType() == Material.SNOW_BLOCK ||
event.getBlock().getType() == Material.SNOW) {
match.getChangedBlocks().add(event.getBlock().getState());
event.getBlock().setType(Material.AIR);
event.getPlayer().getInventory().addItem(new ItemStack(Material.SNOW_BALL, 4));
event.getPlayer().updateInventory();
} else {
event.setCancelled(true);
}
} else if (!match.getPlacedBlocks().remove(event.getBlock().getLocation())) {
event.setCancelled(true);
}
} else {
event.setCancelled(true);
}
} else {
if (event.getPlayer().getGameMode() != GameMode.CREATIVE || !event.getPlayer().isOp()) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerPickupItem(PlayerPickupItemEvent event) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (praxiPlayer.isInMatch()) {
if (!praxiPlayer.getMatch().getMatchPlayer(event.getPlayer()).isAlive()) {
event.setCancelled(true);
return;
}
Iterator<Entity> entityIterator = praxiPlayer.getMatch().getEntities().iterator();
while (entityIterator.hasNext()) {
Entity entity = entityIterator.next();
if (entity instanceof Item && entity.equals(event.getItem())) {
entityIterator.remove();
return;
}
}
event.setCancelled(true);
} else if (praxiPlayer.isSpectating()) {
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerDropItem(PlayerDropItemEvent event) {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (event.getItemDrop().getItemStack().getType() == Material.BOOK ||
event.getItemDrop().getItemStack().getType() == Material.ENCHANTED_BOOK) {
event.getItemDrop().remove();
return;
}
if (praxiPlayer.isInMatch()) {
if (praxiPlayer.getMatch() != null) {
if (event.getItemDrop().getItemStack().getType() == Material.GLASS_BOTTLE) {
event.getItemDrop().remove();
return;
}
praxiPlayer.getMatch().getEntities().add(event.getItemDrop());
}
} else {
event.setCancelled(true);
}
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (event.getWhoClicked() instanceof Player) {
final Player player = (Player) event.getWhoClicked();
if (event.getClickedInventory() != null && event.getClickedInventory() instanceof CraftingInventory) {
if (player.getGameMode() != GameMode.CREATIVE) {
event.setCancelled(true);
return;
}
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (!praxiPlayer.isInMatch() && player.getGameMode() == GameMode.SURVIVAL) {
final Inventory clicked = event.getClickedInventory();
if (praxiPlayer.getKitEditor().isActive()) {
if (clicked == null) {
event.setCancelled(true);
event.setCursor(null);
player.updateInventory();
} else if (clicked.equals(player.getOpenInventory().getTopInventory())) {
if (event.getCursor().getType() != Material.AIR &&
event.getCurrentItem().getType() == Material.AIR ||
event.getCursor().getType() != Material.AIR &&
event.getCurrentItem().getType() != Material.AIR) {
event.setCancelled(true);
event.setCursor(null);
player.updateInventory();
}
}
} else {
if (clicked != null && clicked.equals(player.getInventory())) {
event.setCancelled(true);
}
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerItemDamage(PlayerItemDamageEvent event) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(event.getPlayer().getUniqueId());
if (praxiPlayer.isInLobby()) {
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,58 @@
package me.joeleoli.praxi.listener;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
public class ProjectileListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onProjectileLaunch(ProjectileLaunchEvent event) {
if (event.getEntity() instanceof ThrownPotion) {
if (event.getEntity().getShooter() instanceof Player) {
final Player shooter = (Player) event.getEntity().getShooter();
final PraxiPlayer shooterData = PraxiPlayer.getByUuid(shooter.getUniqueId());
if (shooterData.isInMatch() && shooterData.getMatch().isFighting()) {
shooterData.getMatch().getMatchPlayer(shooter).incrementPotionsThrown();
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onProjectileHit(ProjectileHitEvent event) {
if (event.getEntity() instanceof Arrow) {
if (event.getEntity().getShooter() instanceof Player) {
final Player shooter = (Player) event.getEntity().getShooter();
final PraxiPlayer shooterData = PraxiPlayer.getByUuid(shooter.getUniqueId());
if (shooterData.isInMatch()) {
shooterData.getMatch().getEntities().add(event.getEntity());
shooterData.getMatch().getMatchPlayer(shooter).handleHit();
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPotionSplash(PotionSplashEvent event) {
if (event.getPotion().getShooter() instanceof Player) {
final Player shooter = (Player) event.getPotion().getShooter();
final PraxiPlayer shooterData = PraxiPlayer.getByUuid(shooter.getUniqueId());
if (shooterData.isInMatch() && shooterData.getMatch().isFighting()) {
if (event.getIntensity(shooter) <= 0.5D) {
shooterData.getMatch().getMatchPlayer(shooter).incrementPotionsMissed();
}
}
}
}
}

View File

@ -0,0 +1,31 @@
package me.joeleoli.praxi.listener;
import me.joeleoli.nucleus.Nucleus;
import me.joeleoli.nucleus.event.PreShutdownEvent;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class ServerListener implements Listener {
@EventHandler
public void onPreShutdown(PreShutdownEvent event) {
Nucleus.getInstance().getServer().getScheduler().runTaskAsynchronously(Nucleus.getInstance(), () -> {
for (Player player : Nucleus.getInstance().getServer().getOnlinePlayers()) {
PraxiPlayer.getByUuid(player.getUniqueId()).save();
}
});
for (Match match : Match.getMatches()) {
match.getPlacedBlocks().forEach(location -> location.getBlock().setType(Material.AIR));
match.getChangedBlocks()
.forEach((blockState) -> blockState.getLocation().getBlock().setType(blockState.getType()));
match.getEntities().forEach(Entity::remove);
}
}
}

View File

@ -0,0 +1,66 @@
package me.joeleoli.praxi.listener;
import org.bukkit.Difficulty;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.weather.WeatherChangeEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldLoadEvent;
public class WorldListener implements Listener {
@EventHandler
public void onChunkUnload(ChunkUnloadEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
event.getWorld().getEntities().clear();
event.getWorld().setDifficulty(Difficulty.HARD);
}
@EventHandler
public void onWeatherChange(WeatherChangeEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onCreatureSpawn(CreatureSpawnEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onBlockIgnite(BlockIgniteEvent event) {
if (event.getCause() == BlockIgniteEvent.IgniteCause.LIGHTNING) {
event.setCancelled(true);
}
}
@EventHandler
public void onLeavesDecay(LeavesDecayEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onHangingBreak(HangingBreakEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onBlockBurn(BlockBurnEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onBlockSpread(BlockSpreadEvent event) {
event.setCancelled(true);
}
}

View File

@ -0,0 +1,722 @@
package me.joeleoli.praxi.match;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.fairfight.FairFight;
import me.joeleoli.nucleus.chat.ChatComponentBuilder;
import me.joeleoli.nucleus.nametag.NameTagHandler;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.nucleus.util.TimeUtil;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.player.PlayerState;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.praxi.player.RematchData;
import me.joeleoli.ragespigot.RageSpigot;
import me.joeleoli.ragespigot.knockback.KnockbackProfile;
import net.md_5.bungee.api.chat.BaseComponent;
import net.minecraft.server.v1_8_R3.EntityLightning;
import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityWeather;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
@Getter
public abstract class Match {
protected static final BaseComponent[] HOVER_TEXT =
new ChatComponentBuilder(Style.GRAY + "Click to view this player's inventory.").create();
@Getter
protected static List<Match> matches = new ArrayList<>();
private UUID matchId = UUID.randomUUID();
@Setter
private MatchState state = MatchState.STARTING;
private UUID queueId;
@Setter
private Ladder ladder;
private Arena arena;
private boolean ranked;
private List<MatchSnapshot> snapshots = new ArrayList<>();
private List<UUID> spectators = new ArrayList<>();
private List<Entity> entities = new ArrayList<>();
private List<Location> placedBlocks = new ArrayList<>();
private List<BlockState> changedBlocks = new ArrayList<>();
@Setter
private long startTimestamp;
public Match(Ladder ladder, Arena arena, boolean ranked) {
this(null, ladder, arena, ranked);
}
public Match(UUID queueId, Ladder ladder, Arena arena, boolean ranked) {
this.queueId = queueId;
this.ladder = ladder;
this.arena = arena;
this.ranked = ranked;
matches.add(this);
}
public boolean isMatchMakingMatch() {
return this.queueId != null;
}
public boolean isStarting() {
return this.state == MatchState.STARTING;
}
public boolean isFighting() {
return this.state == MatchState.FIGHTING;
}
public boolean isEnding() {
return this.state == MatchState.ENDING;
}
public void setupPlayers() {
if (this.isSoloMatch()) {
final MatchPlayer matchPlayerA = this.getMatchPlayerA();
final MatchPlayer matchPlayerB = this.getMatchPlayerB();
matchPlayerA.setAlive(true);
matchPlayerB.setAlive(true);
final Player playerA = matchPlayerA.toPlayer();
final Player playerB = matchPlayerB.toPlayer();
playerA.showPlayer(playerB);
playerB.showPlayer(playerA);
if (this.arena.getSpawn1().getBlock().getType() == Material.AIR) {
playerA.teleport(this.arena.getSpawn1());
} else {
playerA.teleport(this.arena.getSpawn1().add(0, 2, 0));
}
if (this.arena.getSpawn2().getBlock().getType() == Material.AIR) {
playerB.teleport(this.arena.getSpawn2());
} else {
playerB.teleport(this.arena.getSpawn2().add(0, 2, 0));
}
NameTagHandler.addToTeam(playerA, playerB, ChatColor.RED, this.ladder.isBuild());
NameTagHandler.addToTeam(playerB, playerA, ChatColor.RED, this.ladder.isBuild());
PlayerUtil.reset(playerA);
PlayerUtil.reset(playerB);
playerA.setMaximumNoDamageTicks(this.ladder.getHitDelay());
playerB.setMaximumNoDamageTicks(this.ladder.getHitDelay());
if (this.ladder.isSumo()) {
FairFight.getInstance().getPlayerDataManager().getPlayerData(playerA).setAllowTeleport(true);
FairFight.getInstance().getPlayerDataManager().getPlayerData(playerB).setAllowTeleport(true);
PlayerUtil.denyMovement(playerA);
PlayerUtil.denyMovement(playerB);
} else {
for (ItemStack itemStack : PraxiPlayer.getByUuid(playerA.getUniqueId()).getKitItems(this.ladder)) {
playerA.getInventory().addItem(itemStack);
}
for (ItemStack itemStack : PraxiPlayer.getByUuid(playerB.getUniqueId()).getKitItems(this.ladder)) {
playerB.getInventory().addItem(itemStack);
}
}
if (this.ladder.getKbProfile() != null) {
final KnockbackProfile profile =
RageSpigot.INSTANCE.getConfig().getKbProfileByName(this.ladder.getKbProfile());
if (profile != null) {
playerA.setKnockbackProfile(profile);
playerB.setKnockbackProfile(profile);
}
}
} else if (this.isTeamMatch()) {
final MatchTeam teamA = this.getTeamA();
final MatchTeam teamB = this.getTeamB();
for (MatchPlayer matchPlayer : teamA.getTeamPlayers()) {
if (!matchPlayer.isDisconnected()) {
matchPlayer.setAlive(true);
}
final Player player = matchPlayer.toPlayer();
if (player == null || !player.isOnline()) {
continue;
}
player.teleport(this.arena.getSpawn1());
for (Player member : teamA.getPlayers()) {
NameTagHandler.addToTeam(player, member, ChatColor.GREEN, this.ladder.isBuild());
}
for (Player enemy : teamB.getPlayers()) {
NameTagHandler.addToTeam(player, enemy, ChatColor.RED, this.ladder.isBuild());
}
}
for (MatchPlayer matchPlayer : teamB.getTeamPlayers()) {
if (!matchPlayer.isDisconnected()) {
matchPlayer.setAlive(true);
}
final Player player = matchPlayer.toPlayer();
if (player == null || !player.isOnline()) {
continue;
}
player.teleport(this.arena.getSpawn2());
for (Player member : teamB.getPlayers()) {
NameTagHandler.addToTeam(player, member, ChatColor.GREEN, this.ladder.isBuild());
}
for (Player enemy : teamA.getPlayers()) {
NameTagHandler.addToTeam(player, enemy, ChatColor.RED, this.ladder.isBuild());
}
}
final List<Player> players = this.getPlayers();
for (Player first : players) {
PlayerUtil.reset(first);
first.setMaximumNoDamageTicks(this.ladder.getHitDelay());
if (this.ladder.isSumo()) {
FairFight.getInstance().getPlayerDataManager().getPlayerData(first).setAllowTeleport(true);
PlayerUtil.denyMovement(first);
} else {
for (ItemStack itemStack : PraxiPlayer.getByUuid(first.getUniqueId()).getKitItems(this.ladder)) {
first.getInventory().addItem(itemStack);
}
}
if (this.ladder.getKbProfile() != null) {
final KnockbackProfile profile =
RageSpigot.INSTANCE.getConfig().getKbProfileByName(this.ladder.getKbProfile());
if (profile != null) {
first.setKnockbackProfile(profile);
}
}
for (Player second : players) {
if (first.getUniqueId().equals(second.getUniqueId())) {
continue;
}
first.showPlayer(second);
second.showPlayer(first);
}
}
}
}
public void handleStart() {
this.setupPlayers();
this.state = MatchState.STARTING;
this.startTimestamp = -1;
this.arena.setActive(true);
this.onStart();
this.getPlayers().forEach(player -> {
player.sendMessage(Style.YELLOW + "You are playing on arena " + Style.PINK + this.arena.getName() + Style.YELLOW + ".");
});
TaskUtil.runTimer(new MatchStartTask(this), 20L, 20L);
}
private void handleEnd() {
this.state = MatchState.ENDING;
this.onEnd();
if (this.isSoloMatch()) {
final Player playerA = this.getPlayerA();
final Player playerB = this.getPlayerB();
playerA.hidePlayer(playerB);
playerB.hidePlayer(playerA);
for (MatchPlayer matchPlayer : new MatchPlayer[]{ this.getMatchPlayerA(), this.getMatchPlayerB() }) {
if (matchPlayer.isAlive()) {
final Player player = matchPlayer.toPlayer();
if (player != null) {
player.setFireTicks(0);
player.updateInventory();
if (matchPlayer.isAlive()) {
MatchSnapshot snapshot = new MatchSnapshot(matchPlayer);
snapshot.setSwitchTo(this.getOpponentMatchPlayer(player));
this.snapshots.add(snapshot);
}
}
}
}
} else if (this.isTeamMatch()) {
for (MatchPlayer firstMatchPlayer : this.getMatchPlayers()) {
if (firstMatchPlayer.isDisconnected()) {
continue;
}
final Player player = firstMatchPlayer.toPlayer();
if (player != null) {
for (MatchPlayer secondMatchPlayer : this.getMatchPlayers()) {
if (secondMatchPlayer.isDisconnected()) {
continue;
}
if (secondMatchPlayer.getUuid().equals(player.getUniqueId())) {
continue;
}
final Player secondPlayer = secondMatchPlayer.toPlayer();
if (secondPlayer == null) {
continue;
}
player.hidePlayer(secondPlayer);
}
player.setFireTicks(0);
player.updateInventory();
if (firstMatchPlayer.isAlive()) {
this.snapshots.add(new MatchSnapshot(firstMatchPlayer));
}
}
}
}
this.getSpectators().forEach(this::removeSpectator);
this.entities.forEach(Entity::remove);
this.snapshots.forEach(matchInventory -> {
matchInventory.setCreated(System.currentTimeMillis());
MatchSnapshot.getCache().put(matchInventory.getMatchPlayer().getUuid(), matchInventory);
});
new MatchResetTask(this).runTask(Praxi.getInstance());
TaskUtil.runLater(() -> {
if (this.isSoloMatch()) {
final UUID rematchKey = UUID.randomUUID();
final Player playerA = this.getPlayerA();
final Player playerB = this.getPlayerB();
if (playerA != null && playerB != null) {
NameTagHandler.removeFromTeams(playerA, playerB);
NameTagHandler.removeFromTeams(playerB, playerA);
NameTagHandler.removeHealthDisplay(playerA);
NameTagHandler.removeHealthDisplay(playerB);
}
for (MatchPlayer matchPlayer : new MatchPlayer[]{ this.getMatchPlayerA(), this.getMatchPlayerB() }) {
final Player player = matchPlayer.toPlayer();
final Player opponent = this.getOpponentPlayer(player);
if (player != null) {
player.setKnockbackProfile(null);
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (opponent != null) {
praxiPlayer.setRematchData(
new RematchData(rematchKey, player.getUniqueId(), opponent.getUniqueId(),
this.getLadder(), this.getArena()
));
}
praxiPlayer.setState(PlayerState.IN_LOBBY);
praxiPlayer.setMatch(null);
praxiPlayer.loadHotbar();
PlayerUtil.spawn(player);
}
}
} else if (this.isTeamMatch()) {
this.getPlayers().forEach(player -> {
NameTagHandler.removeHealthDisplay(player);
this.getPlayers().forEach(otherPlayer -> NameTagHandler.removeFromTeams(player, otherPlayer));
});
for (MatchPlayer matchPlayer : this.getMatchPlayers()) {
if (matchPlayer.isDisconnected()) {
continue;
}
final Player player = matchPlayer.toPlayer();
if (player != null) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setState(PlayerState.IN_LOBBY);
praxiPlayer.setMatch(null);
praxiPlayer.loadHotbar();
player.setKnockbackProfile(null);
PlayerUtil.spawn(player);
}
}
}
}, 20L * 3);
matches.remove(this);
}
public void handleRespawn(Player player) {
player.spigot().respawn();
player.setVelocity(new Vector());
this.onRespawn(player);
}
public void handleDeath(Player deadPlayer, Player killerPlayer, boolean disconnected) {
final MatchPlayer matchPlayer = this.getMatchPlayer(deadPlayer);
if (!matchPlayer.isAlive()) {
return;
}
matchPlayer.setAlive(false);
matchPlayer.setDisconnected(disconnected);
final List<Player> involvedPlayers = new ArrayList<>();
if (this.isSoloMatch()) {
involvedPlayers.add(this.getPlayerA());
involvedPlayers.add(this.getPlayerB());
} else {
involvedPlayers.addAll(this.getPlayers());
}
involvedPlayers.addAll(this.getSpectators());
EntityLightning is =
new EntityLightning(((CraftWorld) deadPlayer.getWorld()).getHandle(), deadPlayer.getLocation().getX(),
deadPlayer.getLocation().getY(), deadPlayer.getLocation().getZ()
);
PacketPlayOutSpawnEntityWeather lightningPacket = new PacketPlayOutSpawnEntityWeather(is);
involvedPlayers.forEach(other -> {
if (other != null) {
other.playSound(deadPlayer.getLocation(), Sound.AMBIENCE_THUNDER, 1.0F, 1.0F);
((CraftPlayer) other).getHandle().playerConnection.sendPacket(lightningPacket);
}
});
for (Player involved : involvedPlayers) {
String deadName = Style.RED + deadPlayer.getName();
if (this.isSoloMatch()) {
// Todo: fix NPE here, idk where but it says the line right below...
// DEBUG FOR NOW:
if (deadPlayer == null) {
System.out.println("DEBUG: DEAD PLAYER NULL");
continue;
}
if (involved == null) {
System.out.println("DEBUG: INVOLVED PLAYER NULL");
continue;
}
if (deadPlayer.getUniqueId().equals(involved.getUniqueId())) {
deadName = Style.GREEN + deadPlayer.getName();
}
} else {
final MatchTeam matchTeam = this.getTeam(involved);
if (matchTeam != null && matchTeam.containsPlayer(deadPlayer)) {
deadName = Style.GREEN + deadPlayer.getName();
}
}
if (matchPlayer.isDisconnected()) {
involved.sendMessage(deadName + Style.YELLOW + " has disconnected.");
continue;
}
String killerName = null;
if (killerPlayer != null) {
killerName = Style.RED + killerPlayer.getName();
if (this.isSoloMatch()) {
if (killerPlayer.getUniqueId().equals(involved.getUniqueId())) {
killerName = Style.GREEN + killerPlayer.getName();
}
} else {
final MatchTeam matchTeam = this.getTeam(involved);
if (matchTeam != null && matchTeam.containsPlayer(killerPlayer)) {
killerName = Style.GREEN + killerPlayer.getName();
}
}
}
if (killerName == null) {
involved.sendMessage(deadName + Style.YELLOW + " has died.");
} else {
involved.sendMessage(deadName + Style.YELLOW + " was killed by " + killerName + Style.YELLOW + ".");
}
}
this.onDeath(deadPlayer, killerPlayer);
if (this.canEnd()) {
this.handleEnd();
}
}
public String getDuration() {
if (this.isStarting()) {
return "00:00";
} else if (this.isEnding()) {
return "Ending";
} else {
return TimeUtil.millisToTimer(this.getElapsedDuration());
}
}
public long getElapsedDuration() {
return System.currentTimeMillis() - this.startTimestamp;
}
public void broadcastMessage(String message) {
this.getPlayers().forEach(player -> player.sendMessage(message));
this.getSpectators().forEach(player -> player.sendMessage(message));
}
public void broadcastSound(Sound sound) {
this.getPlayers().forEach(player -> player.playSound(player.getLocation(), sound, 1.0F, 1.0F));
this.getSpectators().forEach(player -> player.playSound(player.getLocation(), sound, 1.0F, 1.0F));
}
public List<UUID> getInvolvedPlayers() {
List<UUID> toReturn = new ArrayList<>();
toReturn.addAll(this.spectators);
if (this.isSoloMatch()) {
toReturn.add(this.getMatchPlayerA().getUuid());
toReturn.add(this.getMatchPlayerB().getUuid());
} else if (this.isTeamMatch()) {
this.getMatchPlayers().forEach(matchPlayer -> toReturn.add(matchPlayer.getUuid()));
}
return toReturn;
}
protected List<Player> getSpectators() {
return PlayerUtil.convertUUIDListToPlayerList(this.spectators);
}
public void addSpectator(Player player, Player target) {
this.spectators.add(player.getUniqueId());
if (this.isSoloMatch()) {
final Player playerA = this.getPlayerA();
final Player playerB = this.getPlayerB();
if (playerA != null) {
player.showPlayer(playerA);
NameTagHandler.addToTeam(player, playerA, ChatColor.AQUA, this.ladder.isBuild());
}
if (playerB != null) {
player.showPlayer(playerB);
NameTagHandler.addToTeam(player, playerB, ChatColor.LIGHT_PURPLE, this.ladder.isBuild());
}
} else if (this.isTeamMatch()) {
this.getTeamA().getPlayers().forEach(teamPlayer -> {
player.showPlayer(teamPlayer);
teamPlayer.hidePlayer(player);
NameTagHandler.addToTeam(player, teamPlayer, ChatColor.AQUA, this.ladder.isBuild());
});
this.getTeamB().getPlayers().forEach(teamPlayer -> {
player.showPlayer(teamPlayer);
teamPlayer.hidePlayer(player);
NameTagHandler.addToTeam(player, teamPlayer, ChatColor.LIGHT_PURPLE, this.ladder.isBuild());
});
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setMatch(this);
praxiPlayer.setState(PlayerState.SPECTATE_MATCH);
praxiPlayer.loadHotbar();
player.setAllowFlight(true);
player.setFlying(true);
player.updateInventory();
player.teleport(target.getLocation().clone().add(0, 2, 0));
player.sendMessage(Style.YELLOW + "You are spectating " + Style.PINK + target.getName() + Style.YELLOW + ".");
if (this.isSoloMatch()) {
for (Player matchPlayer : new Player[]{ this.getPlayerA(), this.getPlayerB() }) {
if (!player.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(Style.PINK + player.getName() + Style.YELLOW + " is now spectating.");
} else if (matchPlayer.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(Style.GRAY + "[Silent] " + Style.PINK + player.getName() + Style.YELLOW +
" is now spectating.");
}
}
} else if (this.isTeamMatch()) {
for (Player matchPlayer : this.getPlayers()) {
if (!player.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(Style.PINK + player.getName() + Style.YELLOW + " is now spectating.");
} else if (matchPlayer.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(Style.GRAY + "[Silent] " + Style.PINK + player.getName() + Style.YELLOW +
" is now spectating.");
}
}
}
}
public void removeSpectator(Player player) {
this.spectators.remove(player.getUniqueId());
if (this.isSoloMatch()) {
player.hidePlayer(this.getPlayerA());
player.hidePlayer(this.getPlayerB());
NameTagHandler.removeFromTeams(player, this.getPlayerA());
NameTagHandler.removeFromTeams(player, this.getPlayerB());
NameTagHandler.removeHealthDisplay(player);
} else if (this.isTeamMatch()) {
this.getPlayers().forEach(other -> {
player.hidePlayer(other);
other.hidePlayer(player);
NameTagHandler.removeFromTeams(player, other);
});
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (this.state != MatchState.ENDING) {
final String toSend = Style.PINK + player.getName() + Style.YELLOW + " is no longer spectating your match.";
if (this.isSoloMatch()) {
for (Player matchPlayer : new Player[]{ this.getPlayerA(), this.getPlayerB() }) {
if (!player.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(toSend);
} else if (matchPlayer.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(Style.GRAY + "[Silent] " + toSend);
}
}
} else if (this.isTeamMatch()) {
for (Player matchPlayer : this.getPlayers()) {
if (!player.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(toSend);
} else if (matchPlayer.hasPermission("praxi.spectate.hidden")) {
matchPlayer.sendMessage(Style.GRAY + "[Silent] " + toSend);
}
}
}
}
praxiPlayer.setState(PlayerState.IN_LOBBY);
praxiPlayer.setMatch(null);
praxiPlayer.loadHotbar();
PlayerUtil.spawn(player);
}
public abstract boolean isDuel();
public abstract boolean isSoloMatch();
public abstract boolean isTeamMatch();
public abstract void onStart();
public abstract void onEnd();
public abstract void onDeath(Player player, Player killer);
public abstract void onRespawn(Player player);
public abstract boolean canEnd();
public abstract Player getWinningPlayer();
public abstract MatchTeam getWinningTeam();
public abstract MatchPlayer getMatchPlayerA();
public abstract MatchPlayer getMatchPlayerB();
public abstract List<MatchPlayer> getMatchPlayers();
public abstract Player getPlayerA();
public abstract Player getPlayerB();
public abstract List<Player> getPlayers();
public abstract MatchTeam getTeamA();
public abstract MatchTeam getTeamB();
public abstract MatchTeam getTeam(MatchPlayer matchPlayer);
public abstract MatchTeam getTeam(Player player);
public abstract MatchPlayer getMatchPlayer(Player player);
public abstract int getOpponentsLeft(Player player);
public abstract MatchTeam getOpponentTeam(MatchTeam matchTeam);
public abstract MatchTeam getOpponentTeam(Player player);
public abstract MatchPlayer getOpponentMatchPlayer(Player player);
public abstract Player getOpponentPlayer(Player player);
public abstract int getTotalRoundWins();
public abstract int getRoundWins(MatchPlayer matchPlayer);
public abstract int getRoundWins(MatchTeam matchTeam);
public abstract int getRoundsNeeded(MatchPlayer matchPlayer);
public abstract int getRoundsNeeded(MatchTeam matchTeam);
}

View File

@ -0,0 +1,51 @@
package me.joeleoli.praxi.match;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.team.TeamPlayer;
import org.bukkit.entity.Player;
@Getter
@Setter
public class MatchPlayer extends TeamPlayer {
private boolean alive = true;
private boolean disconnected;
private int elo, potionsThrown, potionsMissed, hits, combo, longestCombo;
public MatchPlayer(Player player) {
super(player.getUniqueId(), player.getName());
}
public double getPotionAccuracy() {
if (this.potionsMissed == 0) {
return 100.0;
} else if (this.potionsThrown == this.potionsMissed) {
return 50.0;
}
return Math.round(100.0D - (((double) this.potionsMissed / (double) this.potionsThrown) * 100.0D));
}
public void incrementPotionsThrown() {
this.potionsThrown++;
}
public void incrementPotionsMissed() {
this.potionsMissed++;
}
public void handleHit() {
this.hits++;
this.combo++;
if (this.combo > this.longestCombo) {
this.longestCombo = this.combo;
}
}
public void resetCombo() {
this.combo = 0;
}
}

View File

@ -0,0 +1,82 @@
package me.joeleoli.praxi.match;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import lombok.AllArgsConstructor;
import org.bukkit.Location;
import org.bukkit.block.BlockState;
import org.bukkit.scheduler.BukkitRunnable;
@AllArgsConstructor
public class MatchResetTask extends BukkitRunnable {
private Match match;
@Override
public void run() {
if (this.match.getLadder().isBuild() && this.match.getPlacedBlocks().size() > 0) {
TaskManager.IMP.async(() -> {
EditSession editSession = new EditSessionBuilder(this.match.getArena().getSpawn1().getWorld().getName())
.fastmode(true)
.allowedRegionsEverywhere()
.autoQueue(false)
.limitUnlimited()
.build();
for (Location location : this.match.getPlacedBlocks()) {
try {
editSession.setBlock(
new Vector((double) location.getBlockX(), (double) location.getBlockY(),
location.getZ()
), new BaseBlock(0));
} catch (Exception ex) {
}
}
editSession.flushQueue();
TaskManager.IMP.task(() -> {
this.match.getPlacedBlocks().clear();
this.match.getArena().setActive(false);
this.cancel();
});
});
} else if (this.match.getLadder().isBuild() && this.match.getChangedBlocks().size() > 0) {
TaskManager.IMP.async(() -> {
EditSession editSession = new EditSessionBuilder(this.match.getArena().getSpawn1().getWorld().getName())
.fastmode(true)
.allowedRegionsEverywhere()
.autoQueue(false)
.limitUnlimited()
.build();
for (BlockState blockState : this.match.getChangedBlocks()) {
try {
editSession.setBlock(
new Vector(blockState.getLocation().getBlockX(), blockState.getLocation().getBlockY(),
blockState.getLocation().getZ()
), new BaseBlock(blockState.getTypeId(), blockState.getRawData()));
} catch (Exception ex) {
}
}
editSession.flushQueue();
TaskManager.IMP.task(() -> {
if (this.match.getLadder().isBuild()) {
this.match.getChangedBlocks().clear();
this.match.getArena().setActive(false);
}
this.cancel();
});
});
} else {
this.cancel();
}
}
}

View File

@ -0,0 +1,77 @@
package me.joeleoli.praxi.match;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import lombok.Data;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
@Data
public class MatchSnapshot {
@Getter
private static Map<UUID, MatchSnapshot> cache = new HashMap<>();
private MatchPlayer matchPlayer;
private MatchPlayer switchTo;
private int health;
private int hunger;
private ItemStack[] armor;
private ItemStack[] contents;
private Collection<PotionEffect> effects;
private long created = System.currentTimeMillis();
public MatchSnapshot(MatchPlayer matchPlayer) {
this(matchPlayer, null);
}
public MatchSnapshot(MatchPlayer matchPlayer, MatchPlayer switchTo) {
this.matchPlayer = matchPlayer;
final Player player = this.matchPlayer.toPlayer();
this.health = player.getHealth() == 0 ? 0 : (int) Math.round(player.getHealth() / 2);
this.hunger = player.getFoodLevel();
this.armor = player.getInventory().getArmorContents();
this.contents = player.getInventory().getContents();
this.effects = player.getActivePotionEffects();
this.switchTo = switchTo;
}
public static MatchSnapshot getByUuid(UUID uuid) {
return cache.get(uuid);
}
public static MatchSnapshot getByName(String name) {
for (MatchSnapshot details : cache.values()) {
if (details.getMatchPlayer().getName().equalsIgnoreCase(name)) {
return details;
}
}
return null;
}
public int getRemainingPotions() {
int amount = 0;
for (ItemStack itemStack : this.contents) {
if (itemStack != null && itemStack.getType() == Material.POTION && itemStack.getDurability() == 16421) {
amount++;
}
}
return amount;
}
public boolean shouldDisplayRemainingPotions() {
return this.getRemainingPotions() > 0 || this.matchPlayer.getPotionsThrown() > 0 ||
this.matchPlayer.getPotionsMissed() > 0;
}
}

View File

@ -0,0 +1,90 @@
package me.joeleoli.praxi.match;
import me.joeleoli.fairfight.FairFight;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class MatchStartTask extends BukkitRunnable {
private Match match;
private int ticks;
public MatchStartTask(Match match) {
this.match = match;
}
@Override
public void run() {
int seconds = 5 - this.ticks;
if (this.match.isEnding()) {
this.cancel();
return;
}
if (this.match.getLadder().isSumo()) {
if (seconds == 2) {
if (this.match.isSoloMatch()) {
final Player playerA = this.match.getPlayerA();
final Player playerB = this.match.getPlayerB();
if (playerA != null) {
FairFight.getInstance().getPlayerDataManager().getPlayerData(playerA).setAllowTeleport(false);
PlayerUtil.allowMovement(playerA);
}
if (playerB != null) {
FairFight.getInstance().getPlayerDataManager().getPlayerData(playerB).setAllowTeleport(false);
PlayerUtil.allowMovement(playerB);
}
} else if (this.match.isTeamMatch()) {
this.match.getMatchPlayers().forEach(matchPlayer -> {
if (!matchPlayer.isDisconnected()) {
final Player player = matchPlayer.toPlayer();
if (player != null) {
FairFight.getInstance().getPlayerDataManager().getPlayerData(player)
.setAllowTeleport(false);
PlayerUtil.allowMovement(player);
}
}
});
}
this.match.setState(MatchState.FIGHTING);
this.match.setStartTimestamp(System.currentTimeMillis());
this.match.broadcastMessage(Style.YELLOW + "The round has started!");
this.match.broadcastSound(Sound.NOTE_BASS);
this.cancel();
return;
}
this.match.broadcastMessage(
Style.YELLOW + "The round will start in " + Style.PINK + (seconds - 2) + " second" +
(seconds - 2 == 1 ? "" : "s") + Style.YELLOW + "...");
this.match.broadcastSound(Sound.NOTE_PLING);
} else {
if (seconds == 0) {
this.match.setState(MatchState.FIGHTING);
this.match.setStartTimestamp(System.currentTimeMillis());
this.match.broadcastMessage(Style.YELLOW + "The match has started!");
this.match.broadcastSound(Sound.NOTE_BASS);
this.cancel();
return;
}
this.match.broadcastMessage(Style.YELLOW + "The match will start in " + Style.PINK + seconds + " second" +
(seconds == 1 ? "" : "s") + Style.YELLOW + "...");
this.match.broadcastSound(Sound.NOTE_PLING);
}
this.ticks++;
}
}

View File

@ -0,0 +1,9 @@
package me.joeleoli.praxi.match;
public enum MatchState {
STARTING,
FIGHTING,
ENDING
}

View File

@ -0,0 +1,23 @@
package me.joeleoli.praxi.match;
import me.joeleoli.nucleus.team.Team;
public class MatchTeam extends Team<MatchPlayer> {
public MatchTeam(MatchPlayer matchPlayer) {
super(matchPlayer);
}
public int getDisconnectedCount() {
int disconnected = 0;
for (MatchPlayer matchPlayer : this.getTeamPlayers()) {
if (matchPlayer.isDisconnected()) {
disconnected++;
}
}
return disconnected;
}
}

View File

@ -0,0 +1,210 @@
package me.joeleoli.praxi.match.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.command.CommandHandler;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.menu.buttons.DisplayButton;
import me.joeleoli.nucleus.util.BukkitUtil;
import me.joeleoli.nucleus.util.InventoryUtil;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TimeUtil;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.match.MatchSnapshot;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
@AllArgsConstructor
public class MatchDetailsMenu extends Menu {
private MatchSnapshot snapshot;
@Override
public String getTitle(Player player) {
return ChatColor.YELLOW + "Snapshot of " + this.snapshot.getMatchPlayer().getName();
}
@Override
public Map<Integer, Button> getButtons(Player player) {
final Map<Integer, Button> buttons = new HashMap<>();
final ItemStack[] fixedContents = InventoryUtil.fixInventoryOrder(this.snapshot.getContents());
for (int i = 0; i < fixedContents.length; i++) {
final ItemStack itemStack = fixedContents[i];
if (itemStack == null || itemStack.getType() == Material.AIR) {
continue;
}
buttons.put(i, new DisplayButton(itemStack, true));
}
for (int i = 0; i < this.snapshot.getArmor().length; i++) {
ItemStack itemStack = this.snapshot.getArmor()[i];
if (itemStack != null && itemStack.getType() != Material.AIR) {
buttons.put(39 - i, new DisplayButton(itemStack, true));
}
}
int pos = 45;
buttons.put(pos++, new HealthButton(this.snapshot.getHealth()));
buttons.put(pos++, new HungerButton(this.snapshot.getHunger()));
buttons.put(pos++, new EffectsButton(this.snapshot.getEffects()));
if (this.snapshot.shouldDisplayRemainingPotions()) {
buttons.put(
pos++,
new PotionsButton(this.snapshot.getMatchPlayer().getName(), this.snapshot.getRemainingPotions())
);
}
buttons.put(pos, new StatisticsButton(this.snapshot.getMatchPlayer()));
if (this.snapshot.getSwitchTo() != null) {
buttons.put(53, new SwitchInventoryButton(this.snapshot.getSwitchTo()));
}
return buttons;
}
@Override
public void onOpen(Player player) {
player.sendMessage(Style.YELLOW + "You are viewing " + Style.PINK + this.snapshot.getMatchPlayer().getName() +
Style.YELLOW + "'s inventory.");
}
@AllArgsConstructor
private class SwitchInventoryButton extends Button {
private MatchPlayer switchTo;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.LEVER)
.name(Style.YELLOW + Style.BOLD + "Opponent's Inventory")
.lore(Style.YELLOW + "Switch to " + Style.PINK + this.switchTo.getName() + Style.YELLOW +
"'s inventory")
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hb) {
CommandHandler.executeCommand(player, "viewinv " + this.switchTo.getUuid().toString());
}
}
@AllArgsConstructor
private class HealthButton extends Button {
private int health;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.MELON)
.name(Style.YELLOW + Style.BOLD + "Health: " + Style.PINK + this.health + "/10 " + Style.UNICODE_HEART)
.amount(this.health == 0 ? 1 : this.health)
.build();
}
}
@AllArgsConstructor
private class HungerButton extends Button {
private int hunger;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.COOKED_BEEF)
.name(Style.YELLOW + Style.BOLD + "Hunger: " + Style.PINK + this.hunger + "/20")
.amount(this.hunger == 0 ? 1 : this.hunger)
.build();
}
}
@AllArgsConstructor
private class EffectsButton extends Button {
private Collection<PotionEffect> effects;
@Override
public ItemStack getButtonItem(Player player) {
final ItemBuilder builder = new ItemBuilder(Material.POTION)
.name(Style.YELLOW + Style.BOLD + "Potion Effects");
if (this.effects.isEmpty()) {
builder.lore(Style.PINK + "No potion effects");
} else {
final List<String> lore = new ArrayList<>();
this.effects.forEach(effect -> {
final String name = BukkitUtil.getName(effect.getType()) + " " + (effect.getAmplifier() + 1);
final String duration = " (" + TimeUtil.millisToTimer((effect.getDuration() / 20) * 1000) + ")";
lore.add(Style.PINK + name + Style.GRAY + duration);
});
builder.lore(lore);
}
return builder.build();
}
}
@AllArgsConstructor
private class PotionsButton extends Button {
private String name;
private int potions;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.POTION)
.durability(16421)
.amount(this.potions == 0 ? 1 : this.potions)
.name(Style.YELLOW + Style.BOLD + "Potions")
.lore(Style.PINK + this.name + Style.YELLOW + " had " + Style.PINK + this.potions + Style.YELLOW +
" potion" + (this.potions == 1 ? "" : "s") + " left.")
.build();
}
}
@AllArgsConstructor
private class StatisticsButton extends Button {
private MatchPlayer matchPlayer;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(Material.PAPER)
.name(Style.YELLOW + Style.BOLD + "Statistics")
.lore(Arrays.asList(
Style.PINK + "Hits: " + Style.RESET + this.matchPlayer.getHits(),
Style.PINK + "Longest Combo: " + Style.RESET + this.matchPlayer.getLongestCombo(),
Style.PINK + "Potions Thrown: " + Style.RESET + this.matchPlayer.getPotionsThrown(),
Style.PINK + "Potions Missed: " + Style.RESET + this.matchPlayer.getPotionsMissed(),
Style.PINK + "Potion Accuracy: " + Style.RESET + this.matchPlayer.getPotionAccuracy()
))
.build();
}
}
}

View File

@ -0,0 +1,375 @@
package me.joeleoli.praxi.match.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import lombok.Getter;
import me.joeleoli.nucleus.chat.ChatComponentBuilder;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.elo.EloUtil;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.match.MatchSnapshot;
import me.joeleoli.praxi.match.MatchState;
import me.joeleoli.praxi.match.MatchTeam;
import me.joeleoli.praxi.player.PlayerState;
import me.joeleoli.praxi.player.PraxiPlayer;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import org.bukkit.entity.Player;
@Getter
public class SoloMatch extends Match {
private MatchPlayer playerA;
private MatchPlayer playerB;
private int playerARoundWins = 0;
private int playerBRoundWins = 0;
private boolean duel;
public SoloMatch(MatchPlayer playerA, MatchPlayer playerB, Ladder ladder, Arena arena, boolean ranked,
boolean duel) {
this(null, playerA, playerB, ladder, arena, ranked, duel);
this.duel = duel;
}
public SoloMatch(UUID queueId, MatchPlayer playerA, MatchPlayer playerB, Ladder ladder, Arena arena, boolean ranked,
boolean duel) {
super(queueId, ladder, arena, ranked);
this.playerA = playerA;
this.playerB = playerB;
this.duel = duel;
}
@Override
public boolean isSoloMatch() {
return true;
}
@Override
public boolean isTeamMatch() {
return false;
}
@Override
public void onStart() {
if (this.getTotalRoundWins() == 0) {
for (MatchPlayer matchPlayer : new MatchPlayer[]{ this.playerA, this.playerB }) {
final Player player = matchPlayer.toPlayer();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setState(PlayerState.IN_MATCH);
praxiPlayer.setMatch(this);
}
}
}
@Override
public void onEnd() {
final Player winningPlayer = this.getWinningPlayer();
final Player losingPlayer = this.getOpponentPlayer(winningPlayer);
final MatchPlayer winningMatchPlayer = this.getMatchPlayer(winningPlayer);
final MatchPlayer losingMatchPlayer = this.getMatchPlayer(losingPlayer);
final HoverEvent winnerHoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, HOVER_TEXT);
final ClickEvent winnerClickEvent =
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewinv " + winningPlayer.getUniqueId().toString());
final HoverEvent loserHoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, HOVER_TEXT);
final ClickEvent loserClickEvent =
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewinv " + losingPlayer.getUniqueId().toString());
final ChatComponentBuilder inventoriesBuilder = new ChatComponentBuilder("");
inventoriesBuilder
.append("Winner: ")
.color(ChatColor.GREEN)
.append(winningPlayer.getName())
.color(ChatColor.YELLOW);
inventoriesBuilder
.setCurrentHoverEvent(winnerHoverEvent)
.setCurrentClickEvent(winnerClickEvent)
.append(" - ")
.color(ChatColor.GRAY)
.append("Loser: ")
.color(ChatColor.RED)
.append(losingPlayer.getName())
.color(ChatColor.YELLOW);
inventoriesBuilder
.setCurrentHoverEvent(loserHoverEvent)
.setCurrentClickEvent(loserClickEvent);
final List<BaseComponent[]> components = new ArrayList<>();
components.add(new ChatComponentBuilder("").parse("&dPost-Match Inventories &7(click name to view)").create());
components.add(inventoriesBuilder.create());
if (this.isRanked()) {
final int oldWinnerElo = winningMatchPlayer.getElo();
final int oldLoserElo = losingMatchPlayer.getElo();
final int newWinnerElo = EloUtil.getNewRating(oldWinnerElo, oldLoserElo, true);
final int newLoserElo = EloUtil.getNewRating(oldLoserElo, oldWinnerElo, false);
final PraxiPlayer winningPraxiPlayer = PraxiPlayer.getByUuid(winningPlayer.getUniqueId());
final PraxiPlayer losingPraxiPlayer = PraxiPlayer.getByUuid(losingPlayer.getUniqueId());
if (winningPraxiPlayer.isLoaded()) {
winningPraxiPlayer.getStatistics().getLadderStatistics(this.getLadder()).setElo(newWinnerElo);
}
if (losingPraxiPlayer.isLoaded()) {
losingPraxiPlayer.getStatistics().getLadderStatistics(this.getLadder()).setElo(newLoserElo);
}
int winnerEloChange = newWinnerElo - oldWinnerElo;
int loserEloChange = oldLoserElo - newLoserElo;
components.add(new ChatComponentBuilder("")
.parse("&dELO Changes: &a" + winningPlayer.getName() + " +" + winnerEloChange + " (" +
newWinnerElo + ") &c" + losingPlayer.getName() + " -" + loserEloChange + " (" + newLoserElo +
")")
.create());
}
components.add(0, new ChatComponentBuilder("").parse(Style.getBorderLine()).create());
components.add(new ChatComponentBuilder("").parse(Style.getBorderLine()).create());
for (Player player : new Player[]{ winningPlayer, losingPlayer }) {
components.forEach(player::sendMessage);
}
for (Player player : this.getSpectators()) {
components.forEach(player::sendMessage);
}
}
@Override
public boolean canEnd() {
if (this.getLadder().isSumo()) {
return this.playerA.isDisconnected()
|| this.playerB.isDisconnected()
|| (this.isRanked() ? (this.playerARoundWins == 3 || this.playerBRoundWins == 3)
: (this.playerARoundWins == 1 || this.playerBRoundWins == 1));
} else {
return !this.playerA.isAlive() || !this.playerB.isAlive();
}
}
@Override
public Player getWinningPlayer() {
if (this.playerA.isDisconnected() || !this.playerA.isAlive()) {
return this.playerB.toPlayer();
} else {
return this.playerA.toPlayer();
}
}
@Override
public MatchTeam getWinningTeam() {
throw new UnsupportedOperationException("Cannot get winning team from a SoloMatch");
}
@Override
public MatchPlayer getMatchPlayerA() {
return this.playerA;
}
@Override
public MatchPlayer getMatchPlayerB() {
return this.playerB;
}
@Override
public List<MatchPlayer> getMatchPlayers() {
throw new UnsupportedOperationException("Cannot get match players from a SoloMatch");
}
@Override
public Player getPlayerA() {
return this.playerA.toPlayer();
}
@Override
public Player getPlayerB() {
return this.playerB.toPlayer();
}
@Override
public List<Player> getPlayers() {
final List<Player> players = new ArrayList<>();
final Player playerA = this.playerA.toPlayer();
final Player playerB = this.playerB.toPlayer();
if (playerA != null) {
players.add(playerA);
}
if (playerB != null) {
players.add(playerB);
}
return players;
}
@Override
public MatchTeam getTeamA() {
throw new UnsupportedOperationException("Cannot get team from a SoloMatch");
}
@Override
public MatchTeam getTeamB() {
throw new UnsupportedOperationException("Cannot get team from a SoloMatch");
}
@Override
public MatchTeam getTeam(MatchPlayer matchPlayer) {
throw new UnsupportedOperationException("Cannot get team from a SoloMatch");
}
@Override
public MatchTeam getTeam(Player player) {
throw new UnsupportedOperationException("Cannot get team from a SoloMatch");
}
@Override
public MatchPlayer getMatchPlayer(Player player) {
if (this.playerA.getUuid().equals(player.getUniqueId())) {
return this.playerA;
} else if (this.playerB.getUuid().equals(player.getUniqueId())) {
return this.playerB;
} else {
return null;
}
}
@Override
public int getOpponentsLeft(Player player) {
throw new UnsupportedOperationException("Cannot get opponents left from a SoloMatch");
}
@Override
public MatchTeam getOpponentTeam(MatchTeam team) {
throw new UnsupportedOperationException("Cannot get opponent team from a SoloMatch");
}
@Override
public MatchTeam getOpponentTeam(Player player) {
throw new UnsupportedOperationException("Cannot get opponent team from a SoloMatch");
}
@Override
public Player getOpponentPlayer(Player player) {
if (player == null) {
return null;
}
if (this.playerA.getUuid().equals(player.getUniqueId())) {
return this.playerB.toPlayer();
} else if (this.playerB.getUuid().equals(player.getUniqueId())) {
return this.playerA.toPlayer();
} else {
return null;
}
}
@Override
public MatchPlayer getOpponentMatchPlayer(Player player) {
if (this.playerA.getUuid().equals(player.getUniqueId())) {
return this.playerB;
} else if (this.playerB.getUuid().equals(player.getUniqueId())) {
return this.playerA;
} else {
return null;
}
}
@Override
public int getTotalRoundWins() {
return this.playerARoundWins + this.playerBRoundWins;
}
@Override
public int getRoundWins(MatchPlayer matchPlayer) {
if (this.playerA.equals(matchPlayer)) {
return this.playerARoundWins;
} else if (this.playerB.equals(matchPlayer)) {
return this.playerBRoundWins;
} else {
return -1;
}
}
@Override
public int getRoundWins(MatchTeam matchTeam) {
throw new UnsupportedOperationException("Cannot get team round wins from SoloMatch");
}
@Override
public int getRoundsNeeded(MatchPlayer matchPlayer) {
if (this.playerA.equals(matchPlayer)) {
return 3 - this.playerARoundWins;
} else if (this.playerB.equals(matchPlayer)) {
return 3 - this.playerBRoundWins;
} else {
return -1;
}
}
@Override
public int getRoundsNeeded(MatchTeam matchTeam) {
throw new UnsupportedOperationException("Cannot get team round wins from SoloMatch");
}
@Override
public void onDeath(Player player, Player killer) {
MatchPlayer roundLoser = this.getMatchPlayer(player);
MatchPlayer roundWinner = this.getOpponentMatchPlayer(player);
this.getSnapshots().add(new MatchSnapshot(roundLoser, roundWinner));
PlayerUtil.reset(player);
if (this.getLadder().isSumo()) {
if (this.playerA.getUuid().equals(player.getUniqueId())) {
this.playerBRoundWins++;
} else {
this.playerARoundWins++;
}
if (this.canEnd()) {
final String broadcast =
Style.PINK + roundWinner.getName() + Style.YELLOW + " has " + Style.GREEN + "won" +
Style.YELLOW + " the match.";
this.setState(MatchState.ENDING);
this.broadcastMessage(broadcast);
this.getOpponentPlayer(player).hidePlayer(player);
this.getSpectators().forEach(other -> other.hidePlayer(player));
} else {
final String broadcast =
Style.PINK + roundWinner.getName() + Style.YELLOW + " has " + Style.GREEN + "won" +
Style.YELLOW + " the round, they need " + Style.GOLD + this.getRoundsNeeded(roundWinner) +
Style.YELLOW + " more to win.";
this.broadcastMessage(broadcast);
this.handleStart();
}
}
}
@Override
public void onRespawn(Player player) {
if (this.getLadder().isSumo() && !this.isEnding()) {
player.teleport(this.getArena().getSpawn1());
this.getOpponentPlayer(player).teleport(this.getArena().getSpawn2());
} else {
player.teleport(player.getLocation().clone().add(0, 3, 0));
}
}
}

View File

@ -0,0 +1,446 @@
package me.joeleoli.praxi.match.impl;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import me.joeleoli.nucleus.chat.ChatComponentBuilder;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.match.MatchSnapshot;
import me.joeleoli.praxi.match.MatchState;
import me.joeleoli.praxi.match.MatchTeam;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import org.bukkit.entity.Player;
@Getter
public class TeamMatch extends Match {
private MatchTeam teamA;
private MatchTeam teamB;
private int teamARoundWins = 0;
private int teamBRoundWins = 0;
public TeamMatch(MatchTeam teamA, MatchTeam teamB, Ladder ladder, Arena arena) {
super(null, ladder, arena, false);
this.teamA = teamA;
this.teamB = teamB;
}
@Override
public boolean isDuel() {
return false;
}
@Override
public boolean isSoloMatch() {
return false;
}
@Override
public boolean isTeamMatch() {
return true;
}
@Override
public void onStart() {
}
@Override
public void onEnd() {
final MatchTeam winningTeam = this.getWinningTeam();
final MatchTeam losingTeam = this.getOpponentTeam(winningTeam);
final ChatComponentBuilder winnerInventories = new ChatComponentBuilder("");
final ChatComponentBuilder loserInventories = new ChatComponentBuilder("");
winnerInventories
.append("Winners: ")
.color(ChatColor.GREEN);
loserInventories
.append("Losers: ")
.color(ChatColor.RED);
for (MatchPlayer matchPlayer : winningTeam.getTeamPlayers()) {
final HoverEvent hover = new HoverEvent(HoverEvent.Action.SHOW_TEXT, HOVER_TEXT);
final ClickEvent click =
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewinv " + matchPlayer.getUuid().toString());
winnerInventories
.append(matchPlayer.getName())
.color(ChatColor.YELLOW);
winnerInventories
.setCurrentHoverEvent(hover)
.setCurrentClickEvent(click)
.append(", ")
.color(ChatColor.YELLOW);
}
for (MatchPlayer matchPlayer : losingTeam.getTeamPlayers()) {
final HoverEvent hover = new HoverEvent(HoverEvent.Action.SHOW_TEXT, HOVER_TEXT);
final ClickEvent click =
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewinv " + matchPlayer.getUuid().toString());
loserInventories
.append(matchPlayer.getName())
.color(ChatColor.YELLOW);
loserInventories
.setCurrentHoverEvent(hover)
.setCurrentClickEvent(click)
.append(", ")
.color(ChatColor.YELLOW);
}
winnerInventories.getCurrent().setText(winnerInventories.getCurrent().getText().substring(
0,
winnerInventories.getCurrent().getText().length() - 2
));
loserInventories.getCurrent().setText(loserInventories.getCurrent().getText().substring(
0,
loserInventories.getCurrent().getText().length() - 2
));
final List<BaseComponent[]> components = new ArrayList<>();
components.add(new ChatComponentBuilder("").parse(Style.getBorderLine()).create());
components.add(new ChatComponentBuilder("").parse("&dPost-Match Inventories &7(click name to view)").create());
components.add(winnerInventories.create());
components.add(loserInventories.create());
components.add(new ChatComponentBuilder("").parse(Style.getBorderLine()).create());
for (Player player : this.getPlayers()) {
components.forEach(player::sendMessage);
}
for (Player player : this.getSpectators()) {
components.forEach(player::sendMessage);
}
}
@Override
public boolean canEnd() {
if (this.getLadder().isSumo()) {
return (this.teamA.getDeadCount() + this.teamA.getDisconnectedCount()) >= this.teamA.getTeamPlayers().size()
||
(this.teamB.getDeadCount() + this.teamB.getDisconnectedCount()) >= this.teamB.getTeamPlayers().size()
|| this.teamARoundWins == 3
|| this.teamBRoundWins == 3;
} else {
return this.teamA.getAliveTeamPlayers().isEmpty() || this.teamB.getAliveTeamPlayers().isEmpty();
}
}
@Override
public Player getWinningPlayer() {
throw new UnsupportedOperationException("Cannot get solo winning player from a TeamMatch");
}
@Override
public MatchTeam getWinningTeam() {
if (this.getLadder().isSumo()) {
if (this.teamA.getDisconnectedCount() == this.teamA.getTeamPlayers().size()) {
return this.teamB;
} else if (this.teamB.getDisconnectedCount() == this.teamB.getTeamPlayers().size()) {
return this.teamA;
}
return this.teamARoundWins == 3 ? this.teamA : this.teamB;
} else {
if (this.teamA.getAliveTeamPlayers().isEmpty()) {
return this.teamB;
} else if (this.teamB.getAliveTeamPlayers().isEmpty()) {
return this.teamA;
} else {
return null;
}
}
}
@Override
public MatchPlayer getMatchPlayerA() {
throw new UnsupportedOperationException("Cannot get solo match player from a TeamMatch");
}
@Override
public MatchPlayer getMatchPlayerB() {
throw new UnsupportedOperationException("Cannot get solo match player from a TeamMatch");
}
@Override
public List<MatchPlayer> getMatchPlayers() {
List<MatchPlayer> matchPlayers = new ArrayList<>();
matchPlayers.addAll(this.teamA.getTeamPlayers());
matchPlayers.addAll(this.teamB.getTeamPlayers());
return matchPlayers;
}
@Override
public Player getPlayerA() {
throw new UnsupportedOperationException("Cannot get solo player from a TeamMatch");
}
@Override
public Player getPlayerB() {
throw new UnsupportedOperationException("Cannot get solo player from a TeamMatch");
}
@Override
public List<Player> getPlayers() {
List<Player> players = new ArrayList<>();
this.teamA.getTeamPlayers().forEach(matchPlayer -> {
Player player = matchPlayer.toPlayer();
if (player != null) {
players.add(player);
}
});
this.teamB.getTeamPlayers().forEach(matchPlayer -> {
Player player = matchPlayer.toPlayer();
if (player != null) {
players.add(player);
}
});
return players;
}
@Override
public MatchTeam getTeamA() {
return this.teamA;
}
@Override
public MatchTeam getTeamB() {
return this.teamB;
}
@Override
public MatchTeam getTeam(MatchPlayer matchPlayer) {
for (MatchPlayer teamMatchPlayer : this.teamA.getTeamPlayers()) {
if (teamMatchPlayer.getUuid().equals(matchPlayer.getUuid())) {
return this.teamA;
}
}
for (MatchPlayer teamMatchPlayer : this.teamB.getTeamPlayers()) {
if (teamMatchPlayer.getUuid().equals(matchPlayer.getUuid())) {
return this.teamB;
}
}
return null;
}
@Override
public MatchTeam getTeam(Player player) {
for (MatchPlayer teamMatchPlayer : this.teamA.getTeamPlayers()) {
if (teamMatchPlayer.getUuid().equals(player.getUniqueId())) {
return this.teamA;
}
}
for (MatchPlayer teamMatchPlayer : this.teamB.getTeamPlayers()) {
if (teamMatchPlayer.getUuid().equals(player.getUniqueId())) {
return this.teamB;
}
}
return null;
}
@Override
public MatchPlayer getMatchPlayer(Player player) {
for (MatchPlayer matchPlayer : this.teamA.getTeamPlayers()) {
if (matchPlayer.getUuid().equals(player.getUniqueId())) {
return matchPlayer;
}
}
for (MatchPlayer matchPlayer : this.teamB.getTeamPlayers()) {
if (matchPlayer.getUuid().equals(player.getUniqueId())) {
return matchPlayer;
}
}
return null;
}
@Override
public int getOpponentsLeft(Player player) {
if (this.teamA.containsPlayer(player)) {
return this.teamB.getAliveCount() - this.teamB.getDisconnectedCount();
} else if (this.teamB.containsPlayer(player)) {
return this.teamA.getAliveCount() - this.teamA.getDisconnectedCount();
} else {
return -1;
}
}
@Override
public MatchTeam getOpponentTeam(MatchTeam team) {
if (this.teamA.equals(team)) {
return this.teamB;
} else if (this.teamB.equals(team)) {
return this.teamA;
} else {
return null;
}
}
@Override
public MatchTeam getOpponentTeam(Player player) {
if (this.teamA.containsPlayer(player)) {
return this.teamB;
} else if (this.teamB.containsPlayer(player)) {
return this.teamA;
} else {
return null;
}
}
@Override
public Player getOpponentPlayer(Player player) {
throw new UnsupportedOperationException("Cannot get solo opponent player from TeamMatch");
}
@Override
public MatchPlayer getOpponentMatchPlayer(Player player) {
throw new UnsupportedOperationException("Cannot get solo opponent match player from TeamMatch");
}
@Override
public int getTotalRoundWins() {
return this.teamARoundWins + this.teamBRoundWins;
}
@Override
public int getRoundWins(MatchPlayer matchPlayer) {
throw new UnsupportedOperationException("Cannot get solo round wins from TeamMatch");
}
@Override
public int getRoundWins(MatchTeam matchTeam) {
if (this.teamA.equals(matchTeam)) {
return this.teamARoundWins;
} else if (this.teamB.equals(matchTeam)) {
return this.teamBRoundWins;
} else {
return -1;
}
}
@Override
public int getRoundsNeeded(MatchPlayer matchPlayer) {
throw new UnsupportedOperationException("Cannot get solo rounds needed from TeamMatch");
}
@Override
public int getRoundsNeeded(MatchTeam matchTeam) {
if (this.teamA.equals(matchTeam)) {
return 3 - this.teamARoundWins;
} else if (this.teamB.equals(matchTeam)) {
return 3 - this.teamBRoundWins;
} else {
return -1;
}
}
@Override
public void onDeath(Player player, Player killer) {
// TODO: request teams messages directly then request global messages to spectators
// MatchTeam roundLoser = this.getOpponentTeam(player);
this.getSnapshots().add(new MatchSnapshot(this.getMatchPlayer(player)));
PlayerUtil.reset(player);
this.getPlayers().forEach(matchPlayer -> {
matchPlayer.hidePlayer(player);
});
if (this.getLadder().isSumo()) {
final MatchTeam deadTeam = this.getTeam(player);
final MatchTeam roundWinner = this.getOpponentTeam(deadTeam);
final int dead = deadTeam.getDisconnectedCount() + deadTeam.getDeadCount();
if (dead == deadTeam.getTeamPlayers().size()) {
if (this.teamA.equals(roundWinner)) {
this.teamARoundWins++;
} else {
this.teamBRoundWins++;
}
if (this.canEnd()) {
this.setState(MatchState.ENDING);
this.getPlayers().forEach(other -> other.hidePlayer(player));
this.getSpectators().forEach(other -> other.hidePlayer(player));
} else {
final String broadcast =
roundWinner.getLeader().getDisplayName() + Style.YELLOW + "'s team has " + Style.GREEN +
"won" + Style.YELLOW + " the round, they need " + Style.GOLD +
this.getRoundsNeeded(roundWinner) + Style.YELLOW + " more to win.";
this.broadcastMessage(broadcast);
this.handleStart();
}
} else {
for (Player other : this.getPlayers()) {
other.hidePlayer(player);
}
player.setAllowFlight(true);
player.setFlying(true);
player.updateInventory();
}
} else {
if (!this.canEnd()) {
player.setAllowFlight(true);
player.setFlying(true);
player.updateInventory();
}
}
}
@Override
public void onRespawn(Player player) {
if (this.getLadder().isSumo() && !this.isEnding()) {
for (MatchPlayer matchPlayer : this.teamA.getTeamPlayers()) {
if (matchPlayer.isDisconnected()) {
continue;
}
final Player toPlayer = matchPlayer.toPlayer();
if (toPlayer != null && toPlayer.isOnline()) {
toPlayer.teleport(this.getArena().getSpawn1());
}
}
for (MatchPlayer matchPlayer : this.teamB.getTeamPlayers()) {
if (matchPlayer.isDisconnected()) {
continue;
}
final Player toPlayer = matchPlayer.toPlayer();
if (toPlayer != null && toPlayer.isOnline()) {
toPlayer.teleport(this.getArena().getSpawn2());
}
}
} else {
player.teleport(player.getLocation().clone().add(0, 3, 0));
}
}
}

View File

@ -0,0 +1,66 @@
package me.joeleoli.praxi.mongo;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.ReplaceOptions;
import java.util.Collections;
import java.util.UUID;
import me.joeleoli.nucleus.config.ConfigCursor;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bson.Document;
public class PraxiMongo {
private MongoClient client;
private MongoDatabase database;
private MongoCollection<Document> players;
private MongoCollection<Document> matches;
public PraxiMongo() {
ConfigCursor cursor = new ConfigCursor(Praxi.getInstance().getMainConfig(), "mongo");
if (!cursor.exists("host")
|| !cursor.exists("port")
|| !cursor.exists("database")
|| !cursor.exists("authentication.enabled")
|| !cursor.exists("authentication.username")
|| !cursor.exists("authentication.password")
|| !cursor.exists("authentication.database")) {
throw new RuntimeException("Missing configuration option");
}
if (cursor.getBoolean("authentication.enabled")) {
final MongoCredential credential = MongoCredential.createCredential(
cursor.getString("authentication.username"),
cursor.getString("authentication.database"),
cursor.getString("authentication.password").toCharArray()
);
this.client = new MongoClient(new ServerAddress(cursor.getString("host"), cursor.getInt("port")),
Collections.singletonList(credential)
);
} else {
this.client = new MongoClient(new ServerAddress(cursor.getString("host"), cursor.getInt("port")));
}
this.database = this.client.getDatabase("praxi");
this.players = this.database.getCollection("players");
this.matches = this.database.getCollection("matches");
}
public Document getPlayer(UUID uuid) {
return this.players.find(Filters.eq("uuid", uuid.toString())).first();
}
public void replacePlayer(PraxiPlayer player, Document document) {
this.players.replaceOne(Filters.eq("uuid", player.getUuid().toString()), document,
new ReplaceOptions().upsert(true)
);
}
}

View File

@ -0,0 +1,154 @@
package me.joeleoli.praxi.party;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.chat.ChatComponentBuilder;
import me.joeleoli.nucleus.team.Team;
import me.joeleoli.nucleus.team.TeamPlayer;
import me.joeleoli.nucleus.util.ObjectUtil;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.player.PraxiPlayer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import org.bukkit.entity.Player;
@Getter
public class Party extends Team<TeamPlayer> {
@Getter
private static List<Party> parties = new ArrayList<>();
private PartyState state = PartyState.CLOSED;
private Map<UUID, Long> invited;
@Setter
private PartyEvent selectedEvent;
public Party(Player player) {
super(new TeamPlayer(player.getUniqueId(), player.getName()));
this.invited = new HashMap<>();
parties.add(this);
}
public void setState(PartyState state) {
this.state = state;
this.broadcast(Style.YELLOW + "The party state has been changed to: " + Style.RESET + this.state.name());
}
public boolean canInvite(Player player) {
for (UUID uuid : this.invited.keySet()) {
if (uuid.equals(player.getUniqueId())) {
if (System.currentTimeMillis() - this.invited.get(uuid) >= 30_000) {
this.invited.remove(uuid);
return true;
}
return false;
}
}
return true;
}
public boolean isInvited(Player player) {
for (UUID uuid : this.invited.keySet()) {
if (uuid.equals(player.getUniqueId())) {
if (System.currentTimeMillis() - this.invited.get(uuid) >= 30_000) {
this.invited.remove(uuid);
return false;
}
return true;
}
}
return false;
}
public void invite(Player target) {
this.invited.put(target.getUniqueId(), System.currentTimeMillis());
final HoverEvent hoverEvent = new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new ChatComponentBuilder(Style.YELLOW + "Click to join the party.").create()
);
final ClickEvent clickEvent =
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/party join " + this.getLeader().getName());
this.broadcast(Style.RESET + target.getDisplayName() + " " + Style.YELLOW + "has been invited to the party.");
target.sendMessage(
Style.YELLOW + "You have been invited to join " + Style.RESET + this.getLeader().getDisplayName() +
Style.YELLOW + "'s party.");
target.sendMessage(new ChatComponentBuilder("").parse(Style.GOLD + "Click here to join the party.")
.attachToEachPart(clickEvent).attachToEachPart(hoverEvent)
.create());
}
public void join(Player player) {
this.getTeamPlayers().add(new TeamPlayer(player.getUniqueId(), player.getName()));
this.invited.keySet().removeIf(uuid -> uuid.equals(player.getUniqueId()));
this.broadcast(Style.RESET + player.getDisplayName() + Style.YELLOW + " has joined the party.");
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setParty(this);
praxiPlayer.loadHotbar();
}
public void leave(Player player, boolean kick) {
this.broadcast(
Style.RESET + player.getDisplayName() + Style.YELLOW + " has " + (kick ? "been kicked" : "left") +
" the party.");
this.getTeamPlayers().removeIf(playerInfo -> playerInfo.getUuid().equals(player.getUniqueId()));
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setParty(null);
praxiPlayer.loadHotbar();
}
public void disband() {
parties.remove(this);
this.broadcast(Style.YELLOW + "The party has been disbanded.");
this.getPlayers().forEach(player -> {
PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.setParty(null);
if (praxiPlayer.isInLobby()) {
praxiPlayer.loadHotbar();
}
});
}
public void sendInformation(Player player) {
StringBuilder builder = new StringBuilder();
for (Player member : this.getPlayers()) {
builder.append(member.getName());
builder.append(", ");
}
final String[] lines = new String[]{
Style.getBorderLine(),
Style.GOLD + "Party of " + this.getLeader().getName(),
Style.YELLOW + "State: " + Style.GRAY + ObjectUtil.toReadable(this.state),
Style.YELLOW + "Members: " + Style.GRAY +
builder.toString().substring(0, builder.toString().length() - 2),
Style.getBorderLine()
};
player.sendMessage(lines);
}
}

View File

@ -0,0 +1,15 @@
package me.joeleoli.praxi.party;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum PartyEvent {
FFA("FFA"),
SPLIT("Split");
private String name;
}

View File

@ -0,0 +1,6 @@
package me.joeleoli.praxi.party;
public enum PartyState {
OPEN,
CLOSED
}

View File

@ -0,0 +1,30 @@
package me.joeleoli.praxi.party.gui;
import java.util.HashMap;
import java.util.Map;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.pagination.PaginatedMenu;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.party.Party;
import me.joeleoli.praxi.party.gui.button.PartyDisplayButton;
import org.bukkit.entity.Player;
public class OtherPartiesMenu extends PaginatedMenu {
@Override
public String getPrePaginatedTitle(Player player) {
return Style.GOLD + "Other Parties";
}
@Override
public Map<Integer, Button> getAllPagesButtons(Player player) {
Map<Integer, Button> buttons = new HashMap<>();
Party.getParties().forEach(party -> {
buttons.put(buttons.size(), new PartyDisplayButton(party));
});
return buttons;
}
}

View File

@ -0,0 +1,68 @@
package me.joeleoli.praxi.party.gui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.party.PartyEvent;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class PartyEventSelectEventMenu extends Menu {
@Override
public String getTitle(Player player) {
return Style.BLUE + Style.BOLD + "Select an event";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
final Map<Integer, Button> buttons = new HashMap<>();
buttons.put(3, new SelectEventButton(PartyEvent.FFA));
buttons.put(5, new SelectEventButton(PartyEvent.SPLIT));
return buttons;
}
@AllArgsConstructor
private class SelectEventButton extends Button {
private PartyEvent partyEvent;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(this.partyEvent == PartyEvent.FFA ? Material.QUARTZ : Material.REDSTONE)
.name(Style.GREEN + Style.BOLD + this.partyEvent.getName())
.lore(Arrays.asList(
"",
Style.YELLOW + "Click here to select " + Style.GREEN + Style.BOLD +
this.partyEvent.getName() + Style.YELLOW + "."
))
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hotbarSlot) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You are not in a party.");
return;
}
praxiPlayer.getParty().setSelectedEvent(this.partyEvent);
new PartyEventSelectLadderMenu().openMenu(player);
}
}
}

View File

@ -0,0 +1,151 @@
package me.joeleoli.praxi.party.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.match.MatchTeam;
import me.joeleoli.praxi.match.impl.TeamMatch;
import me.joeleoli.praxi.party.Party;
import me.joeleoli.praxi.party.PartyEvent;
import me.joeleoli.praxi.player.PlayerState;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class PartyEventSelectLadderMenu extends Menu {
@Override
public String getTitle(Player player) {
return Style.GOLD + Style.BOLD + "Select a ladder";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
final Map<Integer, Button> buttons = new HashMap<>();
for (Ladder ladder : Ladder.getLadders()) {
if (ladder.isEnabled()) {
buttons.put(buttons.size(), new SelectLadderButton(ladder));
}
}
return buttons;
}
@Override
public void onClose(Player player) {
if (!this.isClosedByMenu()) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() != null) {
praxiPlayer.getParty().setSelectedEvent(null);
}
}
}
@AllArgsConstructor
private class SelectLadderButton extends Button {
private Ladder ladder;
@Override
public ItemStack getButtonItem(Player player) {
return new ItemBuilder(this.ladder.getDisplayIcon())
.name(Style.PINK + Style.BOLD + this.ladder.getName())
.lore(Arrays.asList(
"",
Style.YELLOW + "Click here to select " + Style.PINK + Style.BOLD +
this.ladder.getName() + Style.YELLOW + "."
))
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hbSlot) {
Menu.currentlyOpenedMenus.get(player.getName()).setClosedByMenu(true);
player.closeInventory();
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer.getParty() == null) {
player.sendMessage(Style.RED + "You are not in a party.");
return;
}
if (praxiPlayer.getParty().getSelectedEvent() == null) {
return;
}
if (praxiPlayer.getParty().getTeamPlayers().size() <= 1) {
player.sendMessage(Style.RED + "You do not have enough players in your party to start an event.");
return;
}
Party party = praxiPlayer.getParty();
Arena arena = Arena.getRandom(this.ladder);
if (arena == null) {
player.sendMessage(Style.RED + "There are no available arenas.");
return;
}
arena.setActive(true);
Match match;
if (party.getSelectedEvent() == PartyEvent.FFA) {
player.sendMessage(Style.RED + "The FFA party event is currently disabled.");
return;
} else {
MatchTeam teamA = new MatchTeam(new MatchPlayer(party.getLeader().toPlayer()));
MatchTeam teamB = new MatchTeam(new MatchPlayer(party.getPlayers().get(1)));
final List<Player> players = new ArrayList<>();
players.addAll(party.getPlayers());
Collections.shuffle(players);
// Create match
match = new TeamMatch(teamA, teamB, this.ladder, arena);
for (Player other : players) {
final PraxiPlayer otherData = PraxiPlayer.getByUuid(other.getUniqueId());
otherData.setState(PlayerState.IN_MATCH);
otherData.setMatch(match);
if (teamA.getLeader().getUuid().equals(other.getUniqueId()) ||
teamB.getLeader().getUuid().equals(other.getUniqueId())) {
continue;
}
if (teamA.getTeamPlayers().size() > teamB.getTeamPlayers().size()) {
teamB.getTeamPlayers().add(new MatchPlayer(other));
} else {
teamA.getTeamPlayers().add(new MatchPlayer(other));
}
}
}
// Start match
match.handleStart();
}
}
}

View File

@ -0,0 +1,47 @@
package me.joeleoli.praxi.party.gui.button;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.team.TeamPlayer;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.party.Party;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@AllArgsConstructor
public class PartyDisplayButton extends Button {
private Party party;
@Override
public ItemStack getButtonItem(Player player) {
final List<String> lore = new ArrayList<>();
int added = 0;
for (TeamPlayer teamPlayer : this.party.getTeamPlayers()) {
if (added >= 10) {
break;
}
lore.add(Style.GRAY + " - " + Style.RESET + teamPlayer.getDisplayName());
added++;
}
if (this.party.getTeamPlayers().size() != added) {
lore.add(Style.GRAY + " and " + (this.party.getTeamPlayers().size() - added) + " others...");
}
return new ItemBuilder(Material.SKULL_ITEM)
.amount(this.party.getTeamPlayers().size())
.durability(3)
.name(Style.GOLD + this.party.getLeader().getName() + "s Party")
.lore(lore)
.build();
}
}

View File

@ -0,0 +1,25 @@
package me.joeleoli.praxi.player;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.praxi.kit.NamedKit;
import me.joeleoli.praxi.ladder.Ladder;
@Setter
public class KitEditor {
@Getter
private boolean active;
private boolean rename;
@Getter
private PlayerState previousState;
@Getter
private Ladder selectedLadder;
@Getter
private NamedKit selectedKit;
public boolean isRenaming() {
return this.active && this.rename && this.selectedKit != null;
}
}

View File

@ -0,0 +1,19 @@
package me.joeleoli.praxi.player;
import lombok.Data;
@Data
public class LadderStatistics {
private int elo = 1000;
private int won, lost;
public void incrementWon() {
this.won++;
}
public void incrementLost() {
this.lost++;
}
}

View File

@ -0,0 +1,231 @@
package me.joeleoli.praxi.player;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.Praxi;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public class PlayerHotbar {
@Getter
private static Map<HotbarItem, ItemStack> items = new HashMap<>();
// Utility class - cannot be instantiated
private PlayerHotbar() {
}
public static void init() {
items.put(
HotbarItem.QUEUE_JOIN_UNRANKED,
new ItemBuilder(Material.IRON_SWORD).name(Style.GRAY + Style.BOLD + "Unranked Queue")
.lore(Style.YELLOW + "Right-click to join an unranked queue.")
.build()
);
items.put(
HotbarItem.QUEUE_JOIN_RANKED,
new ItemBuilder(Material.DIAMOND_SWORD).name(Style.GREEN + Style.BOLD + "Ranked Queue")
.lore(Style.YELLOW + "Right-click to join a ranked queue.")
.build()
);
items.put(
HotbarItem.QUEUE_LEAVE,
new ItemBuilder(Material.INK_SACK).durability(1).name(Style.RED + Style.BOLD + "Leave Queue")
.lore(Style.YELLOW + "Right-click to leave your queue.").build()
);
items.put(
HotbarItem.PARTY_EVENTS,
new ItemBuilder(Material.DIAMOND_SWORD).name(Style.GREEN + Style.BOLD + "Party Events")
.lore(Style.YELLOW + "Right-click to start a party event.")
.build()
);
items.put(
HotbarItem.PARTY_CREATE,
new ItemBuilder(Material.NAME_TAG).name(Style.YELLOW + Style.BOLD + "Create Party")
.lore(Style.YELLOW + "Right-click to create a party.").build()
);
items.put(
HotbarItem.PARTY_DISBAND,
new ItemBuilder(Material.INK_SACK).durability(1).name(Style.RED + Style.BOLD + "Disband Party")
.lore(Style.YELLOW + "Right-click to disband your party.").build()
);
items.put(
HotbarItem.PARTY_LEAVE,
new ItemBuilder(Material.INK_SACK).durability(1).name(Style.RED + Style.BOLD + "Leave Party")
.lore(Style.YELLOW + "Right-click to leave your party.").build()
);
items.put(
HotbarItem.PARTY_INFORMATION,
new ItemBuilder(Material.SKULL_ITEM).durability(3).name(Style.YELLOW + Style.BOLD + "Party Information")
.lore(Style.YELLOW +
"Right-click to show your party's information.").build()
);
items.put(
HotbarItem.OTHER_PARTIES,
new ItemBuilder(Material.CHEST).name(Style.BLUE + Style.BOLD + "Other Parties")
.lore(Style.YELLOW + "Right-click to show other parties.").build()
);
items.put(HotbarItem.SETTINGS, new ItemBuilder(Material.WATCH).name(Style.PINK + Style.BOLD + "Settings")
.lore(Style.YELLOW +
"Right-click to open your settings.")
.build());
items.put(HotbarItem.KIT_EDITOR, new ItemBuilder(Material.BOOK).name(Style.RED + Style.BOLD + "Kit Editor")
.lore(Style.YELLOW +
"Right-click to open the kit editor.")
.build());
items.put(
HotbarItem.SPECTATE_STOP,
new ItemBuilder(Material.INK_SACK).durability(1).name(Style.RED + Style.BOLD + "Stop Spectating")
.lore(Style.YELLOW + "Right-click to stop spectating.").build()
);
items.put(
HotbarItem.VIEW_INVENTORY,
new ItemBuilder(Material.BOOK).name(Style.GOLD + Style.BOLD + "View Inventory")
.lore(Style.YELLOW + "Right-click a player to view their inventory.")
.build()
);
items.put(
HotbarItem.EVENT_JOIN,
new ItemBuilder(Material.NETHER_STAR).name(Style.AQUA + Style.BOLD + "Join Event")
.lore(Style.YELLOW + "Right-click to join the event.").build()
);
items.put(
HotbarItem.EVENT_LEAVE,
new ItemBuilder(Material.NETHER_STAR).name(Style.RED + Style.BOLD + "Leave Event")
.lore(Style.YELLOW + "Right-click to leave the event.").build()
);
items.put(
HotbarItem.REMATCH_REQUEST,
new ItemBuilder(Material.EMERALD).name(Style.DARK_GREEN + Style.BOLD + "Request Rematch")
.lore(Style.YELLOW + "Right-click to request a rematch.").build()
);
items.put(
HotbarItem.REMATCH_ACCEPT,
new ItemBuilder(Material.DIAMOND).name(Style.AQUA + Style.BOLD + "Accept Rematch")
.lore(Style.YELLOW + "Right-click to accept a rematch.").build()
);
}
public static ItemStack[] getLayout(HotbarLayout layout, PraxiPlayer praxiPlayer) {
final ItemStack[] toReturn = new ItemStack[9];
Arrays.fill(toReturn, null);
switch (layout) {
case LOBBY: {
if (praxiPlayer.getParty() == null) {
toReturn[0] = items.get(HotbarItem.QUEUE_JOIN_UNRANKED);
toReturn[1] = items.get(HotbarItem.QUEUE_JOIN_RANKED);
if (praxiPlayer.getRematchData() != null) {
if (praxiPlayer.getRematchData().isReceive()) {
toReturn[2] = items.get(HotbarItem.REMATCH_ACCEPT);
} else {
toReturn[2] = items.get(HotbarItem.REMATCH_REQUEST);
}
toReturn[4] = items.get(HotbarItem.PARTY_CREATE);
if (Praxi.getInstance().getEventManager().getActiveEvent() != null && Praxi.getInstance().getEventManager().getActiveEvent().isWaiting()) {
toReturn[6] = items.get(HotbarItem.EVENT_JOIN);
}
} else {
if (Praxi.getInstance().getEventManager().getActiveEvent() != null && Praxi.getInstance().getEventManager().getActiveEvent().isWaiting()) {
toReturn[3] = items.get(HotbarItem.EVENT_JOIN);
toReturn[5] = items.get(HotbarItem.PARTY_CREATE);
} else {
toReturn[4] = items.get(HotbarItem.PARTY_CREATE);
}
}
toReturn[7] = items.get(HotbarItem.SETTINGS);
toReturn[8] = items.get(HotbarItem.KIT_EDITOR);
} else {
if (praxiPlayer.getParty().isLeader(praxiPlayer.getUuid())) {
toReturn[0] = items.get(HotbarItem.PARTY_EVENTS);
toReturn[2] = items.get(HotbarItem.PARTY_INFORMATION);
toReturn[3] = items.get(HotbarItem.OTHER_PARTIES);
toReturn[5] = items.get(HotbarItem.PARTY_DISBAND);
toReturn[7] = items.get(HotbarItem.SETTINGS);
toReturn[8] = items.get(HotbarItem.KIT_EDITOR);
} else {
toReturn[0] = items.get(HotbarItem.PARTY_INFORMATION);
toReturn[2] = items.get(HotbarItem.OTHER_PARTIES);
toReturn[4] = items.get(HotbarItem.PARTY_LEAVE);
toReturn[7] = items.get(HotbarItem.SETTINGS);
toReturn[8] = items.get(HotbarItem.KIT_EDITOR);
}
}
}
break;
case QUEUE: {
toReturn[0] = items.get(HotbarItem.QUEUE_LEAVE);
toReturn[7] = items.get(HotbarItem.SETTINGS);
toReturn[8] = items.get(HotbarItem.KIT_EDITOR);
}
break;
case EVENT_SPECTATE: {
toReturn[0] = items.get(HotbarItem.EVENT_LEAVE);
toReturn[8] = items.get(HotbarItem.SETTINGS);
}
break;
case MATCH_SPECTATE: {
toReturn[0] = items.get(HotbarItem.SPECTATE_STOP);
if (!praxiPlayer.getMatch().isRanked()) {
toReturn[5] = items.get(HotbarItem.VIEW_INVENTORY);
}
toReturn[8] = items.get(HotbarItem.SETTINGS);
}
break;
}
return toReturn;
}
public static HotbarItem fromItemStack(ItemStack itemStack) {
for (Map.Entry<HotbarItem, ItemStack> entry : PlayerHotbar.getItems().entrySet()) {
if (entry.getValue() != null && entry.getValue().equals(itemStack)) {
return entry.getKey();
}
}
return null;
}
@AllArgsConstructor
public enum HotbarItem {
QUEUE_JOIN_RANKED,
QUEUE_JOIN_UNRANKED,
QUEUE_LEAVE,
PARTY_EVENTS,
PARTY_CREATE,
PARTY_DISBAND,
PARTY_LEAVE,
PARTY_INFORMATION,
OTHER_PARTIES,
SETTINGS,
KIT_EDITOR,
SPECTATE_STOP,
VIEW_INVENTORY,
EVENT_JOIN,
EVENT_LEAVE,
REMATCH_REQUEST,
REMATCH_ACCEPT
}
public enum HotbarLayout {
LOBBY,
QUEUE,
MATCH_SPECTATE,
EVENT_SPECTATE,
}
}

View File

@ -0,0 +1,11 @@
package me.joeleoli.praxi.player;
public enum PlayerState {
IN_LOBBY,
IN_QUEUE,
IN_MATCH,
IN_EVENT,
SPECTATE_MATCH
}

View File

@ -0,0 +1,68 @@
package me.joeleoli.praxi.player;
import java.util.HashMap;
import java.util.Map;
import lombok.Getter;
import me.joeleoli.praxi.ladder.Ladder;
@Getter
public class PlayerStatistics {
private Map<String, LadderStatistics> ladders;
public PlayerStatistics() {
this.ladders = new HashMap<>();
for (Ladder ladder : Ladder.getLadders()) {
this.ladders.put(ladder.getName(), new LadderStatistics());
}
}
public int getElo(Ladder ladder) {
if (!this.ladders.containsKey(ladder.getName())) {
return 1000;
}
return this.ladders.get(ladder.getName()).getElo();
}
public LadderStatistics getLadderStatistics(Ladder ladder) {
LadderStatistics ladderStatistics = this.ladders.get(ladder.getName());
if (ladderStatistics == null) {
ladderStatistics = new LadderStatistics();
this.ladders.put(ladder.getName(), ladderStatistics);
}
return ladderStatistics;
}
public int getWins() {
int wins = 0;
for (LadderStatistics stats : this.ladders.values()) {
wins += stats.getWon();
}
return wins;
}
public double getWinRatio() {
int wins = 0;
int losses = 0;
for (LadderStatistics ladder : this.ladders.values()) {
wins += ladder.getWon();
losses += ladder.getLost();
}
if (losses == 0) {
return 100.0;
} else if (wins == 0 && losses > 0) {
return 0.0;
} else {
return (wins / (wins + losses)) * 100;
}
}
}

View File

@ -0,0 +1,12 @@
package me.joeleoli.praxi.player;
import me.joeleoli.nucleus.player.DefinedSetting;
public enum PracticeSetting implements DefinedSetting {
RECEIVE_DUEL_REQUESTS,
SHOW_SCOREBOARD,
ALLOW_SPECTATORS,
PING_FACTOR,
}

View File

@ -0,0 +1,394 @@
package me.joeleoli.praxi.player;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import me.joeleoli.nucleus.cooldown.Cooldown;
import me.joeleoli.nucleus.player.PlayerInfo;
import me.joeleoli.nucleus.util.InventoryUtil;
import me.joeleoli.nucleus.util.PlayerUtil;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.duel.DuelProcedure;
import me.joeleoli.praxi.duel.DuelRequest;
import me.joeleoli.praxi.events.Event;
import me.joeleoli.praxi.kit.Kit;
import me.joeleoli.praxi.kit.NamedKit;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.party.Party;
import me.joeleoli.praxi.queue.QueuePlayer;
import org.bson.Document;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@Getter
public class PraxiPlayer extends PlayerInfo {
@Getter
private static Map<UUID, PraxiPlayer> players = new HashMap<>();
@Setter
private PlayerState state;
private PlayerStatistics statistics = new PlayerStatistics();
private KitEditor kitEditor = new KitEditor();
private Map<String, NamedKit[]> kits = new HashMap<>();
@Setter
private Party party;
@Setter
private Match match;
@Setter
private Event event;
@Setter
private QueuePlayer queuePlayer;
@Setter
private Cooldown enderpearlCooldown = new Cooldown(0);
private Map<UUID, DuelRequest> sentDuelRequests = new HashMap<>();
@Setter
private DuelProcedure duelProcedure;
@Setter
private RematchData rematchData;
private boolean loaded;
public PraxiPlayer(UUID uuid, String name) {
super(uuid, name);
this.state = PlayerState.IN_LOBBY;
for (Ladder ladder : Ladder.getLadders()) {
this.kits.put(ladder.getName(), new NamedKit[4]);
}
}
public static PraxiPlayer getByUuid(UUID uuid) {
PraxiPlayer praxiPlayer = players.get(uuid);
if (praxiPlayer == null) {
praxiPlayer = new PraxiPlayer(uuid, null);
}
return praxiPlayer;
}
public boolean canSendDuelRequest(Player player) {
if (!this.sentDuelRequests.containsKey(player.getUniqueId())) {
return true;
}
final DuelRequest request = this.sentDuelRequests.get(player.getUniqueId());
if (request.isExpired()) {
this.sentDuelRequests.remove(player.getUniqueId());
return true;
} else {
return false;
}
}
public boolean isPendingDuelRequest(Player player) {
if (!this.sentDuelRequests.containsKey(player.getUniqueId())) {
return false;
}
final DuelRequest request = this.sentDuelRequests.get(player.getUniqueId());
if (request.isExpired()) {
this.sentDuelRequests.remove(player.getUniqueId());
return false;
} else {
return true;
}
}
public boolean isInLobby() {
return this.state == PlayerState.IN_LOBBY;
}
public boolean isInQueue() {
return this.state == PlayerState.IN_QUEUE && this.queuePlayer != null;
}
public boolean isInMatch() {
return (this.state == PlayerState.IN_MATCH) && this.match != null;
}
public boolean isSpectating() {
return this.state == PlayerState.SPECTATE_MATCH && this.match != null;
}
public boolean isInEvent() {
return this.state == PlayerState.IN_EVENT && this.event != null;
}
public boolean isBusy() {
return this.isInMatch() || this.isInQueue() || this.isInEvent() || this.isSpectating() ||
this.getParty() != null;
}
public void refreshHotbar() {
final Player player = this.toPlayer();
if (player == null) {
return;
}
if (this.isInLobby() && !this.kitEditor.isActive()) {
boolean update = false;
if (this.rematchData != null) {
final Player target = Bukkit.getPlayer(this.rematchData.getTarget());
if (System.currentTimeMillis() - this.rematchData.getTimestamp() >= 30_000) {
this.rematchData = null;
update = true;
} else if (target == null || !target.isOnline()) {
this.rematchData = null;
update = true;
} else {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(target.getUniqueId());
if (!(praxiPlayer.isInLobby() || praxiPlayer.isInQueue())) {
this.rematchData = null;
update = true;
} else if (praxiPlayer.getRematchData() == null) {
this.rematchData = null;
update = true;
} else if (!this.rematchData.getKey().equals(praxiPlayer.getRematchData().getKey())) {
this.rematchData = null;
update = true;
} else if (this.rematchData.isReceive()) {
final int requestSlot = player.getInventory().first(PlayerHotbar.getItems()
.get(PlayerHotbar.HotbarItem.REMATCH_REQUEST));
if (requestSlot != -1) {
update = true;
}
}
}
}
{
final Event activeEvent = Praxi.getInstance().getEventManager().getActiveEvent();
final int eventSlot =
player.getInventory().first(PlayerHotbar.getItems().get(PlayerHotbar.HotbarItem.EVENT_JOIN));
if (eventSlot == -1 && activeEvent != null && activeEvent.isWaiting()) {
update = true;
} else if (eventSlot != -1 && (activeEvent == null || !activeEvent.isWaiting())) {
update = true;
}
}
if (update) {
TaskUtil.run(this::loadHotbar);
}
}
}
public void loadHotbar() {
Player player = this.toPlayer();
if (player == null || !player.isOnline()) {
return;
}
PlayerUtil.reset(player, false);
if (this.isInLobby()) {
player.getInventory().setContents(PlayerHotbar.getLayout(PlayerHotbar.HotbarLayout.LOBBY, this));
} else if (this.isInQueue()) {
player.getInventory().setContents(PlayerHotbar.getLayout(PlayerHotbar.HotbarLayout.QUEUE, this));
} else if (this.isSpectating()) {
player.getInventory().setContents(PlayerHotbar.getLayout(PlayerHotbar.HotbarLayout.MATCH_SPECTATE, this));
} else if (this.isInEvent()) {
player.getInventory().setContents(PlayerHotbar.getLayout(PlayerHotbar.HotbarLayout.EVENT_SPECTATE, this));
}
player.updateInventory();
}
public NamedKit[] getKits(Ladder ladder) {
return this.kits.get(ladder.getName());
}
public NamedKit getKit(Ladder ladder, int index) {
return this.kits.get(ladder.getName())[index];
}
public void replaceKit(Ladder ladder, int index, NamedKit kit) {
NamedKit[] kits = this.kits.get(ladder.getName());
kits[index] = kit;
this.kits.put(ladder.getName(), kits);
}
public void deleteKit(Ladder ladder, NamedKit kit) {
if (kit == null) {
return;
}
NamedKit[] kits = this.kits.get(ladder.getName());
for (int i = 0; i < 4; i++) {
if (kits[i] != null && kits[i].equals(kit)) {
kits[i] = null;
break;
}
}
this.kits.put(ladder.getName(), kits);
}
public List<ItemStack> getKitItems(Ladder ladder) {
List<ItemStack> toReturn = new ArrayList<>();
toReturn.add(Kit.DEFAULT_KIT);
for (NamedKit kit : this.kits.get(ladder.getName())) {
if (kit != null) {
final ItemStack itemStack = new ItemStack(Material.ENCHANTED_BOOK);
final ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setDisplayName(ChatColor.GOLD + "Kit: " + ChatColor.YELLOW + kit.getName());
itemMeta.setLore(Arrays.asList(
ChatColor.GRAY + "Right-click with this book in your",
ChatColor.GRAY + "hand to receive this kit."
));
itemStack.setItemMeta(itemMeta);
toReturn.add(itemStack);
}
}
return toReturn;
}
public void load() {
try {
Document document = Praxi.getInstance().getPraxiMongo().getPlayer(this.getUuid());
if (document == null) {
this.loaded = true;
this.save();
return;
}
if (this.getName() == null) {
this.setName(document.getString("name"));
}
final Document statisticsDocument = (Document) document.get("statistics");
final Document laddersDocument = (Document) statisticsDocument.get("ladders");
final Document kitsDocument = (Document) document.get("kits");
for (String key : laddersDocument.keySet()) {
final Document ladderDocument = (Document) laddersDocument.get(key);
final Ladder ladder = Ladder.getByName(key);
if (ladder == null) {
continue;
}
LadderStatistics ladderStatistics = new LadderStatistics();
ladderStatistics.setElo(ladderDocument.getInteger("elo"));
ladderStatistics.setWon(ladderDocument.getInteger("won"));
ladderStatistics.setLost(ladderDocument.getInteger("lost"));
this.statistics.getLadders().put(ladder.getName(), ladderStatistics);
}
for (String key : kitsDocument.keySet()) {
Ladder ladder = Ladder.getByName(key);
if (ladder == null) {
continue;
}
JsonArray kitsArray = Praxi.PARSER.parse(kitsDocument.getString(key)).getAsJsonArray();
NamedKit[] kits = new NamedKit[4];
for (JsonElement kitElement : kitsArray) {
JsonObject kitObject = kitElement.getAsJsonObject();
NamedKit kit = new NamedKit(kitObject.get("name").getAsString());
kit.setArmor(InventoryUtil.deserializeInventory(kitObject.get("armor").getAsString()));
kit.setContents(InventoryUtil.deserializeInventory(kitObject.get("contents").getAsString()));
kits[kitObject.get("index").getAsInt()] = kit;
}
this.kits.put(ladder.getName(), kits);
}
} catch (Exception e) {
e.printStackTrace();
return;
}
this.loaded = true;
}
public void save() {
Document laddersDocument = new Document();
for (Map.Entry<String, LadderStatistics> entry : this.statistics.getLadders().entrySet()) {
Document ladder = new Document();
ladder.put("elo", entry.getValue().getElo());
ladder.put("won", entry.getValue().getWon());
ladder.put("lost", entry.getValue().getLost());
laddersDocument.put(entry.getKey(), ladder);
}
Document statisticsDocument = new Document();
statisticsDocument.put("ladders", laddersDocument);
Document kitsDocument = new Document();
for (Map.Entry<String, NamedKit[]> entry : this.kits.entrySet()) {
JsonArray kitsArray = new JsonArray();
for (int i = 0; i < 4; i++) {
NamedKit kit = entry.getValue()[i];
if (kit != null) {
JsonObject kitObject = new JsonObject();
kitObject.addProperty("index", i);
kitObject.addProperty("name", kit.getName());
kitObject.addProperty("armor", InventoryUtil.serializeInventory(kit.getArmor()));
kitObject.addProperty("contents", InventoryUtil.serializeInventory(kit.getContents()));
kitsArray.add(kitObject);
}
}
kitsDocument.put(entry.getKey(), kitsArray.toString());
}
Document document = new Document();
document.put("uuid", this.getUuid().toString());
document.put("name", this.getName());
document.put("statistics", statisticsDocument);
document.put("kits", kitsDocument);
Praxi.getInstance().getPraxiMongo().replacePlayer(this, document);
}
}

View File

@ -0,0 +1,127 @@
package me.joeleoli.praxi.player;
import java.util.UUID;
import lombok.Getter;
import me.joeleoli.nucleus.NucleusAPI;
import me.joeleoli.nucleus.chat.ChatComponentBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.match.impl.SoloMatch;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import org.bukkit.entity.Player;
@Getter
public class RematchData {
private static final HoverEvent HOVER_EVENT = new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new ChatComponentBuilder(Style.YELLOW + "Click to accept this rematch invite.").create()
);
private static final ClickEvent CLICK_EVENT = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/rematch");
private UUID key;
private UUID sender;
private UUID target;
private Ladder ladder;
private Arena arena;
private boolean sent;
private boolean receive;
private long timestamp = System.currentTimeMillis();
public RematchData(UUID key, UUID sender, UUID target, Ladder ladder, Arena arena) {
this.key = key;
this.sender = sender;
this.target = target;
this.ladder = ladder;
this.arena = arena;
}
public void request() {
final Player sender = Praxi.getInstance().getServer().getPlayer(this.sender);
final Player target = Praxi.getInstance().getServer().getPlayer(this.target);
if (sender == null || target == null) {
return;
}
final PraxiPlayer senderPraxiPlayer = PraxiPlayer.getByUuid(sender.getUniqueId());
final PraxiPlayer targetPraxiPlayer = PraxiPlayer.getByUuid(target.getUniqueId());
if (senderPraxiPlayer.getRematchData() == null || targetPraxiPlayer.getRematchData() == null ||
!senderPraxiPlayer.getRematchData().getKey().equals(targetPraxiPlayer.getRematchData().getKey())) {
return;
}
if (senderPraxiPlayer.isBusy()) {
sender.sendMessage(Style.RED + "You cannot duel right now.");
return;
}
sender.sendMessage(Style.translate(
"&eYou sent a rematch request to &d" + target.getName() + " &eon arena &d" + this.arena.getName() +
"&e."));
target.sendMessage(Style.translate(
"&d" + sender.getName() + " &ehas sent you a rematch request on arena &d" + this.arena.getName() +
"&e."));
target.sendMessage(new ChatComponentBuilder("").parse("&6Click here or type &b/rematch &6to accept the invite.")
.attachToEachPart(HOVER_EVENT).attachToEachPart(CLICK_EVENT)
.create());
this.sent = true;
targetPraxiPlayer.getRematchData().receive = true;
senderPraxiPlayer.refreshHotbar();
targetPraxiPlayer.refreshHotbar();
}
public void accept() {
final Player sender = Praxi.getInstance().getServer().getPlayer(this.sender);
final Player target = Praxi.getInstance().getServer().getPlayer(this.target);
if (sender == null || target == null || !sender.isOnline() || !target.isOnline()) {
return;
}
final PraxiPlayer senderPraxiPlayer = PraxiPlayer.getByUuid(sender.getUniqueId());
final PraxiPlayer targetPraxiPlayer = PraxiPlayer.getByUuid(target.getUniqueId());
if (senderPraxiPlayer.getRematchData() == null || targetPraxiPlayer.getRematchData() == null ||
!senderPraxiPlayer.getRematchData().getKey().equals(targetPraxiPlayer.getRematchData().getKey())) {
return;
}
if (senderPraxiPlayer.isBusy()) {
sender.sendMessage(Style.RED + "You cannot duel right now.");
return;
}
if (targetPraxiPlayer.isBusy()) {
sender.sendMessage(NucleusAPI.getColoredName(target) + Style.RED + " is currently busy.");
return;
}
Arena arena = this.arena;
if (arena.isActive()) {
arena = Arena.getRandom(this.ladder);
}
if (arena == null) {
sender.sendMessage(Style.RED + "Tried to start a match but there are no available arenas.");
return;
}
arena.setActive(true);
Match match = new SoloMatch(new MatchPlayer(sender), new MatchPlayer(target), this.ladder, arena, false, true);
match.handleStart();
}
}

View File

@ -0,0 +1,151 @@
package me.joeleoli.praxi.player.gui;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.player.DefinedSetting;
import me.joeleoli.nucleus.player.NucleusPlayer;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TextSplitter;
import me.joeleoli.praxi.player.PracticeSetting;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class PlayerSettingsMenu extends Menu {
@Override
public String getTitle(Player player) {
return Style.PINK + Style.BOLD + "Your Settings";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
final Map<Integer, Button> buttons = new HashMap<>();
for (SettingInfo settingInfo : SettingInfo.values()) {
buttons.put(buttons.size(), new ToggleButton(settingInfo));
}
return buttons;
}
@AllArgsConstructor
private enum SettingInfo {
SCOREBOARD(
PracticeSetting.SHOW_SCOREBOARD,
Style.PINK + Style.BOLD + "Scoreboard",
"If enabled, information will be displayed on your side scoreboard.",
Material.ITEM_FRAME,
"Show your scoreboard",
"Hide your scoreboard"
),
SPECTATORS(
PracticeSetting.ALLOW_SPECTATORS,
Style.AQUA + Style.BOLD + "Spectators",
"If enabled, players can spectate your match with /spectate.",
Material.REDSTONE_TORCH_ON,
"Let players spectate your matches",
"Don't let players spectate your matches"
),
DUEL_REQUESTS(
PracticeSetting.RECEIVE_DUEL_REQUESTS,
Style.RED + Style.BOLD + "Duel Requests",
"If enabled, players can request you duel requests.",
Material.BLAZE_ROD,
"Let players request you duel requests",
"Don't let players request you duel requests"
),
GLOBAL_MESSAGES(
DefinedSetting.GlobalPlayerSetting.RECEIVE_GLOBAL_MESSAGES,
Style.GREEN + Style.BOLD + "Global Messages",
"If enabled, you will receive global chat messages.",
Material.BOOK_AND_QUILL,
"Receive global chat messages",
"Don't receive global chat message"
),
PRIVATE_MESSAGES(
DefinedSetting.GlobalPlayerSetting.RECEIVE_PRIVATE_MESSAGES,
Style.BLUE + Style.BOLD + "Private Messages",
"If enabled, you will receive private chat messages.",
Material.NAME_TAG,
"Receive private chat messages",
"Don't receive private chat message"
),
MESSAGE_SOUNDS(
DefinedSetting.GlobalPlayerSetting.PLAY_MESSAGE_SOUNDS,
Style.YELLOW + Style.BOLD + "Message Sounds",
"If enabled, you will be notified via sound when you receive private messages.",
Material.RECORD_7,
"Play message sounds",
"Don't play message sounds"
),
PING_FACTOR(
PracticeSetting.PING_FACTOR,
Style.DARK_PURPLE + Style.BOLD + "Ping Factor",
"If enabled, you will only be matched against players that have a similar ping to you.",
Material.EYE_OF_ENDER,
"Be matched against players with similar ping",
"Be matched against players with any ping"
);
private DefinedSetting setting;
private String title;
private String description;
private Material material;
private String enabledDescription;
private String disabledDescription;
public void toggle(Player player) {
final NucleusPlayer nucleusPlayer = NucleusPlayer.getByUuid(player.getUniqueId());
nucleusPlayer.getSettings().getSettings().put(this.setting, !this.get(player));
}
public boolean get(Player player) {
final NucleusPlayer nucleusPlayer = NucleusPlayer.getByUuid(player.getUniqueId());
return nucleusPlayer.getSettings().getBoolean(this.setting);
}
}
@AllArgsConstructor
private static class ToggleButton extends Button {
private SettingInfo settingInfo;
@Override
public ItemStack getButtonItem(Player player) {
final List<String> lore = new ArrayList<>();
lore.add("");
lore.addAll(TextSplitter.split(this.settingInfo.description, Style.YELLOW));
lore.add("");
lore.add(" " + (this.settingInfo.get(player) ? Style.GREEN + Style.UNICODE_ARROWS_RIGHT : " ") + " " +
Style.GOLD + this.settingInfo.enabledDescription);
lore.add(" " + (!this.settingInfo.get(player) ? Style.GREEN + Style.UNICODE_ARROWS_RIGHT : " ") + " " +
Style.GOLD + this.settingInfo.disabledDescription);
return new ItemBuilder(this.settingInfo.material)
.name(this.settingInfo.title)
.lore(lore)
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hbSlot) {
this.settingInfo.toggle(player);
}
@Override
public boolean shouldUpdate(Player player, int slot, ClickType clickType) {
return true;
}
}
}

View File

@ -0,0 +1,94 @@
package me.joeleoli.praxi.queue;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.function.Predicate;
import lombok.Getter;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.ladder.Ladder;
import me.joeleoli.praxi.player.PlayerState;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@Getter
public class Queue {
@Getter
private static List<Queue> queues = new ArrayList<>();
private UUID uuid = UUID.randomUUID();
private Ladder ladder;
private boolean ranked;
private LinkedList<QueuePlayer> players;
public Queue(Ladder ladder, boolean ranked) {
this.ladder = ladder;
this.ranked = ranked;
this.players = new LinkedList<>();
queues.add(this);
}
public static Queue getByUuid(UUID uuid) {
for (Queue queue : queues) {
if (queue.getUuid().equals(uuid)) {
return queue;
}
}
return null;
}
public static Queue getByPredicate(Predicate<Queue> predicate) {
for (Queue queue : queues) {
if (predicate.test(queue)) {
return queue;
}
}
return null;
}
public void addPlayer(Player player, int elo) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
final QueuePlayer queuePlayer = new QueuePlayer(this.uuid, player.getUniqueId());
if (this.ranked) {
queuePlayer.setElo(elo);
}
praxiPlayer.setState(PlayerState.IN_QUEUE);
praxiPlayer.setQueuePlayer(queuePlayer);
praxiPlayer.loadHotbar();
player.sendMessage(
Style.YELLOW + "You joined the " + Style.PINK + (this.ranked ? "Ranked" : "Unranked") + " " +
this.ladder.getName() + Style.YELLOW + " queue.");
this.players.add(queuePlayer);
}
public QueuePlayer removePlayer(QueuePlayer queuePlayer) {
this.players.remove(queuePlayer);
final Player player = Bukkit.getPlayer(queuePlayer.getPlayerUuid());
if (player != null && player.isOnline()) {
player.sendMessage(
Style.YELLOW + "You left the " + Style.PINK + (this.ranked ? "Ranked" : "Unranked") + " " +
this.ladder.getName() + Style.YELLOW + " queue.");
}
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(queuePlayer.getPlayerUuid());
praxiPlayer.setQueuePlayer(null);
praxiPlayer.setState(PlayerState.IN_LOBBY);
praxiPlayer.loadHotbar();
return queuePlayer;
}
}

View File

@ -0,0 +1,59 @@
package me.joeleoli.praxi.queue;
import java.util.UUID;
import lombok.Data;
@Data
public class QueuePlayer {
private UUID queueUuid;
private UUID playerUuid;
private int elo;
private int range = 25;
private long start = System.currentTimeMillis();
private int ticked;
public QueuePlayer(UUID queueUuid, UUID playerUuid) {
this.queueUuid = queueUuid;
this.playerUuid = playerUuid;
}
public void tickRange() {
this.ticked++;
if (this.ticked >= 20) {
this.range += 25;
this.ticked = 0;
}
}
public Queue getQueue() {
return Queue.getByUuid(this.queueUuid);
}
public boolean isInRange(int elo) {
return elo >= (this.elo - this.range) && elo <= (this.elo + this.range);
}
public long getPassed() {
return System.currentTimeMillis() - this.start;
}
public int getMinRange() {
int min = this.elo - this.range;
return min < 0 ? 0 : min;
}
public int getMaxRange() {
int max = this.elo + this.range;
return max > 2500 ? 2500 : max;
}
@Override
public boolean equals(Object o) {
return o instanceof QueuePlayer && ((QueuePlayer) o).getPlayerUuid().equals(this.playerUuid);
}
}

View File

@ -0,0 +1,135 @@
package me.joeleoli.praxi.queue;
import me.joeleoli.nucleus.NucleusAPI;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.nucleus.util.TaskUtil;
import me.joeleoli.praxi.arena.Arena;
import me.joeleoli.praxi.match.Match;
import me.joeleoli.praxi.match.MatchPlayer;
import me.joeleoli.praxi.match.impl.SoloMatch;
import me.joeleoli.praxi.player.PracticeSetting;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class QueueThread extends Thread {
@Override
public void run() {
while (true) {
try {
for (Queue queue : Queue.getQueues()) {
queue.getPlayers().forEach(QueuePlayer::tickRange);
if (queue.getPlayers().size() < 2) {
continue;
}
for (QueuePlayer firstQueuePlayer : queue.getPlayers()) {
final Player firstPlayer = Bukkit.getPlayer(firstQueuePlayer.getPlayerUuid());
if (firstPlayer == null) {
continue;
}
final PraxiPlayer firstPraxiPlayer = PraxiPlayer.getByUuid(firstQueuePlayer.getPlayerUuid());
for (QueuePlayer secondQueuePlayer : queue.getPlayers()) {
if (firstQueuePlayer.equals(secondQueuePlayer)) {
continue;
}
final Player secondPlayer = Bukkit.getPlayer(secondQueuePlayer.getPlayerUuid());
final PraxiPlayer secondPraxiPlayer =
PraxiPlayer.getByUuid(secondQueuePlayer.getPlayerUuid());
if (secondPlayer == null) {
continue;
}
if (NucleusAPI.<Boolean>getSetting(firstPlayer, PracticeSetting.PING_FACTOR) ||
NucleusAPI.<Boolean>getSetting(secondPlayer, PracticeSetting.PING_FACTOR)) {
if (firstPlayer.getPing() >= secondPlayer.getPing()) {
if (firstPlayer.getPing() - secondPlayer.getPing() >= 50) {
continue;
}
} else {
if (secondPlayer.getPing() - firstPlayer.getPing() >= 50) {
continue;
}
}
}
if (queue.isRanked()) {
if (!firstQueuePlayer.isInRange(secondQueuePlayer.getElo()) ||
!secondQueuePlayer.isInRange(firstQueuePlayer.getElo())) {
continue;
}
}
// Find arena
final Arena arena = Arena.getRandom(queue.getLadder());
if (arena == null) {
continue;
}
// Update arena
arena.setActive(true);
// Remove players from queue
queue.getPlayers().remove(firstQueuePlayer);
queue.getPlayers().remove(secondQueuePlayer);
final MatchPlayer firstMatchPlayer = new MatchPlayer(firstPlayer);
final MatchPlayer secondMatchPlayer = new MatchPlayer(secondPlayer);
if (queue.isRanked()) {
firstMatchPlayer.setElo(firstPraxiPlayer.getStatistics().getElo(queue.getLadder()));
secondMatchPlayer.setElo(secondPraxiPlayer.getStatistics().getElo(queue.getLadder()));
}
// Create match
final Match match = new SoloMatch(queue.getUuid(), firstMatchPlayer, secondMatchPlayer,
queue.getLadder(), arena, queue.isRanked(), false
);
final String[] opponentMessages =
this.formatOpponentMessages(firstPlayer.getName(), secondPlayer.getName(),
firstMatchPlayer.getElo(), secondMatchPlayer.getElo(), queue.isRanked()
);
firstPlayer.sendMessage(opponentMessages[0]);
secondPlayer.sendMessage(opponentMessages[1]);
TaskUtil.run(match::handleStart);
}
}
}
} catch (Exception e) {
e.printStackTrace();
continue;
}
try {
Thread.sleep(200L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private String[] formatOpponentMessages(String player1, String player2, int player1Elo, int player2Elo,
boolean ranked) {
final String player1Format = player1 + (ranked ? Style.GRAY + " (" + player1Elo + ")" : "");
final String player2Format = player2 + (ranked ? Style.GRAY + " (" + player2Elo + ")" : "");
return new String[]{
Style.YELLOW + Style.BOLD + "Found opponent: " + Style.GREEN + player1Format + Style.PINK + " vs. " +
Style.RED + player2Format,
Style.YELLOW + Style.BOLD + "Found opponent: " + Style.GREEN + player2Format + Style.PINK + " vs. " +
Style.RED + player1Format
};
}
}

View File

@ -0,0 +1,92 @@
package me.joeleoli.praxi.queue.gui;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import me.joeleoli.nucleus.NucleusAPI;
import me.joeleoli.nucleus.menu.Button;
import me.joeleoli.nucleus.menu.Menu;
import me.joeleoli.nucleus.util.ItemBuilder;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.player.PraxiPlayer;
import me.joeleoli.praxi.queue.Queue;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
@AllArgsConstructor
public class QueueJoinMenu extends Menu {
private boolean ranked;
@Override
public String getTitle(Player player) {
return Style.GOLD + "Join " + (this.ranked ? "Ranked" : "Unranked") + " Queue";
}
@Override
public Map<Integer, Button> getButtons(Player player) {
Map<Integer, Button> buttons = new HashMap<>();
int i = 0;
for (Queue queue : Queue.getQueues()) {
if (queue.isRanked() == this.ranked) {
buttons.put(i++, new SelectLadderButton(queue));
}
}
return buttons;
}
@AllArgsConstructor
private class SelectLadderButton extends Button {
private Queue queue;
@Override
public ItemStack getButtonItem(Player player) {
final List<String> lore = new ArrayList<>();
lore.add(Style.YELLOW + "Fighting: " + Style.RESET + Praxi.getInstance().getFightingCount(this.queue));
lore.add(Style.YELLOW + "Queueing: " + Style.RESET + this.queue.getPlayers().size());
lore.add("");
lore.add(Style.YELLOW + "Click here to select " + Style.PINK + Style.BOLD +
this.queue.getLadder().getName() + Style.YELLOW + ".");
return new ItemBuilder(this.queue.getLadder().getDisplayIcon())
.name(Style.PINK + Style.BOLD + this.queue.getLadder().getName()).lore(lore)
.build();
}
@Override
public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if (praxiPlayer == null) {
return;
}
if (NucleusAPI.isFrozen(player)) {
player.sendMessage(Style.RED + "You cannot queue while frozen.");
return;
}
if (praxiPlayer.isBusy()) {
player.sendMessage(Style.RED + "You cannot queue right now.");
return;
}
player.closeInventory();
this.queue.addPlayer(
player,
!this.queue.isRanked() ? 0 : praxiPlayer.getStatistics().getElo(this.queue.getLadder())
);
}
}
}

View File

@ -0,0 +1,37 @@
package me.joeleoli.praxi.task;
import me.joeleoli.nucleus.util.Style;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Player;
public class ExpBarCooldownTask implements Runnable {
@Override
public void run() {
for (Player player : Praxi.getInstance().getServer().getOnlinePlayers()) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
if ((praxiPlayer.isInMatch() || praxiPlayer.isInEvent()) && !praxiPlayer.getEnderpearlCooldown().hasExpired()) {
int seconds = Math.round(praxiPlayer.getEnderpearlCooldown().getRemaining()) / 1_000;
player.setLevel(seconds);
player.setExp(praxiPlayer.getEnderpearlCooldown().getRemaining() / 16_000.0F);
} else {
if (!praxiPlayer.getEnderpearlCooldown().isNotified()) {
player.sendMessage(Style.PINK + "Your pearl cooldown has expired.");
praxiPlayer.getEnderpearlCooldown().setNotified(true);
}
if (player.getLevel() > 0) {
player.setLevel(0);
}
if (player.getExp() > 0.0F) {
player.setExp(0.0F);
}
}
}
}
}

View File

@ -0,0 +1,13 @@
package me.joeleoli.praxi.task;
import me.joeleoli.praxi.match.MatchSnapshot;
public class InventoryCleanupTask implements Runnable {
@Override
public void run() {
MatchSnapshot.getCache().entrySet()
.removeIf(entry -> System.currentTimeMillis() - entry.getValue().getCreated() >= 45_000);
}
}

View File

@ -0,0 +1,13 @@
package me.joeleoli.praxi.task;
import me.joeleoli.praxi.party.Party;
public class InviteCleanupTask implements Runnable {
@Override
public void run() {
Party.getParties().forEach(party -> party.getInvited().entrySet().removeIf(
entry -> System.currentTimeMillis() >= entry.getValue() + 30_000));
}
}

View File

@ -0,0 +1,18 @@
package me.joeleoli.praxi.task;
import me.joeleoli.praxi.Praxi;
import me.joeleoli.praxi.player.PraxiPlayer;
import org.bukkit.entity.Player;
public class RematchExpireRunnable implements Runnable {
@Override
public void run() {
for (Player player : Praxi.getInstance().getServer().getOnlinePlayers()) {
final PraxiPlayer praxiPlayer = PraxiPlayer.getByUuid(player.getUniqueId());
praxiPlayer.refreshHotbar();
}
}
}

View File

@ -0,0 +1,14 @@
package me.joeleoli.praxi.task;
import me.joeleoli.praxi.player.PraxiPlayer;
public class SaveDataTask implements Runnable {
@Override
public void run() {
for (PraxiPlayer praxiPlayer : PraxiPlayer.getPlayers().values()) {
praxiPlayer.save();
}
}
}

View File

View File

@ -0,0 +1,9 @@
mongo:
host: "127.0.0.1"
port: 27017
database: "praxi"
authentication:
enabled: false
username: "admin"
password: "dev"
database: "admin"

Some files were not shown because too many files have changed in this diff Show More