* Created at 28.04.2019
*/
public class HookManager {
//todo implement in minigamescore as bb citiziens could benefit from too
private final Map hooks = new EnumMap<>(HookFeature.class);
private final Main plugin;
public HookManager(Main plugin) {
this.plugin = plugin;
enableHooks();
}
private void enableHooks() {
for(HookFeature feature : HookFeature.values()) {
boolean hooked = true;
for(Hook requiredHook : feature.getRequiredHooks()) {
if(!Bukkit.getPluginManager().isPluginEnabled(requiredHook.getPluginName())) {
hooks.put(feature, false);
plugin.getDebugger().debug("[HookManager] Feature {0} won't be enabled because " + requiredHook.getPluginName() + " is not installed! Please install it in order to enable this feature in-game!",
feature.name());
hooked = false;
break;
}
}
if(hooked) {
hooks.put(feature, true);
plugin.getDebugger().debug("[HookManager] Feature {0} enabled!", feature.name());
}
}
}
public boolean isFeatureEnabled(HookFeature feature) {
return hooks.getOrDefault(feature, false);
}
public enum HookFeature {
CORPSES(Hook.CORPSE_REBORN);
private final Hook[] requiredHooks;
HookFeature(Hook... requiredHooks) {
this.requiredHooks = requiredHooks;
}
public Hook[] getRequiredHooks() {
return requiredHooks;
}
}
public enum Hook {
CORPSE_REBORN("CorpseReborn");
private final String pluginName;
Hook(String pluginName) {
this.pluginName = pluginName;
}
public String getPluginName() {
return pluginName;
}
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/Main.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery;
import org.jetbrains.annotations.TestOnly;
import plugily.projects.minigamesbox.classic.PluginMain;
import plugily.projects.minigamesbox.classic.handlers.setup.SetupInventory;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginSetupCategoryManager;
import plugily.projects.minigamesbox.classic.utils.services.metrics.Metrics;
import plugily.projects.murdermystery.arena.*;
import plugily.projects.murdermystery.arena.special.SpecialBlockEvents;
import plugily.projects.murdermystery.arena.special.mysterypotion.MysteryPotionRegistry;
import plugily.projects.murdermystery.arena.special.pray.PrayerRegistry;
import plugily.projects.murdermystery.boot.AdditionalValueInitializer;
import plugily.projects.murdermystery.boot.MessageInitializer;
import plugily.projects.murdermystery.boot.PlaceholderInitializer;
import plugily.projects.murdermystery.commands.arguments.ArgumentsRegistry;
import plugily.projects.murdermystery.events.PluginEvents;
import plugily.projects.murdermystery.handlers.CorpseHandler;
import plugily.projects.murdermystery.handlers.lastwords.LastWordsManager;
import plugily.projects.murdermystery.handlers.setup.SetupCategoryManager;
import plugily.projects.murdermystery.handlers.skins.sword.SwordSkinManager;
import plugily.projects.murdermystery.handlers.trails.BowTrailsHandler;
import plugily.projects.murdermystery.handlers.trails.TrailsManager;
/**
* Created by Tigerpanzer_02 on 13.03.2022
*/
public class Main extends PluginMain {
private ArenaRegistry arenaRegistry;
private ArenaManager arenaManager;
private ArgumentsRegistry argumentsRegistry;
private LastWordsManager lastWordsManager;
private TrailsManager trailsManager;
private SwordSkinManager swordSkinManager;
private HookManager hookManager;
private CorpseHandler corpseHandler;
@TestOnly
public Main() {
super();
}
@Override
public void onEnable() {
long start = System.currentTimeMillis();
MessageInitializer messageInitializer = new MessageInitializer(this);
super.onEnable();
getDebugger().debug("[System] [Plugin] Initialization start");
arenaRegistry = new ArenaRegistry(this);
new PlaceholderInitializer(this);
messageInitializer.registerMessages();
new AdditionalValueInitializer(this);
initializePluginClasses();
if(getConfigPreferences().getOption("HIDE_NAMETAGS")) {
getServer().getScheduler().scheduleSyncRepeatingTask(this, () ->
getServer().getOnlinePlayers().forEach(ArenaUtils::updateNameTagsVisibility), 60, 140);
}
getDebugger().debug("Full {0} plugin enabled", getName());
getDebugger()
.debug(
"[System] [Plugin] Initialization finished took {0}ms",
System.currentTimeMillis() - start);
}
public void initializePluginClasses() {
addFileName("lastwords");
addFileName("powerups");
addFileName("skins");
addFileName("special_blocks");
addFileName("trails");
Arena.init(this);
ArenaUtils.init(this);
new ArenaEvents(this);
arenaManager = new ArenaManager(this);
arenaRegistry.registerArenas();
getSignManager().loadSigns();
getSignManager().updateSigns();
argumentsRegistry = new ArgumentsRegistry(this);
lastWordsManager = new LastWordsManager(this);
new BowTrailsHandler(this);
MysteryPotionRegistry.init(this);
PrayerRegistry.init(this);
new SpecialBlockEvents(this);
trailsManager = new TrailsManager(this);
hookManager = new HookManager(this);
corpseHandler = new CorpseHandler(this);
swordSkinManager = new SwordSkinManager(this);
new PluginEvents(this);
addPluginMetrics();
}
private void addPluginMetrics() {
getMetrics()
.addCustomChart(
new Metrics.SimplePie(
"hooked_addons",
() -> {
if(getServer().getPluginManager().getPlugin("MurderMystery-Extension") != null) {
return "Extension";
}
return "None";
}));
}
@Override
public ArenaRegistry getArenaRegistry() {
return arenaRegistry;
}
@Override
public ArgumentsRegistry getArgumentsRegistry() {
return argumentsRegistry;
}
@Override
public ArenaManager getArenaManager() {
return arenaManager;
}
public LastWordsManager getLastWordsManager() {
return lastWordsManager;
}
public TrailsManager getTrailsManager() {
return trailsManager;
}
public SwordSkinManager getSwordSkinManager() {
return swordSkinManager;
}
public HookManager getHookManager() {
return hookManager;
}
public CorpseHandler getCorpseHandler() {
return corpseHandler;
}
@Override
public PluginSetupCategoryManager getSetupCategoryManager(SetupInventory setupInventory) {
return new SetupCategoryManager(setupInventory);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/api/events/game/MurderGameCorpseSpawnEvent.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.api.events.game;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import plugily.projects.minigamesbox.api.events.PlugilyEvent;
import plugily.projects.murdermystery.arena.Arena;
/**
* @author Tigerpanzer_02
*
* Created at 15.04.2022
*/
public class MurderGameCorpseSpawnEvent extends PlugilyEvent implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
private boolean isCancelled = false;
private final Player player;
private final Location location;
public MurderGameCorpseSpawnEvent(Arena arena, Player player, Location location) {
super(arena);
this.player = player;
this.location = location;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancelled) {
isCancelled = cancelled;
}
public Player getPlayer() {
return player;
}
public Location getLocation() {
return location;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/api/events/game/package-info.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/**
* All in-game related events.
*/
package plugily.projects.murdermystery.api.events.game;
================================================
FILE: src/main/java/plugily/projects/murdermystery/api/events/player/package-info.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* Murder Mystery is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Murder Mystery is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Murder Mystery. If not, see .
*/
/**
* All in-game player related events.
*/
package plugily.projects.murdermystery.api.events.player;
================================================
FILE: src/main/java/plugily/projects/murdermystery/api/package-info.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/**
* Package with all API events and methods to hook with Murder Mystery.
*/
package plugily.projects.murdermystery.api;
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/Arena.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.managers.PluginMapRestorerManager;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.murdermystery.HookManager;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.corpse.Corpse;
import plugily.projects.murdermystery.arena.corpse.Stand;
import plugily.projects.murdermystery.arena.managers.MapRestorerManager;
import plugily.projects.murdermystery.arena.managers.ScoreboardManager;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.arena.special.SpecialBlock;
import plugily.projects.murdermystery.arena.states.InGameState;
import plugily.projects.murdermystery.arena.states.RestartingState;
import plugily.projects.murdermystery.arena.states.StartingState;
import plugily.projects.murdermystery.arena.states.WaitingState;
import java.util.*;
/**
* @author Tigerpanzer_02
*
* Created at 17.12.2021
*/
public class Arena extends PluginArena {
private static Main plugin;
private final List spectators = new ArrayList<>();
private final List deaths = new ArrayList<>();
private final List detectives = new ArrayList<>();
private final List murderers = new ArrayList<>();
private final List goldSpawned = new ArrayList<>();
private final List corpses = new ArrayList<>();
private final List stands = new ArrayList<>();
private final List specialBlocks = new ArrayList<>();
private List goldSpawnPoints = new ArrayList<>();
private List playerSpawnPoints = new ArrayList<>();
private int spawnGoldTimer = 0;
private int spawnGoldTime = 0;
private boolean detectiveDead;
private boolean murdererLocatorReceived;
private boolean hideChances;
private boolean goldVisuals = false;
private final Map gameCharacters = new EnumMap<>(CharacterType.class);
private final MapRestorerManager mapRestorerManager;
private ArmorStandHologram bowHologram;
public Arena(String id) {
super(id);
setPluginValues();
setScoreboardManager(new ScoreboardManager(this));
mapRestorerManager = new MapRestorerManager(this);
setMapRestorerManager(mapRestorerManager);
addGameStateHandler(IArenaState.IN_GAME, new InGameState());
addGameStateHandler(IArenaState.RESTARTING, new RestartingState());
addGameStateHandler(IArenaState.STARTING, new StartingState());
addGameStateHandler(IArenaState.WAITING_FOR_PLAYERS, new WaitingState());
}
public static void init(Main plugin) {
Arena.plugin = plugin;
}
@Override
public Main getPlugin() {
return plugin;
}
@Override
public PluginMapRestorerManager getMapRestorerManager() {
return mapRestorerManager;
}
private void setPluginValues() {
}
public void addCorpse(Corpse corpse) {
if(plugin.getHookManager().isFeatureEnabled(HookManager.HookFeature.CORPSES)) {
corpses.add(corpse);
}
}
public List getCorpses() {
return corpses;
}
public List getStands() {
return stands;
}
public void addHead(Stand stand) {
stands.add(stand);
}
public void setSpawnGoldTime(int spawnGoldTime) {
this.spawnGoldTime = spawnGoldTime;
}
public void setHideChances(boolean hideChances) {
this.hideChances = hideChances;
}
public boolean isDetectiveDead() {
return detectiveDead;
}
public void setDetectiveDead(boolean detectiveDead) {
this.detectiveDead = detectiveDead;
}
public boolean isMurdererLocatorReceived() {
return murdererLocatorReceived;
}
public void setMurdererLocatorReceived(boolean murdererLocatorReceived) {
this.murdererLocatorReceived = murdererLocatorReceived;
}
public Map getGameCharacters() {
return gameCharacters;
}
public boolean isHideChances() {
return hideChances;
}
@NotNull
public List getGoldSpawned() {
return goldSpawned;
}
@NotNull
public List getGoldSpawnPoints() {
return goldSpawnPoints;
}
public void setGoldSpawnPoints(@NotNull List goldSpawnPoints) {
this.goldSpawnPoints = goldSpawnPoints;
}
private BukkitTask visualTask;
public void startGoldVisuals() {
if(visualTask != null) {
return;
}
visualTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
if(!goldVisuals || !plugin.isEnabled() || goldSpawnPoints.isEmpty() || getArenaState() != IArenaState.WAITING_FOR_PLAYERS) {
//we need to cancel it that way as the arena class is an task
visualTask.cancel();
return;
}
for(Location goldLocations : goldSpawnPoints) {
Location goldLocation = goldLocations.clone();
goldLocation.add(0, 0.4, 0);
Bukkit.getOnlinePlayers().forEach(player -> VersionUtils.sendParticles("REDSTONE", player, goldLocation, 10));
}
}, 20L, 20L);
}
public boolean isGoldVisuals() {
return goldVisuals;
}
public void setGoldVisuals(boolean goldVisuals) {
this.goldVisuals = goldVisuals;
if(goldVisuals) {
startGoldVisuals();
}
}
public void loadSpecialBlock(SpecialBlock block) {
if(!specialBlocks.contains(block)) {
specialBlocks.add(block);
}
switch(block.getSpecialBlockType()) {
case MYSTERY_CAULDRON:
block.setArmorStandHologram(new ArmorStandHologram(plugin.getBukkitHelper().getBlockCenter(block.getLocation()), new MessageBuilder(plugin.getLanguageManager().getLanguageMessage("In-Game.Messages.Arena.Playing.Special-Blocks.Cauldron.Hologram")).build()));
break;
case PRAISE_DEVELOPER:
ArmorStandHologram prayer = new ArmorStandHologram(plugin.getBukkitHelper().getBlockCenter(block.getLocation()));
for(String str : plugin.getLanguageManager().getLanguageMessage("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Hologram").split(";")) {
prayer.appendLine(new MessageBuilder(str).build());
}
block.setArmorStandHologram(prayer);
break;
case HORSE_PURCHASE:
case RAPID_TELEPORTATION:
//not yet implemented
default:
break;
}
}
public List getSpecialBlocks() {
return specialBlocks;
}
public int getTotalRoleChances(Role role) {
int totalRoleChances = 0;
for(Player p : getPlayersLeft()) {
IUser user = getPlugin().getUserManager().getUser(p);
totalRoleChances += getContributorValue(role, user);
}
//avoid division / 0
return totalRoleChances == 0 ? 1 : totalRoleChances;
}
public boolean isCharacterSet(Arena.CharacterType type) {
return gameCharacters.containsKey(type);
}
public void setCharacter(Arena.CharacterType type, Player player) {
gameCharacters.put(type, player);
}
public void setCharacter(Role role, Player player) {
gameCharacters.put(role == Role.MURDERER ? CharacterType.MURDERER : CharacterType.DETECTIVE, player);
}
@Nullable
public Player getCharacter(Arena.CharacterType type) {
return gameCharacters.get(type);
}
public void addToDetectiveList(Player player) {
detectives.add(player);
}
public boolean lastAliveDetective() {
return aliveDetective() <= 1;
}
public int aliveDetective() {
int alive = 0;
for(Player player : getPlayersLeft()) {
if(Role.isRole(Role.ANY_DETECTIVE, plugin.getUserManager().getUser(player), this) && isDetectiveAlive(player)) {
alive++;
}
}
return alive;
}
public boolean isDetectiveAlive(Player player) {
for(Player p : getPlayersLeft()) {
if(p == player && detectives.contains(p)) {
return true;
}
}
return false;
}
public List getDetectiveList() {
return detectives;
}
public void addToMurdererList(Player player) {
murderers.add(player);
}
public void removeFromMurdererList(Player player) {
murderers.remove(player);
}
public boolean lastAliveMurderer() {
return aliveMurderer() == 1;
}
public int aliveMurderer() {
int alive = 0;
for(Player player : getPlayersLeft()) {
if(Role.isRole(Role.MURDERER, plugin.getUserManager().getUser(player), this) && isMurderAlive(player)) {
alive++;
}
}
return alive;
}
public boolean isMurderAlive(Player player) {
for(Player p : getPlayersLeft()) {
if(p == player && murderers.contains(p)) {
return true;
}
}
return false;
}
public List getMurdererList() {
return murderers;
}
public void setBowHologram(ArmorStandHologram bowHologram) {
if(bowHologram == null) {
this.bowHologram = null;
return;
}
this.bowHologram = bowHologram;
}
public ArmorStandHologram getBowHologram() {
return bowHologram;
}
public void addDeathPlayer(Player player) {
deaths.add(player);
}
public void removeDeathPlayer(Player player) {
deaths.remove(player);
}
public boolean isDeathPlayer(Player player) {
return deaths.contains(player);
}
public List getDeaths() {
return deaths;
}
public void addSpectatorPlayer(Player player) {
spectators.add(player);
}
public void removeSpectatorPlayer(Player player) {
spectators.remove(player);
}
public boolean isSpectatorPlayer(Player player) {
return spectators.contains(player);
}
public List getPlayerSpawnPoints() {
return playerSpawnPoints;
}
public int getSpawnGoldTime() {
return spawnGoldTime;
}
public int getSpawnGoldTimer() {
return spawnGoldTimer;
}
public void setSpawnGoldTimer(int spawnGoldTimer) {
this.spawnGoldTimer = spawnGoldTimer;
}
public void setPlayerSpawnPoints(@NotNull List playerSpawnPoints) {
this.playerSpawnPoints = playerSpawnPoints;
}
public void adjustContributorValue(Role role, IUser user, int number) {
user.adjustStatistic("CONTRIBUTION_" + role.name(), number);
}
private final Map murdererContributions = new HashMap<>();
private final Map detectiveContributions = new HashMap<>();
public Map getMurdererContributions() {
return murdererContributions;
}
public Map getDetectiveContributions() {
return detectiveContributions;
}
public int getContributorValue(Role role, IUser user) {
if(role == Role.MURDERER && murdererContributions.containsKey(user)) {
return murdererContributions.get(user);
} else if(detectiveContributions.containsKey(user)) {
return detectiveContributions.get(user);
}
Player player = user.getPlayer();
int contributor = user.getStatistic("CONTRIBUTION_" + role.name());
int increase = plugin.getPermissionsManager().getPermissionCategoryValue(role.name() + "_BOOSTER", player);
int multiplicator = plugin.getPermissionsManager().getPermissionCategoryValue("CHANCES_BOOSTER", player);
int calculatedContributor = (contributor + increase) * (multiplicator == 0 ? 1 :multiplicator);
if(role == Role.MURDERER) {
murdererContributions.put(user, calculatedContributor);
} else {
detectiveContributions.put(user, calculatedContributor);
}
return calculatedContributor;
}
public void resetContributorValue(Role role, IUser user) {
user.setStatistic("CONTRIBUTION_" + role.name(), 1);
}
public enum CharacterType {
MURDERER, DETECTIVE, FAKE_DETECTIVE, HERO
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/ArenaEvents.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.potion.PotionEffectType;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArenaEvents;
import plugily.projects.minigamesbox.classic.handlers.items.SpecialItem;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.utils.misc.complement.ComplementAccessor;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.events.api.PlugilyEntityPickupItemEvent;
import plugily.projects.minigamesbox.classic.utils.version.events.api.PlugilyPlayerPickupArrow;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XPotion;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import plugily.projects.minigamesbox.classic.utils.version.xseries.inventory.XInventoryView;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.managers.MapRestorerManager;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.arena.special.pray.PrayerRegistry;
import plugily.projects.murdermystery.utils.ItemPosition;
/**
* @author Plajer
*
Created at 13.03.2018
*/
public class ArenaEvents extends PluginArenaEvents {
private final Main plugin;
public ArenaEvents(Main plugin) {
super(plugin);
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@Override
public void handleIngameVoidDeath(Player victim, IPluginArena arena) {
Arena pluginArena = plugin.getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
victim.damage(1000.0);
if(arena.getArenaState() == IArenaState.IN_GAME) {
VersionUtils.teleport(victim, pluginArena.getPlayerSpawnPoints().get(0));
}
}
@EventHandler
public void onBowShot(EntityShootBowEvent event) {
if(event.getEntityType() != EntityType.PLAYER) {
return;
}
Player player = (Player) event.getEntity();
IUser user = plugin.getUserManager().getUser(player);
if(!Role.isRole(Role.ANY_DETECTIVE, user)) {
return;
}
if(user.getCooldown("bow_shot") > 0) {
event.setCancelled(true);
return;
}
int bowCooldown = plugin.getConfig().getInt("Bow.Cooldown", 5);
if(bowCooldown <= 0) {
return;
}
user.setCooldown("bow_shot", bowCooldown);
plugin.getBukkitHelper().applyActionBarCooldown(player, bowCooldown);
VersionUtils.setMaterialCooldown(player, event.getBow().getType(), 20 * (plugin.getConfig().getInt("Bow.Cooldown", 5)));
}
@EventHandler
public void onArrowPickup(PlugilyPlayerPickupArrow e) {
if(plugin.getArenaRegistry().isInArena(e.getPlayer())) {
e.getItem().remove();
e.setCancelled(true);
}
}
@EventHandler
public void onItemPickup(PlugilyEntityPickupItemEvent e) {
if(!(e.getEntity() instanceof Player)) {
return;
}
Player player = (Player) e.getEntity();
Arena arena = plugin.getArenaRegistry().getArena(player);
if(arena == null) {
return;
}
IUser user = plugin.getUserManager().getUser(player);
e.setCancelled(true);
if(arena.getBowHologram() != null
&& e.getItem().equals(arena.getBowHologram().getEntityItem())) {
if(!user.isSpectator() && Role.isRole(Role.INNOCENT, user, arena)) {
XSound.BLOCK_LAVA_POP.play(player.getLocation(), 1F, 2F);
((MapRestorerManager) arena.getMapRestorerManager()).removeBowHolo();
e.getItem().remove();
for(Player loopPlayer : arena.getPlayersLeft()) {
IUser loopUser = plugin.getUserManager().getUser(loopPlayer);
if(Role.isRole(Role.INNOCENT, loopUser)) {
ItemPosition.setItem(loopUser, ItemPosition.BOW_LOCATOR, new ItemStack(Material.AIR, 1));
}
}
arena.setCharacter(Arena.CharacterType.FAKE_DETECTIVE, player);
ItemPosition.setItem(user, ItemPosition.BOW, new ItemStack(Material.BOW, 1));
ItemPosition.setItem(user, ItemPosition.INFINITE_ARROWS, new ItemStack(Material.ARROW, plugin.getConfig().getInt("Bow.Amount.Arrows.Fake", 3)));
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_BOW_PICKUP").asKey().player(player).arena(arena).sendArena();
}
return;
}
if(e.getItem().getItemStack().getType() != Material.GOLD_INGOT) {
return;
}
if(user.isSpectator() || arena.getArenaState() != IArenaState.IN_GAME) {
return;
}
if(PrayerRegistry.getBan().contains(player)) {
e.setCancelled(true);
return;
}
e.getItem().remove();
XSound.BLOCK_LAVA_POP.play(player.getLocation(), 1, 1);
arena.getGoldSpawned().remove(e.getItem());
ItemStack stack = new ItemStack(Material.GOLD_INGOT, e.getItem().getItemStack().getAmount());
if(PrayerRegistry.getRush().contains(player)) {
stack.setAmount(3 * e.getItem().getItemStack().getAmount());
}
ItemPosition.addItem(user, ItemPosition.GOLD_INGOTS, stack);
user.adjustStatistic("LOCAL_GOLD", stack.getAmount());
ArenaUtils.addScore(user, ArenaUtils.ScoreAction.GOLD_PICKUP, stack.getAmount());
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_GOLD").asKey().player(player).arena(arena).sendPlayer();
plugin.getRewardsHandler().performReward(player, plugin.getRewardsHandler().getRewardType("GOLD_PICKUP"));
if(Role.isRole(Role.ANY_DETECTIVE, user, arena)) {
ItemPosition.addItem(user, ItemPosition.ARROWS, new ItemStack(Material.ARROW, e.getItem().getItemStack().getAmount() * plugin.getConfig().getInt("Bow.Amount.Arrows.Detective", 3)));
return;
}
if(user.getStatistic("LOCAL_GOLD") >= plugin.getConfig().getInt("Gold.Amount.Bow", 10)) {
user.setStatistic("LOCAL_GOLD", 0);
new TitleBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_BOW_SHOT_TITLE")
.asKey()
.player(player)
.arena(arena)
.sendPlayer();
ItemPosition.setItem(user, ItemPosition.BOW, new ItemStack(Material.BOW, 1));
ItemPosition.addItem(
user,
ItemPosition.ARROWS,
new ItemStack(Material.ARROW, plugin.getConfig().getInt("Bow.Amount.Arrows.Gold", 3)));
player
.getInventory()
.setItem(
/* same for all roles */ ItemPosition.GOLD_INGOTS.getOtherRolesItemPosition(),
null);
}
}
@EventHandler
public void onMurdererDamage(EntityDamageByEntityEvent e) {
if(!(e.getDamager() instanceof Player) || e.getEntityType() != EntityType.PLAYER) {
return;
}
Player attacker = (Player) e.getDamager();
IUser userAttacker = plugin.getUserManager().getUser(attacker);
Player victim = (Player) e.getEntity();
IUser userVictim = plugin.getUserManager().getUser(victim);
if(!ArenaUtils.areInSameArena(attacker, victim)) {
return;
}
//we are killing player via damage() method so event can be cancelled safely, will work for detective damage murderer and others
e.setCancelled(true);
//better check this for future even if anyone else cannot use sword
if(!Role.isRole(Role.MURDERER, userAttacker)) {
return;
}
//check if victim is murderer
if(Role.isRole(Role.MURDERER, userVictim)) {
return;
}
if(VersionUtils.getItemInHand(attacker) == null || plugin.getSwordSkinManager().getMurdererSword(attacker) == null) {
return;
}
//just don't kill user if item isn't murderer sword
if(VersionUtils.getItemInHand(attacker).getType() != plugin.getSwordSkinManager().getMurdererSword(attacker).getType()) {
return;
}
//check if sword has cooldown
if(ServerVersion.Version.isCurrentLower(ServerVersion.Version.v1_11)) {
if(plugin.getUserManager().getUser(attacker).getCooldown("sword_attack") > 0) {
return;
}
} else if(attacker.hasCooldown(plugin.getSwordSkinManager().getMurdererSword(attacker).getType())) {
return;
}
if(Role.isRole(Role.MURDERER, userVictim)) {
plugin.getRewardsHandler().performReward(attacker, plugin.getRewardsHandler().getRewardType("KILL_MURDERER"));
} else if(Role.isRole(Role.ANY_DETECTIVE, userVictim)) {
plugin.getRewardsHandler().performReward(attacker, plugin.getRewardsHandler().getRewardType("KILL_DETECTIVE"));
}
XSound.ENTITY_PLAYER_DEATH.play(victim.getLocation());
victim.damage(100.0);
IUser user = plugin.getUserManager().getUser(attacker);
user.adjustStatistic("KILLS", 1);
user.adjustStatistic("LOCAL_KILLS", 1);
ArenaUtils.addScore(user, ArenaUtils.ScoreAction.KILL_PLAYER, 0);
Arena arena = plugin.getArenaRegistry().getArena(attacker);
if(Role.isRole(Role.ANY_DETECTIVE, userVictim) && arena.lastAliveDetective()) {
//if already true, no effect is done :)
arena.setDetectiveDead(true);
if(Role.isRole(Role.FAKE_DETECTIVE, userVictim)) {
arena.setCharacter(Arena.CharacterType.FAKE_DETECTIVE, null);
}
ArenaUtils.dropBowAndAnnounce(arena, victim);
}
}
@EventHandler
public void onArrowDamage(EntityDamageByEntityEvent e) {
if(!(e.getDamager() instanceof Arrow)) {
return;
}
if(!(((Arrow) e.getDamager()).getShooter() instanceof Player)) {
return;
}
Player attacker = (Player) ((Arrow) e.getDamager()).getShooter();
IUser userAttacker = plugin.getUserManager().getUser(attacker);
if(plugin.getArenaRegistry().isInArena(attacker)) {
e.setCancelled(true);
e.getDamager().remove();
}
if(e.getEntityType() != EntityType.PLAYER) {
return;
}
Player victim = (Player) e.getEntity();
IUser userVictim = plugin.getUserManager().getUser(victim);
if(!ArenaUtils.areInSameArena(attacker, victim)) {
return;
}
//we won't allow to suicide
if(attacker.equals(victim)) {
e.setCancelled(true);
return;
}
//dont kill murderer on bow damage if attacker is murderer
if(Role.isRole(Role.MURDERER, userAttacker) && Role.isRole(Role.MURDERER, userVictim)) {
e.setCancelled(true);
return;
}
Arena arena = plugin.getArenaRegistry().getArena(attacker);
if (arena == null) {
return;
}
//we need to set it before the victim die, because of hero character
if(Role.isRole(Role.MURDERER, userVictim)) {
arena.setCharacter(Arena.CharacterType.HERO, attacker);
}
XSound.ENTITY_PLAYER_DEATH.play(victim.getLocation());
victim.damage(100.0);
userAttacker.adjustStatistic("KILLS", 1);
if(Role.isRole(Role.MURDERER, userAttacker)) {
userAttacker.adjustStatistic("LOCAL_KILLS", 1);
arena.adjustContributorValue(Role.DETECTIVE, userAttacker, plugin.getRandom().nextInt(2));
ArenaUtils.addScore(userAttacker, ArenaUtils.ScoreAction.KILL_PLAYER, 0);
}
VersionUtils.sendTitles(victim, new MessageBuilder("IN_GAME_DEATH_SCREEN").asKey().build(), null, 5, 40, 50);
if(Role.isRole(Role.MURDERER, userVictim)) {
ArenaUtils.addScore(userAttacker, ArenaUtils.ScoreAction.KILL_MURDERER, 0);
arena.adjustContributorValue(Role.MURDERER, userAttacker, plugin.getRandom().nextInt(2));
} else if(plugin.getConfigPreferences().getOption("BOW_KILL_DETECTIVE") && (Role.isRole(Role.ANY_DETECTIVE, userVictim) || Role.isRole(Role.INNOCENT, userVictim))) {
if(Role.isRole(Role.MURDERER, userAttacker)) {
VersionUtils.sendTitles(victim, null, new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_MURDERER_KILLED_YOU").asKey().build(), 5, 40, 5);
} else {
VersionUtils.sendTitles(victim, null, new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_INNOCENT_KILLED_YOU").asKey().build(), 5, 40, 5);
}
//if else, murderer killed, so don't kill him :)
if(Role.isRole(Role.ANY_DETECTIVE, userAttacker) || Role.isRole(Role.INNOCENT, userAttacker)) {
VersionUtils.sendSubTitle(attacker, new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_INNOCENT_KILLED_WRONGLY").asKey().build(), 5, 40, 5);
attacker.damage(100.0);
ArenaUtils.addScore(userAttacker, ArenaUtils.ScoreAction.INNOCENT_KILL, 0);
plugin.getRewardsHandler().performReward(attacker, plugin.getRewardsHandler().getRewardType("KILL_DETECTIVE"));
if(Role.isRole(Role.ANY_DETECTIVE, userAttacker) && arena.lastAliveDetective()) {
arena.setDetectiveDead(true);
if(Role.isRole(Role.FAKE_DETECTIVE, userAttacker)) {
arena.setCharacter(Arena.CharacterType.FAKE_DETECTIVE, null);
}
ArenaUtils.dropBowAndAnnounce(arena, victim);
}
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerDie(PlayerDeathEvent e) {
Player player = e.getEntity();
Arena arena = plugin.getArenaRegistry().getArena(player);
if(arena == null) {
return;
}
IUser user = plugin.getUserManager().getUser(player);
ComplementAccessor.getComplement().setDeathMessage(e, "");
e.getDrops().clear();
e.setDroppedExp(0);
plugin.getCorpseHandler().spawnCorpse(player, arena);
XPotion.BLINDNESS.buildPotionEffect(3 * 20, 1).apply(player);
if(arena.getArenaState() == IArenaState.STARTING) {
return;
} else if(arena.getArenaState() == IArenaState.ENDING || arena.getArenaState() == IArenaState.RESTARTING) {
player.getInventory().clear();
player.setFlying(false);
player.setAllowFlight(false);
user.setStatistic("LOCAL_GOLD", 0);
return;
}
if(Role.isRole(Role.MURDERER, user, arena) && arena.lastAliveMurderer()) {
ArenaUtils.onMurdererDeath(arena);
}
if(Role.isRole(Role.ANY_DETECTIVE, user) && arena.lastAliveDetective()) {
arena.setDetectiveDead(true);
if(Role.isRole(Role.FAKE_DETECTIVE, user)) {
arena.setCharacter(Arena.CharacterType.FAKE_DETECTIVE, null);
}
ArenaUtils.dropBowAndAnnounce(arena, player);
}
user.adjustStatistic("DEATHS", 1);
user.setSpectator(true);
VersionUtils.setCollidable(player, false);
player.setGameMode(GameMode.SURVIVAL);
user.setStatistic("LOCAL_GOLD", 0);
ArenaUtils.hidePlayer(player, arena);
player.setAllowFlight(true);
player.setFlying(true);
player.getInventory().clear();
if(plugin.getConfigPreferences().getOption("HIDE_DEATH")) {
new MessageBuilder(MessageBuilder.ActionType.DEATH).player(player).arena(arena).sendArena();
}
if(arena.getArenaState() != IArenaState.ENDING && arena.getArenaState() != IArenaState.RESTARTING) {
arena.addDeathPlayer(player);
}
//we must call it ticks later due to instant respawn bug
Bukkit.getScheduler().runTaskLater(plugin, () -> {
player.spigot().respawn();
plugin.getSpecialItemManager().addSpecialItemsOfStage(player, SpecialItem.DisplayStage.SPECTATOR);
}, 5);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
Arena arena = plugin.getArenaRegistry().getArena(player);
if(arena == null) {
return;
}
if(arena.getArenaState() == IArenaState.STARTING || arena.getArenaState() == IArenaState.WAITING_FOR_PLAYERS) {
event.setRespawnLocation(arena.getLobbyLocation());
return;
}
if(arena.getArenaState() == IArenaState.RESTARTING) {
event.setRespawnLocation(arena.getEndLocation());
return;
}
if(arena.getPlayers().contains(player)) {
IUser user = plugin.getUserManager().getUser(player);
org.bukkit.Location firstSpawn = arena.getPlayerSpawnPoints().get(0);
if(player.getLocation().getWorld().equals(firstSpawn.getWorld())) {
event.setRespawnLocation(player.getLocation());
} else {
event.setRespawnLocation(firstSpawn);
}
player.setAllowFlight(true);
player.setFlying(true);
user.setSpectator(true);
ArenaUtils.hidePlayer(player, arena);
VersionUtils.setCollidable(player, false);
player.setGameMode(GameMode.SURVIVAL);
player.removePotionEffect(PotionEffectType.NIGHT_VISION);
user.setStatistic("LOCAL_GOLD", 0);
plugin.getRewardsHandler().performReward(player, plugin.getRewardsHandler().getRewardType("PLAYER_DEATH"));
}
}
@EventHandler
public void locatorDistanceUpdate(PlayerMoveEvent event) {
Player player = event.getPlayer();
Arena arena = plugin.getArenaRegistry().getArena(player);
if(arena == null) {
return;
}
IUser user = plugin.getUserManager().getUser(player);
//skip spectators
if(user.isSpectator()) {
return;
}
if(arena.getArenaState() == IArenaState.IN_GAME) {
if(Role.isRole(Role.INNOCENT, user, arena)) {
if(player.getInventory().getItem(ItemPosition.BOW_LOCATOR.getOtherRolesItemPosition()) != null) {
ItemStack bowLocator = new ItemStack(Material.COMPASS, 1);
ItemMeta bowMeta = bowLocator.getItemMeta();
ComplementAccessor.getComplement().setDisplayName(bowMeta, new MessageBuilder("IN_GAME_MESSAGES_ARENA_LOCATOR_BOW").asKey().player(player).arena(arena).build() + " §7| §a" + (int) Math.round(player.getLocation().distance(player.getCompassTarget())));
bowLocator.setItemMeta(bowMeta);
ItemPosition.setItem(user, ItemPosition.BOW_LOCATOR, bowLocator);
return;
}
}
if(arena.isMurdererLocatorReceived() && Role.isRole(Role.MURDERER, user, arena) && arena.isMurderAlive(player)) {
ItemStack innocentLocator = new ItemStack(Material.COMPASS, 1);
ItemMeta innocentMeta = innocentLocator.getItemMeta();
for(Player p : arena.getPlayersLeft()) {
Arena playerArena = plugin.getArenaRegistry().getArena(p);
IUser playerUser = plugin.getUserManager().getUser(p);
if(Role.isRole(Role.INNOCENT, playerUser, playerArena) || Role.isRole(Role.ANY_DETECTIVE, playerUser, playerArena)) {
ComplementAccessor.getComplement().setDisplayName(innocentMeta, new MessageBuilder("IN_GAME_MESSAGES_ARENA_LOCATOR_INNOCENT").asKey().player(player).arena(arena).build() + " §7| §a" + (int) Math.round(player.getLocation().distance(p.getLocation())));
innocentLocator.setItemMeta(innocentMeta);
ItemPosition.setItem(user, ItemPosition.INNOCENTS_LOCATOR, innocentLocator);
}
}
}
}
}
@EventHandler
public void onDrop(PlayerDropItemEvent event) {
if(plugin.getArenaRegistry().getArena(event.getPlayer()) != null && plugin.getArenaRegistry().getArena(event.getPlayer()).getArenaState() == IArenaState.IN_GAME) {
event.setCancelled(true);
}
}
@EventHandler
public void onItemMove(InventoryClickEvent event) {
if(event.getWhoClicked() instanceof Player && plugin.getArenaRegistry().isInArena((Player) event.getWhoClicked())) {
if(XInventoryView.of(event.getView()).getType() == InventoryType.CRAFTING || XInventoryView.of(event.getView()).getType() == InventoryType.PLAYER) {
event.setResult(Event.Result.DENY);
}
}
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/ArenaManager.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArenaManager;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.utils.actionbar.ActionBar;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.managers.MapRestorerManager;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.arena.special.SpecialBlock;
import plugily.projects.murdermystery.utils.ItemPosition;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author Plajer
*
Created at 13.05.2018
*/
public class ArenaManager extends PluginArenaManager {
private final Main plugin;
public ArenaManager(Main plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public void joinAttempt(@NotNull Player player, @NotNull IPluginArena arena) {
Arena pluginArena = (Arena) plugin.getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
super.joinAttempt(player, arena);
ArenaUtils.updateNameTagsVisibility(player);
}
@Override
public void leaveAttempt(@NotNull Player player, @NotNull IPluginArena arena) {
Arena pluginArena = (Arena) plugin.getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
super.leaveAttempt(player, arena);
if(pluginArena.isDeathPlayer(player)) {
pluginArena.removeDeathPlayer(player);
}
IUser user = plugin.getUserManager().getUser(player);
int localScore = user.getStatistic("LOCAL_SCORE");
if(localScore > user.getStatistic("HIGHEST_SCORE")) {
user.setStatistic("HIGHEST_SCORE", localScore);
}
boolean playerHasMurdererRole = Role.isRole(Role.MURDERER, user, arena);
if(playerHasMurdererRole) {
pluginArena.removeFromMurdererList(player);
}
if(arena.getArenaState() == IArenaState.IN_GAME && !user.isSpectator()) {
List playersLeft = arena.getPlayersLeft();
if(playersLeft.size() > 1) {
if(playerHasMurdererRole) {
if(pluginArena.getMurdererList().isEmpty()) {
List players = new ArrayList<>();
for(Player gamePlayer : playersLeft) {
IUser userGamePlayer = plugin.getUserManager().getUser(gamePlayer);
if(gamePlayer == player || Role.isRole(Role.ANY_DETECTIVE, userGamePlayer, arena) || Role.isRole(Role.MURDERER, userGamePlayer, arena)) {
continue;
}
players.add(gamePlayer);
}
Player newMurderer = players.get(players.size() == 1 ? 0 : ThreadLocalRandom.current().nextInt(players.size()));
if(newMurderer != null) {
plugin.getDebugger().debug("A murderer left the game. New murderer: {0}", newMurderer.getName());
pluginArena.setCharacter(Arena.CharacterType.MURDERER, newMurderer);
pluginArena.addToMurdererList(newMurderer);
}
new TitleBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_CHANGE").asKey().player(player).arena(pluginArena).sendArena();
if(newMurderer != null) {
new TitleBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_MURDERER").asKey().player(player).arena(pluginArena).sendPlayer();
plugin.getActionBarManager().addActionBar(player, new ActionBar((new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_CHANGE")).asKey(), ActionBar.ActionBarType.DISPLAY, 5));
ItemPosition.setItem(plugin.getUserManager().getUser(newMurderer), ItemPosition.MURDERER_SWORD, plugin.getSwordSkinManager().getRandomSwordSkin(player));
}
} else {
plugin.getDebugger().debug("No new murderer added as there are some");
}
} else if(Role.isRole(Role.ANY_DETECTIVE, user, arena)
&& pluginArena.lastAliveDetective()) {
pluginArena.setDetectiveDead(true);
if(Role.isRole(Role.FAKE_DETECTIVE, user, arena)) {
pluginArena.setCharacter(Arena.CharacterType.FAKE_DETECTIVE, null);
}
ArenaUtils.dropBowAndAnnounce(pluginArena, player);
}
plugin.getCorpseHandler().spawnCorpse(player, pluginArena);
} else {
stopGame(false, arena);
}
}
}
@Override
public void stopGame(boolean quickStop, @NotNull IPluginArena arena) {
Arena pluginArena = (Arena) plugin.getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
for(SpecialBlock specialBlock : pluginArena.getSpecialBlocks()) {
if(specialBlock.getArmorStandHologram() != null) {
specialBlock.getArmorStandHologram().delete();
}
}
((MapRestorerManager) pluginArena.getMapRestorerManager()).removeBowHolo();
boolean murderWon = arena.getPlayersLeft().size() == pluginArena.aliveMurderer();
for(Player player : arena.getPlayersLeft()) {
if(!quickStop) {
IUser user = plugin.getUserManager().getUser(player);
if(Role.isAnyRole(user, arena)) {
boolean hasDeathRole = Role.isRole(Role.DEATH, user, arena);
int multiplicator = 1;
if(!hasDeathRole) {
multiplicator = arena.getMaximumPlayers();
}
pluginArena.adjustContributorValue(Role.MURDERER, user, plugin.getRandom().nextInt(10 * multiplicator));
pluginArena.adjustContributorValue(Role.DETECTIVE, user, plugin.getRandom().nextInt(10 * multiplicator));
if(!hasDeathRole) {
boolean hasMurdererRole = Role.isRole(Role.MURDERER, user, arena);
if(murderWon || !hasMurdererRole) {
user.adjustStatistic("WINS", 1);
plugin.getRewardsHandler().performReward(player, plugin.getRewardsHandler().getRewardType("WIN"));
} else {
user.adjustStatistic("LOSES", 1);
plugin.getRewardsHandler().performReward(player, plugin.getRewardsHandler().getRewardType("LOSE"));
}
} else {
user.adjustStatistic("LOSES", 1);
plugin.getRewardsHandler().performReward(player, plugin.getRewardsHandler().getRewardType("LOSE"));
}
}
}
}
super.stopGame(quickStop, arena);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/ArenaRegistry.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.PluginArenaRegistry;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.serialization.LocationSerializer;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.special.SpecialBlock;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Tom on 27/07/2014.
*/
public class ArenaRegistry extends PluginArenaRegistry {
private final Main plugin;
public ArenaRegistry(Main plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public PluginArena getNewArena(String id) {
return new Arena(id);
}
@Override
public boolean additionalValidatorChecks(ConfigurationSection section, PluginArena arena, String id) {
boolean checks = super.additionalValidatorChecks(section, arena, id);
if(!checks) return false;
if(!section.getBoolean(id + ".isdone")) {
plugin.getDebugger().sendConsoleMsg(new MessageBuilder("VALIDATOR_INVALID_ARENA_CONFIGURATION").asKey().value("NOT VALIDATED").arena(arena).build());
return false;
}
List playerSpawnPoints = new ArrayList<>();
for(String loc : section.getStringList(id + ".playerspawnpoints")) {
org.bukkit.Location serialized = LocationSerializer.getLocation(loc);
// Ignore the arena if world is not exist at least in spawn points
if(serialized == null || serialized.getWorld() == null) {
section.set(id + ".isdone", false);
} else {
playerSpawnPoints.add(serialized);
}
}
((Arena) arena).setSpawnGoldTime(section.getInt(id + ".spawngoldtime", 5));
((Arena) arena).setHideChances(section.getBoolean(id + ".hidechances"));
arena.setArenaOption("MURDERER_DIVIDER",section.getInt(id + ".playerpermurderer", 5));
arena.setArenaOption("DETECTIVE_DIVIDER",section.getInt(id + ".playerperdetective", 7));
((Arena) arena).setGoldVisuals(section.getBoolean(id + ".goldvisuals"));
((Arena) arena).setPlayerSpawnPoints(playerSpawnPoints);
List goldSpawnPoints = new ArrayList<>();
for(String loc : section.getStringList(id + ".goldspawnpoints")) {
goldSpawnPoints.add(LocationSerializer.getLocation(loc));
}
((Arena) arena).setGoldSpawnPoints(goldSpawnPoints);
List specialBlocks = new ArrayList<>();
for(String loc : section.getStringList(id + ".mystery-cauldrons")) {
specialBlocks.add(new SpecialBlock(LocationSerializer.getLocation(loc), SpecialBlock.SpecialBlockType.MYSTERY_CAULDRON));
}
for(String loc : section.getStringList(id + ".confessionals")) {
specialBlocks.add(new SpecialBlock(LocationSerializer.getLocation(loc), SpecialBlock.SpecialBlockType.PRAISE_DEVELOPER));
}
specialBlocks.forEach(((Arena) arena)::loadSpecialBlock);
return true;
}
@Override
public @Nullable Arena getArena(Player player) {
IPluginArena pluginArena = super.getArena(player);
if(pluginArena instanceof Arena) {
return (Arena) pluginArena;
}
return null;
}
@Override
public @Nullable Arena getArena(String id) {
IPluginArena pluginArena = super.getArena(id);
if(pluginArena instanceof Arena) {
return (Arena) pluginArena;
}
return null;
}
public @NotNull List getPluginArenas() {
List arenas = new ArrayList<>();
for(IPluginArena pluginArena : super.getArenas()) {
if(pluginArena instanceof Arena) {
arenas.add((Arena) pluginArena);
}
}
return arenas;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/ArenaUtils.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena;
import org.bukkit.Bukkit;
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 plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArenaUtils;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
import plugily.projects.minigamesbox.classic.utils.misc.complement.ComplementAccessor;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.utils.ItemPosition;
/**
* @author Plajer
*
Created at 13.03.2018
*/
public class ArenaUtils extends PluginArenaUtils {
private ArenaUtils() {
super();
}
public static void onMurdererDeath(Arena arena) {
for(Player player : arena.getPlayers()) {
VersionUtils.sendSubTitle(player, new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_MURDERER_STOPPED").asKey().build(), 5, 40, 5);
IUser loopUser = getPlugin().getUserManager().getUser(player);
if(Role.isRole(Role.INNOCENT, loopUser, arena)) {
addScore(loopUser, ScoreAction.SURVIVE_GAME, 0);
} else if(Role.isRole(Role.ANY_DETECTIVE, loopUser, arena)) {
addScore(loopUser, ScoreAction.WIN_GAME, 0);
addScore(loopUser, ScoreAction.DETECTIVE_WIN_GAME, 0);
}
}
//we must call it ticks later due to instant respawn bug
Bukkit.getScheduler().runTask(getPlugin(), () -> getPlugin().getArenaManager().stopGame(false, arena));
}
public static void updateInnocentLocator(Arena arena) {
java.util.List list = arena.getPlayersLeft();
if(!arena.isMurdererLocatorReceived()) {
ItemStack innocentLocator = new ItemStack(Material.COMPASS, 1);
ItemMeta innocentMeta = innocentLocator.getItemMeta();
ComplementAccessor.getComplement()
.setDisplayName(
innocentMeta,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_LOCATOR_INNOCENT").asKey().build());
innocentLocator.setItemMeta(innocentMeta);
for(Player p : list) {
if(arena.isMurderAlive(p)) {
ItemPosition.setItem(getPlugin().getUserManager().getUser(p), ItemPosition.INNOCENTS_LOCATOR, innocentLocator);
}
}
arena.setMurdererLocatorReceived(true);
for(Player p : list) {
if(Role.isRole(Role.MURDERER, getPlugin().getUserManager().getUser(p), arena)) {
continue;
}
new TitleBuilder("IN_GAME_MESSAGES_ARENA_LOCATOR_WATCH_OUT")
.asKey()
.player(p)
.arena(arena)
.sendPlayer();
}
}
for(Player p : list) {
if(Role.isRole(Role.MURDERER, getPlugin().getUserManager().getUser(p), arena)) {
continue;
}
for(Player murder : arena.getMurdererList()) {
if(arena.isMurderAlive(murder)) {
murder.setCompassTarget(p.getLocation());
}
}
break;
}
}
public static void dropBowAndAnnounce(Arena arena, Player victim) {
if(arena.getBowHologram() != null) {
return;
}
for(Player player : arena.getPlayers()) {
IUser user = arena.getPlugin().getUserManager().getUser(player);
if(Role.isRole(Role.MURDERER, user, arena)) {
continue;
}
new TitleBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_BOW_DROPPED").asKey().arena(arena).send(player);
}
ArmorStandHologram hologram =
new ArmorStandHologram(victim.getLocation()).appendItem(new ItemStack(Material.BOW, 1));
arena.setBowHologram(hologram);
addBowLocator(arena, hologram.getLocation());
}
private static void addBowLocator(Arena arena, Location loc) {
ItemStack bowLocator = new ItemStack(Material.COMPASS, 1);
ItemMeta bowMeta = bowLocator.getItemMeta();
ComplementAccessor.getComplement()
.setDisplayName(
bowMeta, new MessageBuilder("IN_GAME_MESSAGES_ARENA_LOCATOR_BOW").asKey().build());
bowLocator.setItemMeta(bowMeta);
for(Player p : arena.getPlayersLeft()) {
IUser user = getPlugin().getUserManager().getUser(p);
if(Role.isRole(Role.INNOCENT, user, arena)) {
ItemPosition.setItem(user, ItemPosition.BOW_LOCATOR, bowLocator);
p.setCompassTarget(loc);
}
}
}
public static void updateNameTagsVisibility(final Player p) {
if(!getPlugin().getConfigPreferences().getOption("HIDE_NAMETAGS")) {
return;
}
for(Player players : getPlugin().getServer().getOnlinePlayers()) {
IPluginArena arena = getPlugin().getArenaRegistry().getArena(players);
if(arena == null) {
continue;
}
VersionUtils.updateNameTagsVisibility(
p, players, "MMHide", arena.getArenaState() != IArenaState.IN_GAME);
}
}
public static void addScore(IUser user, ScoreAction action, int amount) {
XSound.matchXSound(XSound.ENTITY_EXPERIENCE_ORB_PICKUP.parseSound())
.play(user.getPlayer().getLocation(), 1F, 2F);
if(action == ScoreAction.GOLD_PICKUP && amount > 1) {
int score = action.points * amount;
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_BONUS")
.asKey()
.player(user.getPlayer())
.arena(user.getArena())
.integer(score)
.value(action.action)
.sendPlayer();
user.adjustStatistic("LOCAL_SCORE", score);
return;
}
if(action == ScoreAction.DETECTIVE_WIN_GAME) {
int innocents = 0;
Arena arena = (Arena) user.getArena();
for(Player p : arena.getPlayersLeft()) {
if(Role.isRole(Role.INNOCENT, getPlugin().getUserManager().getUser(p), arena)) {
innocents++;
}
}
int overallInnocents = 100 * innocents;
user.adjustStatistic("LOCAL_SCORE", overallInnocents);
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_BONUS")
.asKey()
.player(user.getPlayer())
.arena(user.getArena())
.integer(overallInnocents)
.value(new MessageBuilder(action.action).integer(innocents).build())
.sendPlayer();
return;
}
String msg =
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_BONUS")
.asKey()
.player(user.getPlayer())
.arena(user.getArena())
.integer(action.points)
.value(action.action)
.build();
if(action.points < 0) {
msg = msg.replace("+", "");
}
user.adjustStatistic("LOCAL_SCORE", action.points);
user.getPlayer().sendMessage(msg);
}
public enum ScoreAction {
KILL_PLAYER(
100,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_KILL_PLAYER")
.asKey()
.build()),
KILL_MURDERER(
200,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_KILL_MURDERER")
.asKey()
.build()),
GOLD_PICKUP(
15,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_PICKUP_GOLD")
.asKey()
.build()),
SURVIVE_TIME(
150,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_SURVIVING_TIME")
.asKey()
.build()),
SURVIVE_GAME(
200,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_SURVIVING_END")
.asKey()
.build()),
WIN_GAME(
100, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_WIN").asKey().build()),
DETECTIVE_WIN_GAME(
0,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_DETECTIVE")
.asKey()
.build()),
INNOCENT_KILL(
-100,
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_KILL_INNOCENT")
.asKey()
.build());
int points;
String action;
ScoreAction(int points, String action) {
this.points = points;
this.action = action;
}
public int getPoints() {
return points;
}
public String getAction() {
return action;
}
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/corpse/Corpse.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.corpse;
import org.golde.bukkit.corpsereborn.nms.Corpses;
import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
/**
* @author Plajer
*
* Created at 07.08.2018
*/
public class Corpse {
private final ArmorStandHologram hologram;
private final Corpses.CorpseData corpseData;
public Corpse(ArmorStandHologram hologram, Corpses.CorpseData corpseData) {
this.hologram = hologram;
this.corpseData = corpseData;
}
public ArmorStandHologram getHologram() {
return hologram;
}
public Corpses.CorpseData getCorpseData() {
return corpseData;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/corpse/Stand.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.corpse;
import org.bukkit.entity.ArmorStand;
import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
/**
* @author Plajer
*
* Created at 07.08.2018
*/
public class Stand {
private final ArmorStandHologram hologram;
private final ArmorStand stand;
public Stand(ArmorStandHologram hologram, ArmorStand stand) {
this.hologram = hologram;
this.stand = stand;
}
public ArmorStandHologram getHologram() {
return hologram;
}
public ArmorStand getStand() {
return stand;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/managers/MapRestorerManager.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.managers;
import org.bukkit.Bukkit;
import org.bukkit.entity.Item;
import org.golde.bukkit.corpsereborn.CorpseAPI.CorpseAPI;
import plugily.projects.minigamesbox.classic.arena.managers.PluginMapRestorerManager;
import plugily.projects.murdermystery.HookManager;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.corpse.Corpse;
import plugily.projects.murdermystery.arena.corpse.Stand;
import java.util.Objects;
public class MapRestorerManager extends PluginMapRestorerManager {
public final Arena arena;
public MapRestorerManager(Arena arena) {
super(arena);
this.arena = arena;
}
@Override
public void fullyRestoreArena() {
cleanUpArena();
super.fullyRestoreArena();
}
public void cleanUpArena() {
removeBowHolo();
arena.setMurdererLocatorReceived(false);
arena.getDetectiveContributions().clear();
arena.getMurdererContributions().clear();
arena.getGameCharacters().clear();
arena.getMurdererList().clear();
arena.getDetectiveList().clear();
arena.getDeaths().clear();
arena.setDetectiveDead(false);
clearCorpses();
clearGold();
}
public void removeBowHolo() {
if(arena.getBowHologram() != null && !arena.getBowHologram().isDeleted()) {
arena.getBowHologram().delete();
}
arena.setBowHologram(null);
}
public void clearGold() {
arena.getGoldSpawned().stream().filter(Objects::nonNull).forEach(Item::remove);
arena.getGoldSpawned().clear();
}
public void clearCorpses() {
if(!arena.getPlugin().getHookManager().isFeatureEnabled(HookManager.HookFeature.CORPSES)) {
for(Stand stand : arena.getStands()) {
if(!stand.getHologram().isDeleted()) {
stand.getHologram().delete();
}
if(stand.getStand() != null) {
stand.getStand().remove();
}
}
arena.getStands().clear();
return;
}
for(Corpse corpse : arena.getCorpses()) {
if(!corpse.getHologram().isDeleted()) {
corpse.getHologram().delete();
}
if(corpse.getCorpseData() != null) {
corpse.getCorpseData().destroyCorpseFromEveryone();
CorpseAPI.removeCorpse(corpse.getCorpseData());
}
}
arena.getCorpses().clear();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/managers/ScoreboardManager.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.managers;
import org.bukkit.entity.Player;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.managers.PluginScoreboardManager;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.murdermystery.arena.role.Role;
import java.util.ArrayList;
import java.util.List;
/**
* @author Tigerpanzer_02
*
Created at 19.12.2021
*/
public class ScoreboardManager extends PluginScoreboardManager {
private final PluginArena arena;
public ScoreboardManager(PluginArena arena) {
super(arena);
this.arena = arena;
}
@Override
public List getScoreboardLines(Player player) {
List lines;
if(arena.getArenaState() == IArenaState.IN_GAME) {
IUser user = arena.getPlugin().getUserManager().getUser(player);
lines =
arena
.getPlugin()
.getLanguageManager()
.getLanguageList(
"Scoreboard.Content." + arena.getArenaState().getFormattedName() + (Role.isRole(Role.MURDERER, user) ? "-Murderer" : ""));
} else {
lines = super.getScoreboardLines(player);
}
return lines;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/role/Role.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.role;
import org.bukkit.entity.Player;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.user.User;
import plugily.projects.murdermystery.arena.Arena;
/**
* @author Plajer
*
* Created at 06.10.2018
*/
public enum Role {
/**
* Detective or fake detective role
*/
ANY_DETECTIVE,
/**
* Detective role, he must kill murderer
*/
DETECTIVE,
/**
* Detective role, innocent who picked up bow became fake detective because he wasn't
* detective by default
*/
FAKE_DETECTIVE,
/**
* Innocent player role, must survive to win
*/
INNOCENT,
/**
* Murderer role, must kill everyone to win
*/
MURDERER,
/**
* Spectator role, just look :D
*/
SPECTATOR,
/**
* Death role, when everyone died
*/
DEATH;
/**
* Checks whether player is playing specified role or not
*
* @param role role to check
* @param user player to check
* @return true if is playing it, false otherwise
*/
public static boolean isRole(Role role, IUser user) {
return isRole(role, user, user.getArena());
}
/**
* Checks whether player is playing specified role or not
*
* @param role role to check
* @param user player to check
* @param arena the arena where to check
* @return true if is playing it, false otherwise
*/
public static boolean isRole(Role role, IUser user, IPluginArena arena) {
if(arena == null)
return false;
Arena pluginArena = (Arena) arena.getPlugin().getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return false;
}
Player player = user.getPlayer();
switch(role) {
case DETECTIVE:
return pluginArena.isCharacterSet(Arena.CharacterType.DETECTIVE) && pluginArena.getDetectiveList().contains(player);
case FAKE_DETECTIVE:
return player.equals(pluginArena.getCharacter(Arena.CharacterType.FAKE_DETECTIVE));
case MURDERER:
return pluginArena.isCharacterSet(Arena.CharacterType.MURDERER) && pluginArena.getMurdererList().contains(player);
case ANY_DETECTIVE:
return isRole(Role.DETECTIVE, user) || isRole(Role.FAKE_DETECTIVE, user);
case INNOCENT:
return !isRole(Role.MURDERER, user) && !isRole(Role.ANY_DETECTIVE, user);
case DEATH:
return pluginArena.isDeathPlayer(player);
case SPECTATOR:
return pluginArena.isSpectatorPlayer(player);
default:
return false;
}
}
/**
* Checks whether player is playing a role or not
*
* @param user player to check
* @return true if is playing one role, false otherwise
*/
public static boolean isAnyRole(User user) {
return isAnyRole(user, user.getArena());
}
private static final Role[] roles = Role.values();
/**
* Checks whether player is playing a role or not
*
* @param user player to check
* @param arena the player's arena
* @return true if is playing one role, false otherwise
*/
public static boolean isAnyRole(IUser user, IPluginArena arena) {
return arena != null && java.util.Arrays.stream(roles).anyMatch(role -> isRole(role, user, arena));
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/special/SpecialBlock.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.special;
import org.bukkit.Location;
import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
/**
* @author Plajer
*
* Created at 15.10.2018
*/
public class SpecialBlock {
private final Location location;
private final SpecialBlockType specialBlockType;
private ArmorStandHologram armorStandHologram;
public SpecialBlock(Location location, SpecialBlockType specialBlockType) {
this.location = location;
this.specialBlockType = specialBlockType;
}
public Location getLocation() {
return location;
}
public SpecialBlockType getSpecialBlockType() {
return specialBlockType;
}
public ArmorStandHologram getArmorStandHologram() {
return armorStandHologram;
}
public void setArmorStandHologram(ArmorStandHologram armorStandHologram) {
this.armorStandHologram = armorStandHologram;
}
public enum SpecialBlockType {
HORSE_PURCHASE, MYSTERY_CAULDRON, PRAISE_DEVELOPER, RAPID_TELEPORTATION
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/special/SpecialBlockEvents.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.special;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Item;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.inventory.ItemStack;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.helper.ItemUtils;
import plugily.projects.minigamesbox.classic.utils.misc.complement.ComplementAccessor;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.special.mysterypotion.MysteryPotion;
import plugily.projects.murdermystery.arena.special.mysterypotion.MysteryPotionRegistry;
import plugily.projects.murdermystery.arena.special.pray.PrayerRegistry;
import plugily.projects.murdermystery.utils.ItemPosition;
/**
* @author Plajer
*
* Created at 16.10.2018
*/
public class SpecialBlockEvents implements Listener {
private final Main plugin;
public SpecialBlockEvents(Main plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onSpecialBlockClick(PlayerInteractEvent event) {
if(event.getClickedBlock() == null)
return;
if(ServerVersion.Version.isCurrentEqualOrHigher(ServerVersion.Version.v1_11) && event.getHand() == org.bukkit.inventory.EquipmentSlot.OFF_HAND) {
return;
}
Arena arena = plugin.getArenaRegistry().getArena(event.getPlayer());
if(arena == null) {
return;
}
if(arena.getArenaState() != IArenaState.IN_GAME || plugin.getUserManager().getUser(event.getPlayer()).isSpectator()) {
return;
}
for(SpecialBlock specialBlock : arena.getSpecialBlocks()) {
if(event.getClickedBlock().getType() == XMaterial.LEVER.parseMaterial() && plugin.getBukkitHelper().getNearbyBlocks(specialBlock.getLocation(), 3).contains(event.getClickedBlock())) {
onPrayLeverClick(event);
return;
}
if(specialBlock.getLocation().getBlock().equals(event.getClickedBlock())) {
switch(specialBlock.getSpecialBlockType()) {
case MYSTERY_CAULDRON:
onCauldronClick(event);
return;
case PRAISE_DEVELOPER:
onPrayerClick(event);
return;
case HORSE_PURCHASE:
case RAPID_TELEPORTATION:
//not yet implemented
default:
break;
}
}
}
}
private void onCauldronClick(PlayerInteractEvent event) {
if(event.getClickedBlock().getType() != Material.CAULDRON) {
return;
}
if(event.getPlayer().getInventory().getItem(/* same for all roles */ ItemPosition.POTION.getOtherRolesItemPosition()) != null) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_CAULDRON_POTION").asKey().player(event.getPlayer()).sendPlayer();
return;
}
IUser user = plugin.getUserManager().getUser(event.getPlayer());
int localGold = user.getStatistic("LOCAL_GOLD");
if(localGold < 1) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_NOT_ENOUGH_GOLD").asKey().player(event.getPlayer()).integer(1).sendPlayer();
return;
}
org.bukkit.Location blockLoc = event.getClickedBlock().getLocation();
VersionUtils.sendParticles("FIREWORKS_SPARK", event.getPlayer(), blockLoc, 10);
Item item = blockLoc.getWorld().dropItemNaturally(blockLoc.clone().add(0, 1, 0), new ItemStack(Material.POTION, 1));
item.setPickupDelay(10000);
Bukkit.getScheduler().runTaskLater(plugin, item::remove, 20);
user.adjustStatistic("LOCAL_GOLD", -1);
ItemPosition.removeItem(user, new ItemStack(Material.GOLD_INGOT, 1));
ItemPosition.setItem(user, ItemPosition.POTION, new ItemBuilder(XMaterial.POTION.parseItem()).name(MysteryPotionRegistry.getRandomPotion().getName()).build());
}
private void onPrayerClick(PlayerInteractEvent event) {
if(event.getClickedBlock().getType() != XMaterial.ENCHANTING_TABLE.parseMaterial()) {
return;
}
event.setCancelled(true);
IUser user = plugin.getUserManager().getUser(event.getPlayer());
int localGold = user.getStatistic("LOCAL_GOLD");
if(localGold < 1) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_NOT_ENOUGH_GOLD").asKey().player(event.getPlayer()).integer(1).sendPlayer();
return;
}
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_CHAT").asKey().player(event.getPlayer()).sendPlayer();
user.adjustStatistic("LOCAL_PRAISES", 1);
VersionUtils.sendParticles("FIREWORKS_SPARK", event.getPlayer(), event.getClickedBlock().getLocation(), 10);
user.adjustStatistic("LOCAL_GOLD", -1);
ItemPosition.removeItem(user, new ItemStack(Material.GOLD_INGOT, 1));
}
private void onPrayLeverClick(PlayerInteractEvent event) {
IUser user = plugin.getUserManager().getUser(event.getPlayer());
if(user.getStatistic("LOCAL_PRAISES") < 1) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PAY").asKey().player(event.getPlayer()).sendPlayer();
return;
}
PrayerRegistry.applyRandomPrayer(user);
user.setStatistic("LOCAL_PRAISES", 0);
}
@EventHandler
public void onMysteryPotionDrink(PlayerItemConsumeEvent event) {
ItemStack item = event.getItem();
if(item.getType() != XMaterial.POTION.parseMaterial() || !ItemUtils.isItemStackNamed(item)) {
return;
}
if(plugin.getArenaRegistry().getArena(event.getPlayer()) == null) {
return;
}
String itemDisplayName = ComplementAccessor.getComplement().getDisplayName(item.getItemMeta());
IUser user = plugin.getUserManager().getUser(event.getPlayer());
for(MysteryPotion potion : MysteryPotionRegistry.getMysteryPotions()) {
if(itemDisplayName.equals(potion.getName())) {
event.setCancelled(true);
event.getPlayer().sendMessage(potion.getSubtitle());
VersionUtils.sendTitles(event.getPlayer(), "", potion.getSubtitle(), 5, 40, 5);
ItemPosition.setItem(user, ItemPosition.POTION, null);
event.getPlayer().addPotionEffect(potion.getPotionEffect());
return;
}
}
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/special/mysterypotion/MysteryPotion.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.special.mysterypotion;
import org.bukkit.potion.PotionEffect;
/**
* @author Plajer
*
* Created at 15.10.2018
*/
public class MysteryPotion {
private final String name;
private final String subtitle;
private final PotionEffect potionEffect;
public MysteryPotion(String name, String subtitle, PotionEffect potionEffect) {
this.name = name;
this.subtitle = subtitle;
this.potionEffect = potionEffect;
}
public String getName() {
return name;
}
public String getSubtitle() {
return subtitle;
}
public PotionEffect getPotionEffect() {
return potionEffect;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/special/mysterypotion/MysteryPotionRegistry.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.special.mysterypotion;
import org.bukkit.configuration.file.FileConfiguration;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XPotion;
import plugily.projects.murdermystery.Main;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author Plajer
*
* Created at 15.10.2018
*/
public class MysteryPotionRegistry {
private static final List mysteryPotions = new ArrayList<>();
public static void init(Main plugin) {
FileConfiguration config = ConfigUtils.getConfig(plugin, "special_blocks");
org.bukkit.configuration.ConfigurationSection section = config.getConfigurationSection("Special-Blocks.Cauldron-Potions");
if(section == null) {
return;
}
for(String key : section.getKeys(false)) {
mysteryPotions.add(new MysteryPotion(new MessageBuilder(section.getString(key + ".Name")).build(),
new MessageBuilder(section.getString(key + ".Subtitle")).build(), XPotion.of(section.getString(key + ".Type", "").toUpperCase()).get().buildPotionEffect(section.getInt(key + ".Duration") * 20, section.getInt(key + ".Amplifier"))));
}
}
public static MysteryPotion getRandomPotion() {
return mysteryPotions.get(mysteryPotions.size() == 1 ? 0 : ThreadLocalRandom.current().nextInt(mysteryPotions.size()));
}
public static List getMysteryPotions() {
return mysteryPotions;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/special/pray/Prayer.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.special.pray;
/**
* @author Plajer
*
* Created at 16.10.2018
*/
public class Prayer {
private final PrayerType prayerType;
private final boolean goodPray;
private final String prayerDescription;
public Prayer(PrayerType prayerType, boolean goodPray, String prayerDescription) {
this.prayerType = prayerType;
this.goodPray = goodPray;
this.prayerDescription = prayerDescription;
}
public PrayerType getPrayerType() {
return prayerType;
}
public boolean isGoodPray() {
return goodPray;
}
public String getPrayerDescription() {
return prayerDescription;
}
public enum PrayerType {
BLINDNESS_CURSE, BOW_TIME, DETECTIVE_REVELATION, GOLD_BAN, GOLD_RUSH, INCOMING_DEATH, SINGLE_COMPENSATION, SLOWNESS_CURSE
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/special/pray/PrayerRegistry.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.special.pray;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.misc.MiscUtils;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XPotion;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.utils.ItemPosition;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author Plajer
*
* Created at 16.10.2018
*/
public class PrayerRegistry {
private static Main plugin;
private static final List prayers = new ArrayList<>();
private static final List ban = new ArrayList<>(), rush = new ArrayList<>();
private PrayerRegistry() {
}
public static void init(Main plugin) {
PrayerRegistry.plugin = plugin;
//good prayers
prayers.add(new Prayer(Prayer.PrayerType.DETECTIVE_REVELATION, true, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_DETECTIVE_REVELATION").asKey().build()));
prayers.add(new Prayer(Prayer.PrayerType.GOLD_RUSH, true, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_GOLD_RUSH").asKey().build()));
prayers.add(new Prayer(Prayer.PrayerType.SINGLE_COMPENSATION, true, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_SINGLE_COMPENSATION").asKey().build()));
prayers.add(new Prayer(Prayer.PrayerType.BOW_TIME, true, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_BOW").asKey().build()));
//bad prayers
prayers.add(new Prayer(Prayer.PrayerType.SLOWNESS_CURSE, false, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_SLOWNESS").asKey().build()));
prayers.add(new Prayer(Prayer.PrayerType.BLINDNESS_CURSE, false, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_BLINDNESS").asKey().build()));
prayers.add(new Prayer(Prayer.PrayerType.GOLD_BAN, false, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_GOLD").asKey().build()));
prayers.add(new Prayer(Prayer.PrayerType.INCOMING_DEATH, false, new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_DEATH").asKey().build()));
}
public static Prayer getRandomPray() {
return prayers.get(ThreadLocalRandom.current().nextInt(prayers.size()));
}
public static List getPrayers() {
return prayers;
}
public static void applyRandomPrayer(IUser user) {
Prayer prayer = getRandomPray();
user.setStatistic("LOCAL_CURRENT_PRAY", prayer.getPrayerType().ordinal());
Player player = user.getPlayer();
Arena arena = plugin.getArenaRegistry().getArena(player);
List prayMessage = plugin.getLanguageManager().getLanguageList("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Heard");
String feeling = plugin.getLanguageManager().getLanguageMessage("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Feeling." + (prayer.isGoodPray() ? "Blessed" : "Cursed"));
int praySize = prayMessage.size();
for(int a = 0; a < praySize; a++) {
prayMessage.set(a, prayMessage.get(a).replace("%feeling%", feeling).replace("%praise%", prayer.getPrayerDescription()));
}
switch(prayer.getPrayerType()) {
case BLINDNESS_CURSE:
XPotion.BLINDNESS.buildPotionEffect(Integer.MAX_VALUE, 1).apply(player);
break;
case BOW_TIME:
if(!Role.isRole(Role.ANY_DETECTIVE, user, arena)) {
ItemPosition.addItem(user, ItemPosition.BOW, new ItemStack(Material.BOW, 1));
}
ItemPosition.setItem(user, ItemPosition.ARROWS, new ItemStack(Material.ARROW, plugin.getConfig().getInt("Bow.Amount.Arrows.Prayer", 2)));
break;
case DETECTIVE_REVELATION:
Player characterType = null;
if(arena != null) {
characterType = arena.getCharacter(Arena.CharacterType.DETECTIVE);
if(characterType == null) {
characterType = arena.getCharacter(Arena.CharacterType.FAKE_DETECTIVE);
}
}
String charName = characterType == null ? "????" : characterType.getName();
for(int a = 0; a < praySize; a++) {
prayMessage.set(a, prayMessage.get(a).replace("%detective%", charName));
}
break;
case INCOMING_DEATH:
new BukkitRunnable() {
int time = 60;
@Override
public void run() {
if(arena == null || arena.getArenaState() != IArenaState.IN_GAME || !arena.getPlayersLeft().contains(player)) {
cancel();
return;
}
if(time-- == 0) {
player.damage(1000);
cancel();
}
}
}.runTaskTimer(plugin, 20, 20);
break;
case SINGLE_COMPENSATION:
ItemPosition.addItem(user, ItemPosition.GOLD_INGOTS, new ItemStack(Material.GOLD_INGOT, 5));
user.adjustStatistic("LOCAL_GOLD", 5);
break;
case SLOWNESS_CURSE:
XPotion.SLOWNESS.buildPotionEffect(Integer.MAX_VALUE, 1).apply(player);
break;
case GOLD_BAN:
ban.add(player);
break;
case GOLD_RUSH:
rush.add(player);
break;
default:
break;
}
for(String msg : prayMessage) {
MiscUtils.sendCenteredMessage(player, msg);
}
}
public static List getBan() {
return ban;
}
public static List getRush() {
return rush;
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/states/InGameState.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.states;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginInGameState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.ArenaUtils;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.utils.ItemPosition;
/**
* @author Plajer
*
Created at 03.06.2019
*/
public class InGameState extends PluginInGameState {
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
Arena pluginArena = (Arena) getPlugin().getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
// winner checks
if(pluginArena.getTimer() <= 0) {
getPlugin().getArenaManager().stopGame(false, pluginArena);
}
if(pluginArena.getPlayersLeft().size() == pluginArena.aliveMurderer()) {
getPlugin().getArenaManager().stopGame(false, pluginArena);
}
distributeMurdererSword(pluginArena);
//every 30 secs survive reward
givePlayerSurviveReward(pluginArena);
addInnocentLocator(pluginArena);
if(pluginArena.getPlayersLeft().size() == pluginArena.aliveMurderer() + 1) {
addMurdererSpeed(pluginArena);
}
spawnGold(pluginArena);
}
private void addMurdererSpeed(Arena pluginArena) {
int multiplier = getPlugin().getConfig().getInt("Murderer.Speed", 3);
if(multiplier > 1 && multiplier <= 10) {
for(Player player : pluginArena.getMurdererList()) {
if(pluginArena.isMurderAlive(player)) {
// no potion because it adds particles which can be identified
player.setWalkSpeed(0.1f * multiplier);
}
}
}
}
private void distributeMurdererSword(Arena pluginArena) {
int inGameLength = getPlugin().getConfig().getInt("Time-Manager.In-Game", 270);
if(pluginArena.getTimer() <= (inGameLength - 10) && pluginArena.getTimer() > (inGameLength - 15)) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_SWORD_SOON").asKey().integer(pluginArena.getTimer() - (inGameLength - 15)).arena(pluginArena).sendArena();
for(Player p : pluginArena.getPlayers()) {
XSound.UI_BUTTON_CLICK.play(p.getLocation(), 1, 1);
}
if(pluginArena.getTimer() == (inGameLength - 14)) {
if(pluginArena.getMurdererList().isEmpty()) getPlugin().getArenaManager().stopGame(false, pluginArena);
for(Player p : pluginArena.getMurdererList()) {
IUser murderer = getPlugin().getUserManager().getUser(p);
if(murderer.isSpectator() || !p.isOnline())
continue;
p.getInventory().setHeldItemSlot(0);
ItemPosition.setItem(murderer, ItemPosition.MURDERER_SWORD, pluginArena.getPlugin().getSwordSkinManager().getRandomSwordSkin(p));
}
}
}
}
private void spawnGold(Arena pluginArena) {
//don't spawn it every time
if(pluginArena.getSpawnGoldTimer() == pluginArena.getSpawnGoldTime()) {
spawnSomeGold(pluginArena);
pluginArena.setSpawnGoldTimer(0);
} else {
pluginArena.setSpawnGoldTimer(pluginArena.getSpawnGoldTimer() + 1);
}
}
private void givePlayerSurviveReward(Arena pluginArena) {
if(pluginArena.getTimer() % 30 == 0) {
new TitleBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_TIME_LEFT").arena(pluginArena).sendArena();
for(Player p : pluginArena.getPlayersLeft()) {
IUser user = getPlugin().getUserManager().getUser(p);
if(Role.isRole(Role.INNOCENT, user, pluginArena)) {
ArenaUtils.addScore(user, ArenaUtils.ScoreAction.SURVIVE_TIME, 0);
}
}
}
}
private void addInnocentLocator(Arena pluginArena) {
if(pluginArena.getTimer() <= 30 || pluginArena.getPlayersLeft().size() == pluginArena.aliveMurderer() + 1) {
if(getPlugin().getConfigPreferences().getOption("MURDERER_LOCATOR")) {
ArenaUtils.updateInnocentLocator(pluginArena);
}
}
}
private void spawnSomeGold(Arena arena) {
int spawnPointsSize = arena.getGoldSpawnPoints().size();
if(spawnPointsSize == 0) {
return;
}
//may users want to disable it and want much gold on their map xD
if(!getPlugin().getConfigPreferences().getOption("GOLD_LIMITER")) {
//do not exceed amount of gold per spawn
if(arena.getGoldSpawned().size() >= spawnPointsSize) {
return;
}
}
if(getPlugin().getConfigPreferences().getOption("GOLD_SPAWNER_MODE_ALL")) {
for(Location location : arena.getGoldSpawnPoints()) {
dropGold(arena, location);
}
} else {
Location loc = arena.getGoldSpawnPoints().get(getPlugin().getRandom().nextInt(spawnPointsSize));
dropGold(arena, loc);
}
}
private void dropGold(Arena arena, Location location) {
//spawn maximum 1 gold per spawner
if(!getPlugin().getConfigPreferences().getOption("GOLD_MULTIPLE")) {
for(Entity entity : location.getWorld().getNearbyEntities(location, 2, 2, 2)) {
if(entity instanceof Item && XMaterial.GOLD_INGOT.isSimilar(((Item) entity).getItemStack())) {
return;
}
}
}
arena.getGoldSpawned().add(location.getWorld().dropItem(location, new ItemStack(Material.GOLD_INGOT, 1)));
getPlugin().getPowerupRegistry().spawnPowerup(location, arena);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/states/RestartingState.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.states;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginRestartingState;
import plugily.projects.murdermystery.arena.Arena;
/**
* @author Plajer
*
* Created at 03.06.2019
*/
public class RestartingState extends PluginRestartingState {
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
Arena pluginArena = (Arena) getPlugin().getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
if(arena.getTimer() <= 0) {
if(pluginArena.isGoldVisuals()) {
pluginArena.startGoldVisuals();
}
}
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/states/StartingState.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.arena.states;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginStartingState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.utils.actionbar.ActionBar;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.ArenaUtils;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.arena.special.pray.PrayerRegistry;
import plugily.projects.murdermystery.utils.ItemPosition;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Plajer
*
Created at 03.06.2019
*/
public class StartingState extends PluginStartingState {
int maxmurderer = 1;
int maxdetectives = 1;
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
Arena pluginArena = (Arena) getPlugin().getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
if(!pluginArena.isHideChances()) {
for(Player player : arena.getPlayersLeft()) {
pluginArena.getPlugin().getActionBarManager().addActionBar(player, new ActionBar((new MessageBuilder("IN_GAME_MESSAGES_ARENA_ROLE_CHANCES_ACTION_BAR")).asKey().player(player).arena(pluginArena), ActionBar.ActionBarType.DISPLAY));
}
}
if(arena.getTimer() == 0 || arena.isForceStart()) {
int size = pluginArena.getPlayerSpawnPoints().size();
for(Player player : arena.getPlayersLeft()) {
VersionUtils.teleport(player, pluginArena.getPlayerSpawnPoints().get(getPlugin().getRandom().nextInt(size)));
IUser user = arena.getPlugin().getUserManager().getUser(player);
user.resetNonePersistentStatistics();
PrayerRegistry.getRush().remove(player);
PrayerRegistry.getBan().remove(player);
ArenaUtils.updateNameTagsVisibility(player);
player.setGameMode(GameMode.ADVENTURE);
getPlugin().getActionBarManager().clearActionBarsFromPlayer(player);
}
Set playersToSet = new HashSet<>(arena.getPlayersLeft());
getMaxRolesToSet(pluginArena);
addRole(pluginArena, Role.MURDERER, playersToSet);
addRole(pluginArena, Role.DETECTIVE, playersToSet);
for(Player player : playersToSet) {
new TitleBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_INNOCENT").asKey().player(player).arena(pluginArena).sendPlayer();
}
arena.getPlugin().getDebugger().debug("After: Arena: {0} | Detectives = {1}, Murders = {2}, Players = {3} | Players: Detectives = {4}, Murders = {5}", arena.getId(), maxdetectives, maxmurderer, arena.getPlayersLeft().size(), pluginArena.getDetectiveList(), pluginArena.getMurdererList());
// Load and append special blocks hologram
pluginArena.getSpecialBlocks().forEach(pluginArena::loadSpecialBlock);
}
}
private void addRole(Arena arena, Role role, Set playersToSet) {
String roleName = role.toString();
List chancesRanking = getPlugin().getUserManager().getUsers(arena).stream().filter(user -> playersToSet.contains(user.getPlayer())).sorted(Comparator.comparingInt(user -> arena.getContributorValue(role, user))).collect(Collectors.toList());
Collections.reverse(chancesRanking);
List chancesPlayer = new ArrayList<>();
for(IUser user : chancesRanking) {
chancesPlayer.add(user.getPlayer());
}
getPlugin().getDebugger().debug("Arena {0} | Role add {1} | List {2}", arena.getId(), roleName, chancesPlayer);
int amount = role == Role.MURDERER ? maxmurderer : maxdetectives;
for(int i = 0; i < amount; i++) {
IUser user = chancesRanking.get(i);
Player userPlayer = user.getPlayer();
arena.setCharacter(role, userPlayer);
arena.resetContributorValue(role, user);
playersToSet.remove(userPlayer);
new TitleBuilder("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_" + roleName).asKey().arena(arena).player(userPlayer).sendPlayer();
if(role == Role.MURDERER) {
arena.getMurdererList().add(userPlayer);
} else if(role == Role.DETECTIVE) {
arena.getDetectiveList().add(userPlayer);
userPlayer.getInventory().setHeldItemSlot(0);
Bukkit.getScheduler().runTaskLater(arena.getPlugin(), () -> {
ItemPosition.setItem(user, ItemPosition.BOW, new ItemStack(Material.BOW, 1));
ItemPosition.setItem(user, ItemPosition.INFINITE_ARROWS, new ItemStack(Material.ARROW, getPlugin().getConfig().getInt("Bow.Amount.Arrows.Detective", 3)));
}, 20);
}
}
}
private void getMaxRolesToSet(Arena arena) {
int playersSize = arena.getPlayersLeft().size();
arena.getPlugin().getDebugger().debug("Before: Arena: {0} | Detectives = {1}, Murders = {2}, Players = {3} | Configured: Detectives = {4}, Murders = {5}", arena.getId(), maxdetectives, maxmurderer, playersSize, arena.getArenaOption("DETECTIVE_DIVIDER"), arena.getArenaOption("MURDERER_DIVIDER"));
if(arena.getArenaOption("MURDERER_DIVIDER") > 1 && playersSize > arena.getArenaOption("MURDERER_DIVIDER")) {
maxmurderer = (playersSize / arena.getArenaOption("MURDERER_DIVIDER"));
}
if(arena.getArenaOption("DETECTIVE_DIVIDER") > 1 && playersSize > arena.getArenaOption("DETECTIVE_DIVIDER")) {
maxdetectives = (playersSize / arena.getArenaOption("DETECTIVE_DIVIDER"));
}
if(playersSize - (maxmurderer + maxdetectives) < 1) {
arena.getPlugin().getDebugger().debug("{0} Murderers and detectives amount was reduced because there are not enough players", arena.getId());
// Make sure to have one innocent!
if(maxdetectives > 1) {
maxdetectives--;
} else if(maxmurderer > 1) {
maxmurderer--;
}
}
arena.getPlugin().getDebugger().debug("After: Arena: {0} | Detectives = {1}, Murders = {2}, Players = {3} | Configured: Detectives = {4}, Murders = {5}", arena.getId(), maxdetectives, maxmurderer, playersSize, arena.getArenaOption("DETECTIVE_DIVIDER"), arena.getArenaOption("MURDERER_DIVIDER"));
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/arena/states/WaitingState.java
================================================
package plugily.projects.murdermystery.arena.states;
import org.bukkit.configuration.file.FileConfiguration;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginWaitingState;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.murdermystery.arena.Arena;
public class WaitingState extends PluginWaitingState {
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
Arena pluginArena = (Arena) getPlugin().getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return;
}
if(arena.getTimer() <= 0) {
FileConfiguration config =
ConfigUtils.getConfig(getPlugin(), "arenas");
pluginArena.setGoldVisuals(config.getBoolean(pluginArena.getId() + ".goldvisuals"));
}
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/boot/AdditionalValueInitializer.java
================================================
package plugily.projects.murdermystery.boot;
import plugily.projects.minigamesbox.api.preferences.IConfigPreferences;
import plugily.projects.minigamesbox.classic.api.StatisticType;
import plugily.projects.minigamesbox.classic.api.StatsStorage;
import plugily.projects.minigamesbox.classic.arena.options.ArenaOption;
import plugily.projects.minigamesbox.classic.arena.options.ArenaOptionManager;
import plugily.projects.minigamesbox.classic.handlers.items.SpecialItemManager;
import plugily.projects.minigamesbox.classic.handlers.permissions.PermissionCategory;
import plugily.projects.minigamesbox.classic.handlers.permissions.PermissionsManager;
import plugily.projects.minigamesbox.classic.handlers.reward.RewardType;
import plugily.projects.minigamesbox.classic.handlers.reward.RewardsFactory;
import plugily.projects.minigamesbox.classic.preferences.ConfigOption;
import plugily.projects.murdermystery.Main;
/**
* @author Tigerpanzer_02
*
* Created at 15.10.2022
*/
public class AdditionalValueInitializer {
private final Main plugin;
public AdditionalValueInitializer(Main plugin) {
this.plugin = plugin;
registerConfigOptions();
registerStatistics();
registerPermission();
registerRewards();
registerSpecialItems();
registerArenaOptions();
}
private void registerConfigOptions() {
getConfigPreferences().registerOption("CORPSES_INTEGRATION_OVERWRITE", new ConfigOption("Corpses.Integration-Overwrite", true));
getConfigPreferences().registerOption("BOW_KILL_DETECTIVE", new ConfigOption("Bow.Kill-Detective", true));
getConfigPreferences().registerOption("HIDE_DEATH", new ConfigOption("Hide.Death", false));
getConfigPreferences().registerOption("HIDE_NAMETAGS", new ConfigOption("Hide.Nametags", false));
getConfigPreferences().registerOption("GOLD_SPAWNER_MODE_ALL", new ConfigOption("Gold.Spawner-Mode", false));
getConfigPreferences().registerOption("GOLD_LIMITER", new ConfigOption("Gold.Limiter", false));
getConfigPreferences().registerOption("GOLD_MULTIPLE", new ConfigOption("Gold.Multiple", false));
getConfigPreferences().registerOption("MURDERER_LOCATOR", new ConfigOption("Murderer.Locator", true));
}
private void registerStatistics() {
getStatsStorage().registerStatistic("KILLS", new StatisticType("kills", true, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("DEATHS", new StatisticType("deaths", true, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("HIGHEST_SCORE", new StatisticType("highest_score", true, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("CONTRIBUTION_DETECTIVE", new StatisticType("contribution_detective", true, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("CONTRIBUTION_MURDERER", new StatisticType("contribution_murderer", true, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("PASS_MURDERER", new StatisticType("pass_murderer", true, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("PASS_DETECTIVE", new StatisticType("pass_detective", true, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("LOCAL_PRAISES", new StatisticType("local_praises", false, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("LOCAL_SCORE", new StatisticType("local_score", false, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("LOCAL_PRAY", new StatisticType("local_pray", false, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("LOCAL_GOLD", new StatisticType("local_gold", false, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("LOCAL_KILLS", new StatisticType("local_kills", false, "int(11) NOT NULL DEFAULT '0'"));
getStatsStorage().registerStatistic("LOCAL_CURRENT_PRAY", new StatisticType("local_current_pray", false, "int(11) NOT NULL DEFAULT '0'"));
}
private void registerPermission() {
getPermissionsManager().registerPermissionCategory("CHANCES_BOOSTER", new PermissionCategory("Chances-Boost", null));
getPermissionsManager().registerPermissionCategory("MURDERER_BOOSTER", new PermissionCategory("Murderer-Boost", null));
getPermissionsManager().registerPermissionCategory("DETECTIVE_BOOSTER", new PermissionCategory("Detective-Boost", null));
}
private void registerRewards() {
getRewardsHandler().registerRewardType("KILL_DETECTIVE", new RewardType("detective-kill"));
getRewardsHandler().registerRewardType("KILL_MURDERER", new RewardType("murderer-kill"));
getRewardsHandler().registerRewardType("WIN", new RewardType("win"));
getRewardsHandler().registerRewardType("LOSE", new RewardType("lose"));
getRewardsHandler().registerRewardType("PLAYER_DEATH", new RewardType("player-death"));
getRewardsHandler().registerRewardType("GOLD_PICKUP", new RewardType("gold-pickup"));
}
private void registerSpecialItems() {
getSpecialItemManager().registerSpecialItem("ROLE_PASS", "Role-Pass");
}
private void registerArenaOptions() {
getArenaOptionManager().registerArenaOption("DETECTIVE_DIVIDER", new ArenaOption("playerperdetective", 1));
getArenaOptionManager().registerArenaOption("MURDERER_DIVIDER", new ArenaOption("playerpermurderer", 1));
}
private IConfigPreferences getConfigPreferences() {
return plugin.getConfigPreferences();
}
private StatsStorage getStatsStorage() {
return plugin.getStatsStorage();
}
private PermissionsManager getPermissionsManager() {
return plugin.getPermissionsManager();
}
private RewardsFactory getRewardsHandler() {
return plugin.getRewardsHandler();
}
private SpecialItemManager getSpecialItemManager() {
return plugin.getSpecialItemManager();
}
private ArenaOptionManager getArenaOptionManager() {
return plugin.getArenaOptionManager();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/boot/MessageInitializer.java
================================================
package plugily.projects.murdermystery.boot;
import plugily.projects.minigamesbox.classic.handlers.language.Message;
import plugily.projects.minigamesbox.classic.handlers.language.MessageManager;
import plugily.projects.minigamesbox.classic.utils.services.locale.Locale;
import plugily.projects.minigamesbox.classic.utils.services.locale.LocaleRegistry;
import plugily.projects.murdermystery.Main;
import java.util.Arrays;
/**
* @author Tigerpanzer_02
*
* Created at 15.10.2022
*/
public class MessageInitializer {
private final Main plugin;
public MessageInitializer(Main plugin) {
this.plugin = plugin;
}
public void registerMessages() {
getMessageManager().registerMessage("", new Message("", ""));
getMessageManager().registerMessage("SCOREBOARD_ROLES_DETECTIVE", new Message("Scoreboard.Roles.Detective", ""));
getMessageManager().registerMessage("SCOREBOARD_ROLES_MURDERER", new Message("Scoreboard.Roles.Murderer", ""));
getMessageManager().registerMessage("SCOREBOARD_ROLES_INNOCENT", new Message("Scoreboard.Roles.Innocent", ""));
getMessageManager().registerMessage("SCOREBOARD_ROLES_DEAD", new Message("Scoreboard.Roles.Dead", ""));
getMessageManager().registerMessage("SCOREBOARD_DETECTIVE_ALIVE", new Message("Scoreboard.Detective.Alive", ""));
getMessageManager().registerMessage("SCOREBOARD_DETECTIVE_BOW_DROPPED", new Message("Scoreboard.Detective.Bow.Dropped", ""));
getMessageManager().registerMessage("SCOREBOARD_DETECTIVE_BOW_PICKED", new Message("Scoreboard.Detective.Bow.Picked", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_MURDERER_STOPPED", new Message("In-Game.Messages.Game-End.Placeholders.Murderer.Stopped", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_MURDERER_KILLED_YOU", new Message("In-Game.Messages.Game-End.Placeholders.Murderer.Killed.You", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_MURDERER_KILLED_ALL", new Message("In-Game.Messages.Game-End.Placeholders.Murderer.Killed.All", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_INNOCENT_KILLED_YOU", new Message("In-Game.Messages.Game-End.Placeholders.Innocent.Killed.You", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_INNOCENT_KILLED_WRONGLY", new Message("In-Game.Messages.Game-End.Placeholders.Innocent.Killed.All", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_NOBODY", new Message("In-Game.Messages.Game-End.Placeholders.Nobody", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_ROLE_CHANCES_ACTION_BAR", new Message("In-Game.Messages.Arena.Chances.Action-Bar", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_COOLDOWN", new Message("In-Game.Messages.Arena.Cooldown", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_LOCATOR_BOW", new Message("In-Game.Messages.Arena.Locator.Bow", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_LOCATOR_INNOCENT", new Message("In-Game.Messages.Arena.Locator.Innocent", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_LOCATOR_WATCH_OUT", new Message("In-Game.Messages.Arena.Locator.Watch-Out", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_NAME", new Message("In-Game.Messages.Arena.Pass.Name", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_ROLE_MURDERER_NAME", new Message("In-Game.Messages.Arena.Pass.Role.Murderer.Name", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_ROLE_MURDERER_LORE", new Message("In-Game.Messages.Arena.Pass.Role.Murderer.Lore", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_ROLE_DETECTIVE_NAME", new Message("In-Game.Messages.Arena.Pass.Role.Detective.Name", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_ROLE_DETECTIVE_LORE", new Message("In-Game.Messages.Arena.Pass.Role.Detective.Lore", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_FAIL", new Message("In-Game.Messages.Arena.Pass.Fail", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_SUCCESS", new Message("In-Game.Messages.Arena.Pass.Success", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PASS_CHANGE", new Message("In-Game.Messages.Arena.Pass.Change", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_TIME_LEFT", new Message("In-Game.Messages.Arena.Playing.Time-Left", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_CHANGE", new Message("In-Game.Messages.Arena.Playing.Role.Change", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_MURDERER", new Message("In-Game.Messages.Arena.Playing.Role.Murderer", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_DETECTIVE", new Message("In-Game.Messages.Arena.Playing.Role.Detective", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_ROLE_INNOCENT", new Message("In-Game.Messages.Arena.Playing.Role.Innocent", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_BONUS", new Message("In-Game.Messages.Arena.Playing.Score.Bonus", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_GOLD", new Message("In-Game.Messages.Arena.Playing.Score.Gold", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_KILL_PLAYER", new Message("In-Game.Messages.Arena.Playing.Score.Action.Kill.Player", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_KILL_MURDERER", new Message("In-Game.Messages.Arena.Playing.Score.Action.Kill.Murderer", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_KILL_INNOCENT", new Message("In-Game.Messages.Arena.Playing.Score.Action.Kill.Innocent", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_PICKUP_GOLD", new Message("In-Game.Messages.Arena.Playing.Score.Action.Pickup.Gold", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_SURVIVING_TIME", new Message("In-Game.Messages.Arena.Playing.Score.Action.Surviving.Time", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_SURVIVING_END", new Message("In-Game.Messages.Arena.Playing.Score.Action.Surviving.End", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_WIN", new Message("In-Game.Messages.Arena.Playing.Score.Action.Win", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SCORE_ACTION_DETECTIVE", new Message("In-Game.Messages.Arena.Playing.Score.Action.Detective", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SWORD_SOON", new Message("In-Game.Messages.Arena.Playing.Sword.Soon", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_CAULDRON_POTION", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Cauldron.Potion", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_CAULDRON_HOLOGRAM", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Cauldron.Hologram", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_NOT_ENOUGH_GOLD", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Not-Enough-Gold", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_HOLOGRAM", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Hologram", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_CHAT", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Chat", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PAY", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Pay", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_HEARD", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Heard", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_FEELING_BLESSED", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Feeling.Blessed", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_FEELING_CURSED", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Feeling.Cursed", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_DETECTIVE_REVELATION", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Gifts.Detective-Revelation", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_GOLD_RUSH", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Gifts.Gold-Rush", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_SINGLE_COMPENSATION", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Gifts.Single-Compensation", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_GIFTS_BOW", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Gifts.Bow", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_SLOWNESS", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Curses.Slowness", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_BLINDNESS", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Curses.Blindness", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_GOLD", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Curses.Gold", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_SPECIAL_BLOCKS_PRAY_PRAISE_CURSES_DEATH", new Message("In-Game.Messages.Arena.Playing.Special-Blocks.Pray.Praise.Curses.Death", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_BOW_DROPPED", new Message("In-Game.Messages.Arena.Playing.Bow.Dropped", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_BOW_PICKUP", new Message("In-Game.Messages.Arena.Playing.Bow.Pickup", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_BOW_SHOT_GOLD", new Message("In-Game.Messages.Arena.Playing.Bow.Shot.Gold", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ARENA_PLAYING_BOW_SHOT_TITLE", new Message("In-Game.Messages.Arena.Playing.Bow.Shot.Title", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_CONTRIBUTION_DETECTIVE", new Message("Leaderboard.Statistics.Detective-Contribution", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_CONTRIBUTION_MURDERER", new Message("Leaderboard.Statistics.Murderer-Contribution", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_PASS_DETECTIVE", new Message("Leaderboard.Statistics.Detective-Pass", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_PASS_MURDERER", new Message("Leaderboard.Statistics.Murderer-Pass", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_KILLS", new Message("Leaderboard.Statistics.Kills", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_DEATHS", new Message("Leaderboard.Statistics.Deaths", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_HIGHEST_SCORE", new Message("Leaderboard.Statistics.Highest-Score", ""));
}
private MessageManager getMessageManager() {
return plugin.getMessageManager();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/boot/PlaceholderInitializer.java
================================================
package plugily.projects.murdermystery.boot;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.api.user.IUserManager;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.placeholder.Placeholder;
import plugily.projects.minigamesbox.classic.handlers.placeholder.PlaceholderManager;
import plugily.projects.minigamesbox.number.NumberUtils;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.ArenaRegistry;
import plugily.projects.murdermystery.arena.role.Role;
/**
* @author Tigerpanzer_02
*
* Created at 15.10.2022
*/
public class PlaceholderInitializer {
private final Main plugin;
public PlaceholderInitializer(Main plugin) {
this.plugin = plugin;
registerPlaceholders();
}
private void registerPlaceholders() {
getPlaceholderManager().registerPlaceholder(new Placeholder("detective_list", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
StringBuilder detectives = new StringBuilder();
for(Player p : pluginArena.getDetectiveList()) {
detectives.append(p.getName()).append(", ");
}
int index = detectives.length() - 2;
if(index > 0 && index < detectives.length()) {
detectives.deleteCharAt(index);
}
return (pluginArena.isDetectiveDead() ? ChatColor.STRIKETHROUGH : "")
+ detectives.toString();
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("murderer_list", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
StringBuilder murders = new StringBuilder();
for(Player p : pluginArena.getMurdererList()) {
IUser user = getUserManager().getUser(p);
int localKills = user.getStatistic("LOCAL_KILLS");
murders.append(p.getName());
if(pluginArena.getMurdererList().size() > 1) {
murders.append(" (").append(localKills).append("), ");
}
}
if(pluginArena.getMurdererList().size() > 1) {
murders.deleteCharAt(murders.length() - 2);
}
return (pluginArena.aliveMurderer() == 1 ? "" : ChatColor.STRIKETHROUGH)
+ murders.toString();
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("murderer_kills", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
int murdererKills = 0;
for(Player p : pluginArena.getMurdererList()) {
IUser user = getUserManager().getUser(p);
int localKills = user.getStatistic("LOCAL_KILLS");
murdererKills += localKills;
}
return Integer.toString(murdererKills);
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("hero", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
Player hero = pluginArena.getCharacter(Arena.CharacterType.HERO);
return hero != null ? hero.getName() : new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_NOBODY").asKey().build();
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("murderer_chance", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
IUser user = getUserManager().getUser(player);
return NumberUtils.round(((double) pluginArena.getContributorValue(Role.MURDERER, user) / (double) pluginArena.getTotalRoleChances(Role.MURDERER)) * 100.0, 0) + "%";
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("detective_chance", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
IUser user = getUserManager().getUser(player);
return NumberUtils.round(((double) pluginArena.getContributorValue(Role.DETECTIVE, user) / (double) pluginArena.getTotalRoleChances(Role.DETECTIVE)) * 100.0, 0) + "%";
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("detective_status", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
if(pluginArena.isDetectiveDead()) {
if(!pluginArena.isCharacterSet(Arena.CharacterType.FAKE_DETECTIVE)) {
return new MessageBuilder("SCOREBOARD_DETECTIVE_BOW_DROPPED").asKey().build();
} else {
return new MessageBuilder("SCOREBOARD_DETECTIVE_BOW_PICKED").asKey().build();
}
} else {
return new MessageBuilder("SCOREBOARD_DETECTIVE_ALIVE").asKey().build();
}
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("innocent_size", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
int innocents = 0;
for(Player p : arena.getPlayersLeft()) {
if(!Role.isRole(Role.MURDERER, getUserManager().getUser(p))) {
innocents++;
}
}
return Integer.toString(innocents);
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("player_role", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
IUser user = getUserManager().getUser(player);
String role;
if(pluginArena.isDeathPlayer(player)) {
role = new MessageBuilder("SCOREBOARD_ROLES_DEAD").asKey().build();
} else if(Role.isRole(Role.MURDERER, user, arena)) {
role = new MessageBuilder("SCOREBOARD_ROLES_MURDERER").asKey().build();
} else if(Role.isRole(Role.ANY_DETECTIVE, user, arena)) {
role = new MessageBuilder("SCOREBOARD_ROLES_DETECTIVE").asKey().build();
} else {
role = new MessageBuilder("SCOREBOARD_ROLES_INNOCENT").asKey().build();
}
return role;
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("summary_player", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
return getSummary(player, arena);
}
@Nullable
private String getSummary(Player player, IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
String summaryEnding;
if(pluginArena.getMurdererList().containsAll(pluginArena.getPlayersLeft())
&& pluginArena.getMurdererList().contains(player)) {
summaryEnding = new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_WIN").asKey().arena(pluginArena).build();
} else if(!pluginArena.getMurdererList().containsAll(pluginArena.getPlayersLeft())
&& !pluginArena.getMurdererList().contains(player)) {
summaryEnding = new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_WIN").asKey().arena(pluginArena).build();
} else {
summaryEnding = new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_LOSE").asKey().arena(pluginArena).build();
}
return summaryEnding;
}
});
getPlaceholderManager().registerPlaceholder(new Placeholder("summary", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
@Override
public String getValue(Player player, IPluginArena arena) {
return getSummary(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getSummary(arena);
}
@Nullable
private String getSummary(IPluginArena arena) {
Arena pluginArena = getArenaRegistry().getArena(arena.getId());
if(pluginArena == null) {
return null;
}
String summaryEnding;
if(pluginArena.getMurdererList().containsAll(pluginArena.getPlayersLeft())) {
summaryEnding = new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_MURDERER_KILLED_ALL").asKey().arena(pluginArena).build();
} else {
summaryEnding = new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_MURDERER_STOPPED").asKey().arena(pluginArena).build();
}
return summaryEnding;
}
});
}
private PlaceholderManager getPlaceholderManager() {
return plugin.getPlaceholderManager();
}
private ArenaRegistry getArenaRegistry() {
return plugin.getArenaRegistry();
}
private IUserManager getUserManager() {
return plugin.getUserManager();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/commands/arguments/ArgumentsRegistry.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.commands.arguments;
import plugily.projects.minigamesbox.classic.commands.arguments.PluginArgumentsRegistry;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.commands.arguments.admin.RolePassArgument;
import plugily.projects.murdermystery.commands.arguments.admin.arena.SpecialBlockRemoverArgument;
import plugily.projects.murdermystery.commands.arguments.game.RoleSelectorArgument;
/**
* @author Plajer
*
* Created at 11.01.2019
*/
public class ArgumentsRegistry extends PluginArgumentsRegistry {
public ArgumentsRegistry(Main plugin) {
super(plugin);
//register basic arugments
new RoleSelectorArgument(this);
//register admin related arguments
new SpecialBlockRemoverArgument(this);
new RolePassArgument(this);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/commands/arguments/admin/RolePassArgument.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.commands.arguments.admin;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.number.NumberUtils;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.commands.arguments.ArgumentsRegistry;
/**
* @author Tigerpanzer_02
*
* Created at 13.06.2021
*/
public class RolePassArgument {
public RolePassArgument(ArgumentsRegistry registry) {
registry.mapArgument("murdermysteryadmin", new LabeledCommandArgument("rolepass", "murdermystery.admin.rolepass", CommandArgument.ExecutorType.BOTH,
new LabelData("/mma rolepass [player]", "/mma rolepass [player] ", "&7Add or remove rolepass\n&6Permission: &7murdermystery.admin.rolepass")) {
@Override
public void execute(CommandSender sender, String[] args) {
if(args.length < 4) {
sender.sendMessage(ChatColor.RED + "Command: /mma rolepass [player]");
return;
}
//add/remove
String addOrRemove = args[1];
if(!addOrRemove.equalsIgnoreCase("add") && !addOrRemove.equalsIgnoreCase("remove") && !addOrRemove.equalsIgnoreCase("set")) {
sender.sendMessage(ChatColor.RED + "Command: /mma rolepass [player]");
return;
}
String roleArg = args[2];
Role role = Role.MURDERER;
try {
role = Role.valueOf(roleArg.toUpperCase());
} catch(IllegalArgumentException exception) {
sender.sendMessage(ChatColor.RED + "Command: /mma rolepass [player]");
return;
}
if(role != Role.MURDERER && role != Role.DETECTIVE) {
sender.sendMessage(ChatColor.RED + "Command: /mma rolepass [player]");
return;
}
java.util.Optional opt = NumberUtils.parseInt(args[3]);
if(!opt.isPresent()) {
sender.sendMessage(ChatColor.RED + "Command: /mma rolepass [player]");
return;
}
int amount = opt.orElse(0);
//player
Player player = args.length == 5 ? Bukkit.getPlayerExact(args[4]) : (Player) sender;
if(player == null) {
new MessageBuilder("COMMANDS_PLAYER_NOT_FOUND").asKey().send(sender);
return;
}
IUser user = registry.getPlugin().getUserManager().getUser(player);
switch(addOrRemove.toLowerCase()) {
case "add":
if(role == Role.MURDERER) {
user.adjustStatistic("PASS_MURDERER", amount);
} else {
user.adjustStatistic("PASS_DETECTIVE", amount);
}
break;
case "remove":
if(role == Role.MURDERER) {
user.adjustStatistic("PASS_MURDERER", -amount);
} else {
user.adjustStatistic("PASS_DETECTIVE", -amount);
}
break;
case "set":
if(role == Role.MURDERER) {
user.setStatistic("PASS_MURDERER", amount);
} else {
user.setStatistic("PASS_DETECTIVE", amount);
}
break;
default:
break;
}
if(role == Role.MURDERER) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_CHANGE").asKey().player(player).integer(user.getStatistic("PASS_MURDERER")).value(Role.MURDERER.name()).sendPlayer();
} else {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_CHANGE").asKey().player(player).integer(user.getStatistic("PASS_DETECTIVE")).value(Role.DETECTIVE.name()).sendPlayer();
}
}
});
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/commands/arguments/admin/arena/SpecialBlockRemoverArgument.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.commands.arguments.admin.arena;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.minigamesbox.classic.utils.serialization.LocationSerializer;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.special.SpecialBlock;
import plugily.projects.murdermystery.commands.arguments.ArgumentsRegistry;
import java.util.ArrayList;
import java.util.List;
/**
* @author Tigerpanzer_02
*
Created at 22.10.2020
*/
public class SpecialBlockRemoverArgument {
public SpecialBlockRemoverArgument(ArgumentsRegistry registry) {
registry.mapArgument(
"murdermysteryadmin",
new LabeledCommandArgument(
"removeblock",
"murdermystery.admin.removeblock",
CommandArgument.ExecutorType.PLAYER,
new LabelData(
"/mma removeblock",
"/mma removeblock",
"&7Removes the special block you are looking at \n&6Permission: &7murdermystery.admin.removeblock")) {
@Override
public void execute(CommandSender sender, String[] args) {
// no need for check as argument is only for players
Player player = (Player) sender;
Block targetBlock = player.getTargetBlock(null, 7);
if (targetBlock.getType() == Material.CAULDRON
|| targetBlock.getType() == XMaterial.ENCHANTING_TABLE.parseMaterial()) {
for (IPluginArena arena : registry.getPlugin().getArenaRegistry().getArenas()) {
Arena pluginArena = (Arena) registry.getPlugin().getArenaRegistry().getArena(arena.getId());
// do not check arenas that could not be the case
if (pluginArena.getSpecialBlocks().isEmpty()) {
continue;
}
if (pluginArena.getPlayerSpawnPoints().get(0).getWorld() != player.getWorld()) {
continue;
}
// get all special blocks
for (SpecialBlock specialBlock : new ArrayList<>(pluginArena.getSpecialBlocks())) {
// check if targetBlock is specialblock
if (specialBlock.getLocation().getBlock().equals(targetBlock)) {
// get special blocks from config
FileConfiguration config =
ConfigUtils.getConfig(registry.getPlugin(), "arenas");
// remove special block from arena
pluginArena.getSpecialBlocks().remove(specialBlock);
// remove hologram
if (specialBlock.getArmorStandHologram() != null) {
specialBlock.getArmorStandHologram().delete();
}
// remove special block from arena file
String path =
targetBlock.getType() == Material.CAULDRON
? ".mystery-cauldrons"
: ".confessionals";
String serializedLoc =
LocationSerializer.locationToString(specialBlock.getLocation());
List specialBlocksType =
config.getStringList("instances." + arena.getId() + path);
specialBlocksType.remove(serializedLoc);
config.set("instances." + arena.getId() + path, specialBlocksType);
// save arena config after removing special block
ConfigUtils.saveConfig(registry.getPlugin(), config, "arenas");
new MessageBuilder("&cRemoved special block at loc "
+ serializedLoc
+ " from arena "
+ arena.getId()).player(player).sendPlayer();
return;
}
}
}
}
new MessageBuilder("&cPlease target an special block to continue!").player(player).sendPlayer();
}
});
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/commands/arguments/game/RoleSelectorArgument.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.commands.arguments.game;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.PluginMain;
import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.inventory.common.item.SimpleClickableItem;
import plugily.projects.minigamesbox.inventory.normal.NormalFastInv;
import plugily.projects.murdermystery.arena.role.Role;
import plugily.projects.murdermystery.commands.arguments.ArgumentsRegistry;
import java.util.ArrayList;
import java.util.List;
public class RoleSelectorArgument implements Listener {
public RoleSelectorArgument(ArgumentsRegistry registry) {
registry.mapArgument("murdermystery", new LabeledCommandArgument("roleselector", "murdermystery.command.roleselector", CommandArgument.ExecutorType.PLAYER,
new LabelData("/mm roleselector", "/mm roleselector", "&7Select a role\n&6Permission: &7murdermystery.command.roleselector")) {
@Override
public void execute(CommandSender sender, String[] args) {
Player player = (Player) sender;
if(registry.getPlugin().getBukkitHelper().checkIsInGameInstance(player)) {
openRolePassMenu(player, registry.getPlugin());
}
}
});
}
public static void openRolePassMenu(Player player, PluginMain plugin) {
NormalFastInv gui = new NormalFastInv(plugin.getBukkitHelper().serializeInt(Role.values().length), new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_NAME").asKey().build());
List descriptionMurderer = new ArrayList<>();
plugin.getLanguageManager().getLanguageListFromKey("IN_GAME_MESSAGES_ARENA_PASS_ROLE_MURDERER_LORE").forEach(string -> descriptionMurderer.add(new MessageBuilder(string).integer(plugin.getUserManager().getUser(player).getStatistic("PASS_MURDERER")).build()));
gui.addItem(new SimpleClickableItem(new ItemBuilder(XMaterial.IRON_SWORD.parseMaterial())
.name(new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_ROLE_MURDERER_NAME").asKey().build())
.lore(descriptionMurderer)
.build(), event -> {
IUser user = plugin.getUserManager().getUser(player);
if(user.getStatistic("PASS_MURDERER") <= 0) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_FAIL").asKey().player(player).value(Role.MURDERER.name()).sendPlayer();
return;
}
user.adjustStatistic("PASS_MURDERER", -1);
user.adjustStatistic("CONTRIBUTION_MURDERER", 999999999);
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_SUCCESS").asKey().player(player).value(Role.MURDERER.name()).sendPlayer();
}));
List descriptionDetective = new ArrayList<>();
plugin.getLanguageManager().getLanguageListFromKey("IN_GAME_MESSAGES_ARENA_PASS_ROLE_DETECTIVE_LORE").forEach(string -> descriptionDetective.add(new MessageBuilder(string).integer(plugin.getUserManager().getUser(player).getStatistic("PASS_DETECTIVE")).build()));
gui.addItem(new SimpleClickableItem(new ItemBuilder(XMaterial.BOW.parseMaterial())
.name(new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_ROLE_DETECTIVE_NAME").asKey().build())
.lore(descriptionDetective)
.build(), event -> {
IUser user = plugin.getUserManager().getUser(player);
if(user.getStatistic("PASS_DETECTIVE") <= 0) {
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_FAIL").asKey().player(player).value(Role.DETECTIVE.name()).sendPlayer();
return;
}
user.adjustStatistic("PASS_DETECTIVE", -1);
user.adjustStatistic("CONTRIBUTION_DETECTIVE", 999999999);
new MessageBuilder("IN_GAME_MESSAGES_ARENA_PASS_SUCCESS").asKey().player(player).value(Role.DETECTIVE.name()).sendPlayer();
}));
gui.refresh();
gui.open(player);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/events/PluginEvents.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.events;
import org.bukkit.Location;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
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.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.arena.ArenaUtils;
import plugily.projects.murdermystery.arena.role.Role;
/**
* @author Plajer
*
Created at 05.08.2018
*/
public class PluginEvents implements Listener {
private final Main plugin;
public PluginEvents(Main plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onSwordThrow(PlayerInteractEvent event) {
if(event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.PHYSICAL) {
return;
}
Player attacker = event.getPlayer();
Arena arena = plugin.getArenaRegistry().getArena(attacker);
if(arena == null) {
return;
}
IUser attackerUser = plugin.getUserManager().getUser(attacker);
if(!Role.isRole(Role.MURDERER, attackerUser, arena)) {
return;
}
ItemStack murdererSword = plugin.getSwordSkinManager().getMurdererSword(attacker);
if(murdererSword == null) {
return;
}
if(VersionUtils.getItemInHand(attacker).getType() != murdererSword.getType()) {
return;
}
if(attackerUser.getCooldown("sword_shoot") > 0) {
return;
}
createFlyingSword(attacker, attackerUser);
int swordFlyCooldown = plugin.getConfig().getInt("Sword.Cooldown.Fly", 5);
if(swordFlyCooldown <= 0) {
return;
}
attackerUser.setCooldown("sword_shoot", swordFlyCooldown);
if(ServerVersion.Version.isCurrentLower(ServerVersion.Version.v1_11)) {
attackerUser.setCooldown("sword_attack", (plugin.getConfig().getInt("Sword.Cooldown.Attack", 1)));
} else {
VersionUtils.setMaterialCooldown(attacker ,plugin.getSwordSkinManager().getMurdererSword(attacker).getType(), 20 * (plugin.getConfig().getInt("Sword.Cooldown.Attack", 1)));
}
plugin.getBukkitHelper().applyActionBarCooldown(attacker, swordFlyCooldown);
}
private void createFlyingSword(Player attacker, IUser attackerUser) {
Location loc = attacker.getLocation();
Vector vec = loc.getDirection();
vec.normalize().multiply(plugin.getConfig().getDouble("Sword.Speed", 0.65));
Location standStart = plugin.getBukkitHelper().rotateAroundAxisY(new Vector(1.0D, 0.0D, 0.0D), loc.getYaw()).toLocation(attacker.getWorld()).add(loc);
standStart.setYaw(loc.getYaw());
ArmorStand stand = (ArmorStand) attacker.getWorld().spawnEntity(standStart, EntityType.ARMOR_STAND);
stand.setVisible(false);
if(ServerVersion.Version.isCurrentHigher(ServerVersion.Version.v1_8_8)) {
stand.setInvulnerable(true);
stand.setSilent(true);
}
VersionUtils.setItemInHand(stand, plugin.getSwordSkinManager().getMurdererSword(attacker));
stand.setRightArmPose(new EulerAngle(Math.toRadians(350.0), Math.toRadians(loc.getPitch() * -1.0), Math.toRadians(90.0)));
VersionUtils.setCollidable(stand, false);
stand.setGravity(false);
stand.setRemoveWhenFarAway(true);
if(ServerVersion.Version.isCurrentEqualOrHigher(ServerVersion.Version.v1_8_8)) {
stand.setMarker(true);
}
Location initialise = plugin.getBukkitHelper().rotateAroundAxisY(new Vector(-0.8D, 1.45D, 0.0D), loc.getYaw()).toLocation(attacker.getWorld()).add(standStart)
.add(plugin.getBukkitHelper().rotateAroundAxisY(plugin.getBukkitHelper().rotateAroundAxisX(new Vector(0.0D, 0.0D, 1.0D), loc.getPitch()), loc.getYaw()));
int maxRange = plugin.getConfig().getInt("Sword.Fly.Range", 20);
double maxHitRange = plugin.getConfig().getDouble("Sword.Fly.Radius", 0.5);
new BukkitRunnable() {
@Override
public void run() {
VersionUtils.teleport(stand, standStart.add(vec));
initialise.add(vec);
initialise.getWorld().getNearbyEntities(initialise, maxHitRange, maxHitRange, maxHitRange)
.forEach(entity -> {
if(entity instanceof Player) {
Player victim = (Player) entity;
Arena arena = plugin.getArenaRegistry().getArena(victim);
if(arena == null) {
return;
}
if(!plugin.getUserManager().getUser(victim).isSpectator() && !victim.equals(attacker)) {
killBySword(arena, attackerUser, victim);
cancel();
stand.remove();
}
}
});
if(loc.distance(initialise) > maxRange || initialise.getBlock().getType().isSolid()) {
cancel();
stand.remove();
}
}
}.runTaskTimer(plugin, 0, 1);
}
private void killBySword(Arena arena, IUser attackerUser, Player victim) {
Arena victimArena = plugin.getArenaRegistry().getArena(victim);
if(arena == null) {
return;
}
IUser user = plugin.getUserManager().getUser(victim);
// check if victim is murderer
if(Role.isRole(Role.MURDERER, user, victimArena)) {
return;
}
XSound.ENTITY_PLAYER_DEATH.play(victim.getLocation(), 50, 1);
victim.damage(100.0);
attackerUser.adjustStatistic("LOCAL_KILLS", 1);
attackerUser.adjustStatistic("KILLS", 1);
arena.adjustContributorValue(Role.DETECTIVE, user, plugin.getRandom().nextInt(2));
ArenaUtils.addScore(attackerUser, ArenaUtils.ScoreAction.KILL_PLAYER, 0);
if(Role.isRole(Role.ANY_DETECTIVE, user, victimArena) && arena.lastAliveDetective()) {
if(Role.isRole(Role.FAKE_DETECTIVE, user, victimArena)) {
arena.setCharacter(Arena.CharacterType.FAKE_DETECTIVE, null);
}
ArenaUtils.dropBowAndAnnounce(arena, victim);
}
}
@EventHandler(priority = EventPriority.HIGH)
// highest priority to fully protect our game
public void onBlockBreak(BlockBreakEvent event) {
Arena arena = plugin.getArenaRegistry().getArena(event.getPlayer());
if(arena == null) {
return;
}
event.setCancelled(true);
if(event.getBlock().getType() != XMaterial.ARMOR_STAND.parseMaterial()) {
return;
}
plugin.getHologramManager().getArmorStands().removeIf(armorStand -> {
boolean isSameType = armorStand.getLocation().getBlock().getType() == event.getBlock().getType();
if(isSameType) {
armorStand.remove();
armorStand.setCustomNameVisible(false);
}
return isSameType;
});
}
@EventHandler(priority = EventPriority.HIGH)
// highest priority to fully protect our game
public void onBuild(BlockPlaceEvent event) {
Arena arena = plugin.getArenaRegistry().getArena(event.getPlayer());
if(arena == null) {
return;
}
event.setCancelled(true);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/CorpseHandler.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers;
import org.bukkit.Bukkit;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.util.EulerAngle;
import org.golde.bukkit.corpsereborn.CorpseAPI.CorpseAPI;
import org.golde.bukkit.corpsereborn.CorpseAPI.events.CorpseClickEvent;
import org.golde.bukkit.corpsereborn.CorpseAPI.events.CorpseSpawnEvent;
import org.golde.bukkit.corpsereborn.nms.Corpses;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.murdermystery.Main;
import plugily.projects.murdermystery.api.events.game.MurderGameCorpseSpawnEvent;
import plugily.projects.murdermystery.arena.Arena;
import plugily.projects.murdermystery.HookManager;
import plugily.projects.murdermystery.arena.corpse.Corpse;
import plugily.projects.murdermystery.arena.corpse.Stand;
import java.util.HashMap;
import java.util.Map;
/**
* @author Plajer
*
* Created at 07.10.2018
*/
public class CorpseHandler implements Listener {
private final Main plugin;
private Corpses.CorpseData lastSpawnedCorpse;
private final Map registeredLastWords = new HashMap<>();
private final ItemStack head = XMaterial.PLAYER_HEAD.parseItem();
public CorpseHandler(Main plugin) {
this.plugin = plugin;
//run bit later than hook manager to ensure it's not null
Bukkit.getScheduler().runTaskLater(plugin, () -> {
if(plugin.getHookManager().isFeatureEnabled(HookManager.HookFeature.CORPSES)) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
}, 20 * 7);
}
public void registerLastWord(String permission, String lastWord) {
registeredLastWords.put(permission, lastWord);
}
@SuppressWarnings("deprecation")
public void spawnCorpse(Player player, Arena arena) {
MurderGameCorpseSpawnEvent murderGameCorpseSpawnEvent = new MurderGameCorpseSpawnEvent(arena, player.getPlayer(), player.getLocation());
Bukkit.getPluginManager().callEvent(murderGameCorpseSpawnEvent);
if(murderGameCorpseSpawnEvent.isCancelled()) {
return;
}
if(!plugin.getHookManager().isFeatureEnabled(HookManager.HookFeature.CORPSES)) {
ArmorStand stand = player.getLocation().getWorld().spawn(player.getLocation().add(0.0D, -1.25D, 0.0D), ArmorStand.class);
SkullMeta meta = (SkullMeta) head.getItemMeta();
meta = VersionUtils.setPlayerHead(player, meta);
head.setItemMeta(meta);
stand.setVisible(false);
if(ServerVersion.Version.isCurrentEqualOrHigher(ServerVersion.Version.v1_16)) {
stand.getEquipment().setHelmet(head);
} else {
stand.setHelmet(head);
}
stand.setGravity(false);
stand.setCustomNameVisible(false);
stand.setHeadPose(new EulerAngle(Math.toRadians(player.getLocation().getX()), Math.toRadians(player.getLocation().getPitch()), Math.toRadians(player.getLocation().getZ())));
plugin.getHologramManager().getArmorStands().add(stand);
ArmorStandHologram hologram = getLastWordsHologram(player);
arena.addHead(new Stand(hologram, stand));
Bukkit.getScheduler().runTaskLater(plugin, () -> {
hologram.delete();
plugin.getHologramManager().getArmorStands().remove(stand);
Bukkit.getScheduler().runTaskLater(plugin, stand::remove, 20 * 20);
}, 15 * 20);
return;
}
ArmorStandHologram hologram = getLastWordsHologram(player);
Corpses.CorpseData corpse = CorpseAPI.spawnCorpse(player, player.getLocation());
lastSpawnedCorpse = corpse;
//spawns 2 corpses - Corpses.CorpseData corpse = lastSpawnedCorpse = CorpseAPI.spawnCorpse(player, player.getLocation());
arena.addCorpse(new Corpse(hologram, corpse));
Bukkit.getScheduler().runTaskLater(plugin, () -> {
hologram.delete();
Bukkit.getScheduler().runTaskLater(plugin, corpse::destroyCorpseFromEveryone, 20 * 20);
}, 15 * 20);
}
private ArmorStandHologram getLastWordsHologram(Player player) {
ArmorStandHologram hologram = new ArmorStandHologram(player.getLocation());
hologram.appendLine(new MessageBuilder(plugin.getLastWordsManager().getHologramTitle()).player(player).build());
hologram.appendLine(plugin.getLastWordsManager().getRandomLastWord(player));
return hologram;
}
@EventHandler
public void onCorpseSpawn(CorpseSpawnEvent e) {
if(lastSpawnedCorpse == null) {
return;
}
if(plugin.getConfigPreferences().getOption("CORPSES_INTEGRATION_OVERWRITE") && !lastSpawnedCorpse.equals(e.getCorpse())) {
e.setCancelled(true);
}
}
@EventHandler
public void onCorpseClick(CorpseClickEvent e) {
if(plugin.getArenaRegistry().isInArena(e.getClicker())) {
e.setCancelled(true);
e.getClicker().closeInventory();
}
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/lastwords/LastWord.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers.lastwords;
/**
* @author 2Wild4You, Tigerpanzer_02
*
* Created at 19.02.2021
*/
public class LastWord {
private final String message;
private final String permission;
public LastWord(String message, String permission) {
this.message = message;
this.permission = permission;
}
public String getMessage() {
return message;
}
public String getPermission() {
return permission;
}
public boolean hasPermission() {
return !permission.isEmpty();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/lastwords/LastWordsManager.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers.lastwords;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.murdermystery.Main;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
/**
* @author 2Wild4You, Tigerpanzer_02
*
* Created at 19.02.2021
*/
public class LastWordsManager {
private final List registeredLastWords = new ArrayList<>();
private String hologramTitle = "";
public LastWordsManager(Main plugin) {
registerLastWords(plugin);
}
public void registerLastWords(Main plugin) {
FileConfiguration config = ConfigUtils.getConfig(plugin, "lastwords");
hologramTitle = config.getString("Last-Words.Hologram.Title", "-");
ConfigurationSection section = config.getConfigurationSection("Last-Words.Hologram.Content");
String path = "Last-Words.Hologram.Content.";
for(String id : section.getKeys(false)) {
addLastWord(new LastWord(new MessageBuilder(config.getString(path + id + ".Message")).build(), config.getString(path + id + ".Permission", "")));
}
}
public List getRegisteredLastWords() {
return registeredLastWords;
}
public String getHologramTitle() {
return hologramTitle;
}
public void addLastWord(LastWord lastWord) {
registeredLastWords.add(lastWord);
}
public String getRandomLastWord(Player player) {
//check perms
List perms = registeredLastWords.stream().filter(lastWord -> player.hasPermission(lastWord.getPermission())).collect(Collectors.toList());
if(!perms.isEmpty()) {
return perms.get(ThreadLocalRandom.current().nextInt(perms.size())).getMessage();
}
//check default
List noPerms = registeredLastWords.stream().filter(lastWord -> !lastWord.hasPermission()).collect(Collectors.toList());
if(!noPerms.isEmpty()) {
return noPerms.get(ThreadLocalRandom.current().nextInt(noPerms.size())).getMessage();
}
//fallback
return registeredLastWords.get(0).getMessage();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/setup/LocationCategory.java
================================================
/*
*
* MurderMystery
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
package plugily.projects.murdermystery.handlers.setup;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginLocationCategory;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginSpecificCategory;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.CountItem;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.LocationItem;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.MultiLocationItem;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.serialization.LocationSerializer;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.inventory.normal.NormalFastInv;
/**
* @author Tigerpanzer_02
*
* Created at 01.07.2022
*/
public class LocationCategory extends PluginLocationCategory {
@Override
public void addItems(NormalFastInv gui) {
super.addItems(gui);
MultiLocationItem starting = new MultiLocationItem(getSetupInventory(), new ItemBuilder(XMaterial.EMERALD_BLOCK.parseMaterial()), "Player Spawn Points", "Location where players will be randomly teleported when the game starts", "playerspawnpoints", 4, inventoryClickEvent -> {
LocationSerializer.saveLoc(getSetupInventory().getPlugin(), getSetupInventory().getConfig(), "arenas", "instances." + getSetupInventory().getArenaKey() + "." + "startlocation", inventoryClickEvent.getWhoClicked().getLocation());
}, (emptyConsumer) -> {
}, true, true, true);
getItemList().add(starting);
gui.setItem((getInventoryLine() * 9) + 2, starting);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/setup/SetupCategoryManager.java
================================================
package plugily.projects.murdermystery.handlers.setup;
import plugily.projects.minigamesbox.classic.handlers.setup.SetupInventory;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginSetupCategoryManager;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.SetupCategory;
/**
* @author Tigerpanzer_02
*
* Created at 01.07.2022
*/
public class SetupCategoryManager extends PluginSetupCategoryManager {
public SetupCategoryManager(SetupInventory setupInventory) {
super(setupInventory);
getCategoryHandler().put(SetupCategory.LOCATIONS, new LocationCategory());
getCategoryHandler().put(SetupCategory.SPECIFIC, new SpecificCategory());
getCategoryHandler().put(SetupCategory.SWITCH, new SwitchCategory());
super.init();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/setup/SpecificCategory.java
================================================
/*
*
* MurderMystery
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
package plugily.projects.murdermystery.handlers.setup;
import org.bukkit.Material;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginSpecificCategory;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.CountItem;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.MaterialLocationItem;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.MaterialMultiLocationItem;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.MultiLocationItem;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.helper.MaterialUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.inventory.normal.NormalFastInv;
import java.util.Collections;
/**
* @author Tigerpanzer_02
*
* Created at 01.07.2022
*/
public class SpecificCategory extends PluginSpecificCategory {
@Override
public void addItems(NormalFastInv gui) {
super.addItems(gui);
CountItem spawnGoldTime = new CountItem(getSetupInventory(), new ItemBuilder(XMaterial.REDSTONE_TORCH.parseMaterial()), "Gold Spawn Time (Seconds)", "How much gold should be spawned? \nThat means 1 gold spawned every ... seconds\nDefault: 5\nEvery 5 seconds it will spawn 1 gold", "spawngoldtime");
gui.setItem((getInventoryLine() * 9) + 1, spawnGoldTime);
getItemList().add(spawnGoldTime);
CountItem playerMurderer = new CountItem(getSetupInventory(), new ItemBuilder(XMaterial.IRON_SWORD.parseMaterial()), "Player Per Murderer", "How many murderer should be ingame? This means \none murderer for that amount of players. Default: \n5 players are 1 murderer, that means if we have \n14 Players it will calculate 2 murderer! \nSet it to 1 if you want only one murderer ", "playerpermurderer");
gui.setItem((getInventoryLine() * 9) + 2, playerMurderer);
getItemList().add(playerMurderer);
CountItem playerDetective = new CountItem(getSetupInventory(), new ItemBuilder(XMaterial.IRON_SWORD.parseMaterial()), "Player Per Murderer", "How many detectives should be ingame? This means \none detective for that amount of players. Default: \n7 players are 1 detective, that means if we have \n18 Players it will calculate 2 detectives! \nSet it to 1 if you want only one detective ", "playerperdetective");
gui.setItem((getInventoryLine() * 9) + 3, playerDetective);
getItemList().add(playerDetective);
MultiLocationItem goldSpawn = new MultiLocationItem(getSetupInventory(), new ItemBuilder(XMaterial.GOLD_INGOT.parseMaterial()), "Gold Spawn", "Add new gold spawn \n on the place you're standing at.", "goldspawnpoints", 4);
gui.setItem((getInventoryLine() * 9) + 4, goldSpawn);
getItemList().add(goldSpawn);
MaterialMultiLocationItem mysteryCauldron = new MaterialMultiLocationItem(getSetupInventory(), new ItemBuilder(XMaterial.CAULDRON.parseMaterial()), "Mystery Cauldron", "Target a cauldron and add it to the game\nit will cost 1 gold per potion!\nConfigure cauldron potions \nin special_blocks.yml file!", "mystery-cauldrons", Collections.singleton(Material.CAULDRON), false, 0);
gui.setItem((getInventoryLine() * 9) + 5, mysteryCauldron);
getItemList().add(mysteryCauldron);
MaterialMultiLocationItem confessional = new MaterialMultiLocationItem(getSetupInventory(), new ItemBuilder(XMaterial.ENCHANTING_TABLE.parseMaterial()), "Confessional", "Target enchanting table and\nadd praise to the developer\nconfessional, gift for\nthe developer costs 1 gold!\nAdd some levers in radius\nof 3 blocks near the enchant table\nto allow users to pray there!\nYou can either get gifts\nor curses from prayer!", "confessionals", Collections.singleton(XMaterial.ENCHANTING_TABLE.parseMaterial()), false, 0);
gui.setItem((getInventoryLine() * 9) + 6, confessional);
getItemList().add(confessional);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/setup/SwitchCategory.java
================================================
package plugily.projects.murdermystery.handlers.setup;
import org.bukkit.plugin.java.JavaPlugin;
import plugily.projects.minigamesbox.classic.PluginMain;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginSwitchCategory;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.BooleanItem;
import plugily.projects.minigamesbox.classic.handlers.setup.items.category.SwitchItem;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.inventory.normal.NormalFastInv;
import plugily.projects.murdermystery.Main;
import java.util.Arrays;
/**
* @author Tigerpanzer_02
*
* Created at 01.07.2022
*/
public class SwitchCategory extends PluginSwitchCategory {
@Override
public void addItems(NormalFastInv gui) {
super.addItems(gui);
BooleanItem goldVisuals = new BooleanItem(getSetupInventory(), new ItemBuilder(XMaterial.REDSTONE.parseMaterial()), "Gold Visuals", "Enables gold visuals to spawn\nsome particle effects above gold locations", "goldvisuals");
gui.setItem((getInventoryLine() * 9) + 1, goldVisuals);
getItemList().add(goldVisuals);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/skins/sword/SwordSkin.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers.skins.sword;
import org.bukkit.inventory.ItemStack;
/**
* @author Tigerpanzer_02
*
* Created at 03.04.2022
*/
public class SwordSkin {
private final ItemStack itemStack;
private final String permission;
public SwordSkin(ItemStack itemStack, String permission) {
this.itemStack = itemStack;
this.permission = permission;
}
public ItemStack getItemStack() {
return itemStack;
}
public String getPermission() {
return permission;
}
public boolean hasPermission() {
return !permission.isEmpty();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/skins/sword/SwordSkinManager.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers.skins.sword;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.murdermystery.Main;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
/**
* @author 2Wild4You, Tigerpanzer_02
*
Created at 19.02.2021
*/
public class SwordSkinManager {
private final List registeredSwordSkins = new ArrayList<>();
private final Map murdererSwords = new HashMap<>();
public SwordSkinManager(Main plugin) {
registerSwordSkins(plugin);
}
public void registerSwordSkins(Main plugin) {
FileConfiguration config = ConfigUtils.getConfig(plugin, "skins");
ConfigurationSection section = config.getConfigurationSection("Skins.Sword");
String path = "Skins.Sword.";
for (String id : section.getKeys(false)) {
addSwordSkin(
new SwordSkin(
XMaterial.matchXMaterial(config.getString(path + id + ".Material", "BEDROCK"))
.orElse(XMaterial.BEDROCK)
.parseItem(),
config.getString(path + id + ".Permission", "")));
}
}
public List getRegisteredSwordSkins() {
return registeredSwordSkins;
}
public void addSwordSkin(SwordSkin lastWord) {
registeredSwordSkins.add(lastWord);
}
public ItemStack getRandomSwordSkin(Player player) {
// check perms
List perms =
registeredSwordSkins.stream()
.filter(swordSkin -> player.hasPermission(swordSkin.getPermission()))
.collect(Collectors.toList());
if (!perms.isEmpty()) {
ItemStack itemStack =
perms.get(ThreadLocalRandom.current().nextInt(perms.size())).getItemStack();
murdererSwords.put(player, itemStack);
return itemStack;
}
// check default
List noPerms =
registeredSwordSkins.stream()
.filter(swordSkin -> !swordSkin.hasPermission())
.collect(Collectors.toList());
if (!noPerms.isEmpty()) {
ItemStack itemStack =
noPerms.get(ThreadLocalRandom.current().nextInt(noPerms.size())).getItemStack();
murdererSwords.put(player, itemStack);
return itemStack;
}
// fallback
ItemStack itemStack = registeredSwordSkins.get(0).getItemStack();
murdererSwords.put(player, itemStack);
return itemStack;
}
public void removeMurdererSword(Player player) {
murdererSwords.remove(player);
}
public ItemStack getMurdererSword(Player player) {
return murdererSwords.get(player);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/trails/BowTrailsHandler.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers.trails;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.scheduler.BukkitRunnable;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.murdermystery.Main;
/**
* @author 2Wild4You, Tigerpanzer_02
*
* Created at 19.02.2021
*/
public class BowTrailsHandler implements Listener {
private final Main plugin;
public BowTrailsHandler(Main plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onArrowShoot(EntityShootBowEvent event) {
if(!(event.getEntity() instanceof Player && event.getProjectile() instanceof Arrow)) {
return;
}
Entity projectile = event.getProjectile();
if(projectile.isDead() || projectile.isOnGround()) {
return;
}
Player player = (Player) event.getEntity();
if(!plugin.getArenaRegistry().isInArena(player) || !plugin.getTrailsManager().gotAnyTrails(player)) {
return;
}
Trail trail = plugin.getTrailsManager().getRandomTrail(player);
plugin.getDebugger().debug("Spawning particle with perm {0} for player {1}", trail.getPermission(), player.getName());
new BukkitRunnable() {
@Override
public void run() {
if(projectile.isDead() || projectile.isOnGround()) {
plugin.getDebugger().debug("Stopped spawning particle with perm {0} for player {1}", trail.getPermission(), player.getName());
cancel();
}
try {
VersionUtils.sendParticles(trail.getName(), player, projectile.getLocation(), 3);
}catch(Exception ignored) {}
}
}.runTaskTimer(plugin, 0, 0);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/trails/Trail.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers.trails;
/**
* @author 2Wild4You, Tigerpanzer_02
*
* Created at 19.02.2021
*/
public class Trail {
private final String name;
private final String permission;
public Trail(String message, String permission) {
this.name = message;
this.permission = permission;
}
public String getName() {
return name;
}
public String getPermission() {
return permission;
}
public boolean hasPermission() {
return !permission.isEmpty();
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/handlers/trails/TrailsManager.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.handlers.trails;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.murdermystery.Main;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
/**
* @author Tigerpanzer_02
*
* Created at 19.02.2021
*/
public class TrailsManager {
private final List registeredTrails = new ArrayList<>();
private final List blacklistedTrails;
public TrailsManager(Main plugin) {
FileConfiguration config = ConfigUtils.getConfig(plugin, "trails");
blacklistedTrails = config.getStringList("Blacklisted-Trails");
registerTrails();
}
public void registerTrails() {
for (String particle : VersionUtils.getParticleValues()) {
if (blacklistedTrails.contains(particle.toLowerCase())) {
continue;
}
addTrail(new Trail(particle, "murdermystery.trails." + particle.toLowerCase()));
}
}
public List getRegisteredTrails() {
return registeredTrails;
}
public void addTrail(Trail lastWord) {
registeredTrails.add(lastWord);
}
public boolean gotAnyTrails(Player player) {
return registeredTrails.stream().anyMatch(trail -> player.hasPermission(trail.getPermission()));
}
public Trail getRandomTrail(Player player) {
// check perms
List perms =
registeredTrails.stream()
.filter(trail -> player.hasPermission(trail.getPermission()))
.collect(Collectors.toList());
if (!perms.isEmpty()) {
return perms.get(perms.size() == 1 ? 0 : ThreadLocalRandom.current().nextInt(perms.size()));
}
// fallback
return registeredTrails.get(0);
}
}
================================================
FILE: src/main/java/plugily/projects/murdermystery/utils/ItemPosition.java
================================================
/*
* MurderMystery - Find the murderer, kill him and survive!
* Copyright (c) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package plugily.projects.murdermystery.utils;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.murdermystery.arena.role.Role;
/**
* @author Plajer
*
* Created at 17.10.2018
*/
public enum ItemPosition {
ARROWS(2, 2), BOW(0, 1), BOW_LOCATOR(4, 4), MURDERER_SWORD(1, 1), INNOCENTS_LOCATOR(4, 4), INFINITE_ARROWS(9, 9), GOLD_INGOTS(8, 8),
POTION(3, 3);
private final int murdererItemPosition;
private final int otherRolesItemPosition;
ItemPosition(int murdererItemPosition, int otherRolesItemPosition) {
this.murdererItemPosition = murdererItemPosition;
this.otherRolesItemPosition = otherRolesItemPosition;
}
/**
* Adds target item to specified hotbar position sorta different for each role.
* Item will be added if there is already set or will be set when no item is set in the position.
*
* @param user player to add item to
* @param itemPosition position of item to set/add
* @param itemStack itemstack to be added at itemPostion or set at itemPosition
*/
public static void addItem(IUser user, ItemPosition itemPosition, ItemStack itemStack) {
int itemPos = Role.isRole(Role.MURDERER, user) ? itemPosition.getMurdererItemPosition()
: itemPosition.getOtherRolesItemPosition();
if(itemPos < 0) {
return;
}
Inventory inv = user.getPlayer().getInventory();
ItemStack item = inv.getItem(itemPos);
if(item != null) {
item.setAmount(item.getAmount() + itemStack.getAmount());
return;
}
inv.setItem(itemPos, itemStack);
}
/**
* Sets target item in specified hotbar position sorta different for each role.
* If item there is already set it will be incremented by itemStack amount if possible.
*
* @param user player to set item to
* @param itemPosition position of item to set
* @param itemStack itemstack to set at itemPosition
*/
public static void setItem(IUser user, ItemPosition itemPosition, ItemStack itemStack) {
if(Role.isRole(Role.MURDERER, user)) {
user.getPlayer().getInventory().setItem(itemPosition.getMurdererItemPosition(), itemStack);
} else {
user.getPlayer().getInventory().setItem(itemPosition.getOtherRolesItemPosition(), itemStack);
}
}
public static void removeItem(IUser user, ItemStack itemStack) {
user.getPlayer().getInventory().removeItem(itemStack);
}
public int getMurdererItemPosition() {
return murdererItemPosition;
}
public int getOtherRolesItemPosition() {
return otherRolesItemPosition;
}
}
================================================
FILE: src/main/resources/arena_selector.yml
================================================
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/arenas.yml
================================================
instances:
default:
lobbylocation: world,364.0,63.0,-72.0,0.0,0.0
startlocation: world,364.0,63.0,-72.0,0.0,0.0
endlocation: world,364.0,63.0,-72.0,0.0,0.0
minimumplayers: 2
maximumplayers: 10
mapname: mapname
world: worldname
signs: [ ]
isdone: false
playerspawnpoints:
- world,364.0,63.0,-72.0,0.0,0.0
goldspawnpoints:
- world,364.0,63.0,-72.0,0.0,0.0
mystery-cauldrons:
- world,364.0,63.0,-72.0,0.0,0.0
playerpermurderer: 5
playerperdetective: 7
goldvisuals: false
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/bungee.yml
================================================
# Configuration for Bungeecord support.
# Remember to enable it in config.yml (Bungee-Mode: true)
# Your bungeecord server name where players will be teleported after game (main lobby with signs etc.)
Hub: lobby
# Should game server be closed after game?
Shutdown-When-Game-Ends: true
# Should the player connect to hub (e.g. Leave-Item)
Connect-To-Hub: true
# Should the End Location be the hub? (Players will be connected to hub at the End)
End-Location-Hub: true
# This is useful for bungee game systems.
# %state% - Game state will be visible at MOTD.
MOTD:
Manager: false
Message: "The actual game state of the minigame is %state%"
Game-States:
Inactive: "&lInactive..."
In-Game: "&lIn-game"
Starting: "&e&lStarting"
Full-Game: "&4&lFULL"
Ending: "&lEnding"
Restarting: "&c&lRestarting"
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/config.yml
================================================
## Thanks for using our plugins! ~Tigerpanzer_02 from Plugily Projects
# murdermystery configuration file
#
# You can edit here the basic things of murdermystery
# Please read everything CAREFULLY!
# You don't want to break anything, do you?
#
# Select locale of MurderMystery, default it's English.
# Available locales:
# default - English language. Uses 'language.yml'.
# See https://github.com/Plugily-Projects/locale_storage/tree/master/plugins/minecraft/murdermystery
# Help us translate the project -> https://translate.plugily.xyz
# Use filename of the language e.g. de_DE.yml -> locale: de_DE
locale: default
# Should we display a boss bar with additional arena information?
Bossbar:
Display: true
# Interval in seconds between messages
Interval: 10
# Should we hook into bungeecord? (If you wanna use arena per server option)
# This option will let you access bungee.yml and its options.
# You STILL need to use external addon for HUB server game signs
# Check here for more info: https://wiki.plugily.xyz/
Bungee-Mode: false
# Enable Inventory Manager for your games? (VERY USEFUL feature for MULTI ARENA)
# This saves inventory of players and restores it after player leaves arena.
# Saved elements: max health, health, food, experience, full inventory, armor contents, fire ticks, active potions
Inventory-Manager: true
Commands:
# Commands which can be used in game, remove all of them to disable (only works if Block.In-Game.Commands = true)
Whitelist:
- me
- help
# Enable and Disable predefined shortened commands or add your own
Shorter:
'1':
Short: "start"
Executes: "murdermysteryadmin forcestart"
Enabled: true
'2':
Short: "leave"
Executes: "murdermystery leave"
Enabled: true
'3':
Short: "stats"
Executes: "murdermystery stats"
Enabled: false
'4':
Short: "top"
Executes: "murdermystery top"
Enabled: true
# Block some functions of your players
Block:
In-Game:
# Should we block every not plugin associated commands in game?
Commands: true
# Should the leave command be blocked inside arena?
Leave: false
# Cancels Item Movement into player crafting, enchantment tables, anvils ...
Item-Move: true
ArmorStand:
# Should we block armor stand destroy with double click?
Destroy: true
# Should we block armor stand interaction?
Interact: true
# Should these only be blocked while ingame and arena state is in_game? (e.g. Lobby and Ending is blocked)
# Setting it to false means on all stages of the game the event will be cancelled.
# Setting it to true means only while IN_GAME the event will be cancelled.
Check: true
# Should all interactions with interactive materials such as doors / buttons / fences / redstone be blocked during ingame
# Full list see https://github.com/CryptoMorin/XSeries/blob/e84000a2bead7367d893cf8661f8d5432116adaa/core/src/main/java/com/cryptomorin/xseries/XTag.java#L2793
Interact: false
# Enable this option when you're using MySQL, otherwise it won't work.
# Be careful when changing this because there is NO migrator between
# flat file and MySQL for player stats.
# If this option is disabled it means all stats will be saved as flat file!
Database: false
# Should we enable in game rewards? See rewards.yml for more...
# You should also check out our script engine tutorial for rewards! https://tutorial.plugily.xyz
Rewards: false
Chat:
# Enable in game (eg. '[KIT][LEVEL] Tigerpanzer_02: hey') special formatting?
# Formatting is configurable in language.yml
# You can use PlaceholderAPI placeholders in chat format!
Format: true
Separate:
# Should we enable a separate arena chat for players inside a arena
# Useful on multi arena servers that don't want the same chat for all players on the server
Arena: true
# Should spectators only write with other spectators
Spectators: true
# Should we fire some cool fireworks at locations of every player at special events such as the game end?
Firework: true
# Should blocks behind game signs change their color based on game state?
# They will change color to:
# - white (waiting for players) stained glass
# - yellow (starting) stained glass
# - orange (in game) stained glass
# - gray (ending) stained glass
# - black (restarting) stained glass
# or define your own at signs.yml!
Sign-Block-States: true
# Should holiday events for the plugin be enabled?
# Eg. 4 days before and 4 days after Halloween special effects
# for death, spooky! There are more holiday events! Check wiki!
# Wiki: -
Holidays: true
# Should the plugin enable special powerups which can be found in powerups.yml
Powerups: false
# Should we create leaderboards out of the stats?
Leaderboard: true
Parties:
# Should we try to hook into your current party plugin? (Supports well know party plugins, see wiki!)
# It will group up all players with the party leader. The party leader can join with the whole party!
External: true
# Should we enable our own party system that can be only used for this plugin?
# Check the wiki for commands
Own: false
Damage:
# Should players get fall damage?
Fall: false
# Should players get drowning damage?
Drowning: false
# Should players get fire damage?
Fire: false
# Should players lose food ingame & get damage?
Hunger: false
Option:
Player:
# Disable player drops ingame?
Drop: true
Cycle:
# Should we make permanent clear weather on all worlds where our arenas are?
Weather: false
# Should the time on the world your arenas are modified to stay at the same time?
Daylight:
Enable: false
Time: 10000
# How many seconds game should take to start.
Time-Manager:
Waiting: 20
Starting: 60
Shorten-Waiting-Full: 15
Shorten-Waiting-Force: 5
In-Game: 270
Ending: 10
Restarting: 5
# Allow spectators on arena instances
Spectators: true
Update-Notifier:
# Should we check for updates on plugin start/after admin join?
# You REALLY should have this true!
Enabled: true
# Should we inform you when beta version is out?
# BETA IS NOT ALWAYS AS STABLE AS NORMAL RELEASE!
Notify-Beta-Versions: true
Corpses:
# Should we override corpses spawn from CorpsesReborn plugin?
# When player will die outside game corpse won't be spawned!
# Disable this if you don't want this!
# WARNING: If disabled, two corpses will be spawned when player in-game dies
Integration-Overwrite: true
Gold:
#Should we change spawner mode to spawn on all spawners instant of random one
Spawner-Mode: false
#Should we disable the gold spawn limit (It does not spawn more gold than spawner locations)
Limiter: false
#Should we spawn more than 1 gold at a spawner at the same time
Multiple: false
Amount:
#How much gold should a player need to get a bow
Bow: 10
#How much arrows should the player get? (Cause: Bow because enough gold collected)
Arrows: 3
#How much arrows should a player with bow gets when he pick up a gold ingot?
Pick-Up: 1
Bow:
#Should Detectives be killed if they kill a innocent?
Kill-Detective: true
Amount:
Arrows:
#How much arrows should the detective gets on game start or when a player get a bow?
Detective: 10
#How much arrows should the fake detective get? (Cause: Player pick up bow after detective died)
Fake: 3
#How much arrows should the player get when the prayer gives a bow to him?
Prayer: 2
#How much arrows should the player get after x picked up gold
Gold: 3
#How long should be the bow shoot cooldown in seconds?
Cooldown: 5
Hide:
# Should we disable death messages, so the player dies without other recognizes it
# It will not broadcast the death message to all ;)
Death: false
# Should players' name tags in game be hidden?
Nametags: true
Murderer:
# Should the murderer get speed effect?
# Enter a multiplier (min 2, max 10, 1 is normal speed)
Speed: 3
# Should the Murderer get a locator with Innocent location information
# gets the locator if arena time lower 30 and only one innocent left
Locator: true
Sword:
# How many blocks per tick sword thrown by murderer should fly
# Please avoid high values as it might look like the sword is
# blinking each tick
Speed: 0.65
Fly:
# How many blocks should the sword fly
Range: 20
# In what radius should we hit the players
Radius: 0.5
Cooldown:
#How long should be the sword attack after throw cooldown in seconds?
#Its normal lower than Murderer-Sword-Fly-Cooldown!
Attack: 1
#How long should be the sword fly cooldown in seconds?
Fly: 5
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 2
Core-Version: 6
================================================
FILE: src/main/resources/internal/data.yml
================================================
###############################[IMPORTANT]###############################
#
# Leave this file as it is! It is kinda an internal file!
#
### !!!Do not change anything here!!!
#
### THIS FILE AUTOMATICALLY REGENERATES ON SERVER RESTART
#
###############################[IMPORTANT]###############################
Plugin:
Name:
Short: mm
Long: murdermystery
Id:
Spigot: 66614
BStats: 3038
Compatibility:
Spigot:
- "1.8"
- "1.9"
- "1.10"
- "1.11"
- "1.12"
- "1.13"
- "1.14"
- "1.15"
- "1.16"
- "1.17"
- "1.18"
================================================
FILE: src/main/resources/internal/leaderboards_data.yml
================================================
holograms: {}
================================================
FILE: src/main/resources/language.yml
================================================
# You can translate MurderMystery messages here.
# Color codes (&) supported.
#
# Use \n to make new line
# Some messages like item
# descriptions don't support new lines
# they are wrapped every 40 characters automatically
#
# Some messages support their own placeholders
# like %player%, %kit% etc.
#
# Color scheme
#
Color:
Placeholder:
Value: "&4"
Number: "&4"
Player: "&b"
Other: "&4"
Chat:
Issue: "&c"
Messages: "&7"
Special-Char:
Contains: "[,],(,),{,},■,/,|,▸"
Before: "&8"
#
# Command messages
#
Commands:
Did-You-Mean: "%plugin_prefix% Did you mean /%value%?"
Command-Executed: "%plugin_prefix% Command successfully executed!"
Teleported-To-Lobby: "%plugin_prefix% Teleported to lobby!"
Removed-Game-Instance: "%color_chat_issue%%plugin_prefix% Successfully removed game instance!"
No-Arena-Like-That: "%color_chat_issue%%plugin_prefix% No arena with that ID!"
Look-At-Sign: "%color_chat_issue%%plugin_prefix% You have to look at a sign to perform this command!"
Type-Arena-Name: "%color_chat_issue%%plugin_prefix% Please type arena ID!"
Hold-Any-Item: "%color_chat_issue%%plugin_prefix% You must hold any item!"
No-Free-Arenas: "%color_chat_issue%%plugin_prefix% There are no free arenas!"
Only-By-Player: "%color_chat_issue%%plugin_prefix% You can execute this command only as player!"
Not-Playing: "%color_chat_issue%%plugin_prefix% You must play to execute this command!"
No-Permission: "%color_chat_issue%%plugin_prefix% You don't have permission to use this command!"
Player-Not-Found: "%color_chat_issue%%plugin_prefix% Target player %player% doesn't exist!"
Invalid-Location-Teleport: "%color_chat_issue%%plugin_prefix% Location to teleport is invalid!"
Wrong-Usage: "%color_chat_issue%%plugin_prefix% Wrong usage. Do %value%"
Admin:
Adjust-Statistic: "%plugin_prefix% Statistic %value% of %player% is now %number%!"
Reload-Success: "%plugin_prefix% Arenas reloaded!"
List:
Header: "%plugin_name% arenas: Name State Players"
Format: "%arena_name% %arena_state_placeholder% %arena_players_size%/%arena_max_players%"
No-Arenas: "%color_chat_issue%%plugin_prefix% There are no game instances!"
Spychat:
Toggled: "%plugin_prefix% Game spy chat toggled to %value%"
Main:
Header: "&6----------------{%plugin_name% commands}----------"
Description:
- "&aGame commands:"
- "&b/%plugin_short_command% stats: Shows your stats!"
- "&b/%plugin_short_command% leave: Quits current arena!"
- "&b/%plugin_short_command% join : Joins specified arena!"
- "&b/%plugin_short_command% top : Shows top 10 players!"
- "&b/%plugin_short_command% randomjoin: Join random arena!"
Admin-Bonus-Description: "&b/%plugin_short_command%: Shows all the admin commands"
Footer: "&6-------------------------------------------------"
#
# In-Game scoreboard messages
#
# Please do not use more chars than the scoreboard can handle!
# Scoreboard supports up to 122 chars for 1.14+ and 48 chars for 1.13- (COLOR CODES INCLUDED.)
# Placeholders:
# https://wiki.plugily.xyz/REPLACEWITHPROJECTNAME/placeholders/language
Scoreboard:
Title: "&a&l%plugin_name%"
Roles:
Detective: "&bDetective"
Murderer: "&cMurderer"
Innocent: "&eInnocent"
Dead: "Dead"
Detective:
Alive: "Detective &aAlive"
Bow:
Dropped: "%color_chat_issue%Bow Dropped"
Picked: "Bow Not Dropped"
Content:
Waiting:
- ""
- "■ Players | %arena_players_size%"
- ""
- "■ Minimum Players | %arena_min_players%"
- ""
- " www.plugily.xyz"
Starting:
- ""
- "■ Starting In | %arena_time%"
- ""
- "■ Players | %arena_players_size%"
- ""
- "■ Minimum Players | %arena_min_players%"
- ""
- " www.plugily.xyz"
# Contents of scoreboard while ingame
In-Game:
- ""
- "■ Role | %arena_player_role%"
- "&f"
- "■ Innocents | %arena_innocent_size%"
- "&f"
- "■ Time | %arena_time%"
- ""
- "■ %arena_detective_status%"
- ""
- "■ Score | %user_statistic_local_score%"
- ""
- " www.plugily.xyz"
In-Game-Murderer:
- ""
- "■ Role | %arena_player_role%"
- "&f"
- "■ Innocents | %arena_innocent_size%"
- "&f"
- "■ Time | %arena_time%"
- ""
- "■ %arena_detective_status%"
- ""
- "■ Kills | %user_statistic_local_kills%"
- ""
- "■ Score | %user_statistic_local_score%"
- ""
- " www.plugily.xyz"
# Contents of scoreboard while state is ending
Ending:
- "&f"
- "&f"
- "&cGAME ENDED"
- ""
- "&f"
- "&f"
- ""
- " www.plugily.xyz"
# Contents of scoreboard while state is restarting
Restarting:
- "&f"
- "&f"
- "&cRESTARTING GAME"
- ""
- "&f"
- "&f"
- ""
- " www.plugily.xyz"
#
# Bossbar messages
#
# Bossbar needs to be enabled on config.yml
Bossbar:
Title: "%plugin_name% - www.plugily.xyz"
Content:
Waiting:
- "Waiting for more players..."
Starting:
- "Starting in: %arena_time%"
In-Game:
- "Playing %plugin_name_uppercase% on PLUGILY.XYZ"
- "Check the plugin creator out on PLUGILY.XYZ"
- "Your role %arena_player_role%"
Ending:
- "Game has ended! You were playing on PLUGILY.XYZ"
Restarting:
- "Restarting the arena. You will be moved soon!"
#
# In-Game Messages
#
In-Game:
#Used in most game messages.
Plugin-Prefix: "(%plugin_name%)"
Game-Chat-Format: "[%user_statistic_level%] %player% | %message%"
You-Leveled-Up: "%plugin_prefix% You leveled up! You're now level %number%!"
Commands-Blocked: "%color_chat_issue%%plugin_prefix% You have to leave the game first to perform commands. The only command that works is /%plugin_short_command% leave!"
Join:
Already-Playing: "%color_chat_issue%%plugin_prefix% You are already queued for a game! You can leave a game with /%plugin_short_command% leave."
No-Permission: "%color_chat_issue%%plugin_prefix% You don't have %value% permission to join this arena!"
Full-Game: "%color_chat_issue%%plugin_prefix% You don't have the permission to join full games!"
No-Slots-For-Premium: "%color_chat_issue%%plugin_prefix% This game is already full of premium players! Sorry"
# Join cancelled via external plugin that uses the API of our plugin.
Cancelled-Via-API: "%color_chat_issue%%plugin_prefix% You can't join this game!"
As-Party-Member: "%color_chat_issue%%plugin_prefix% You joined %arena_name% because the party leader joined it!"
Arena-Not-Configured: "%color_chat_issue%%plugin_prefix% Arena is not configured yet! Contact your server's staff!"
Title: "20,30,20;%arena_name%;%arena_players_size%/%arena_max_players%"
Death:
Tag: "&8Dead"
Screen: "%color_chat_issue%You died!"
Spectator:
Blocked: "%color_chat_issue%%plugin_prefix% Spectators are disabled for this arena"
You-Are-Spectator: "%plugin_prefix% You're now a spectator! You can fly now!"
Spectator-Menu-Name: "%color_chat_issue%Alive players list"
Target-Player-Health: "%color_chat_issue%Health: %number% | Role: %arena_player_role%"
Spectator-Warning: "%plugin_prefix% You are a spectator!"
Teleport: "%plugin_prefix% Teleported to %player%"
Menu:
Settings:
Status:
Enabled: "Enabled"
Disabled: "Disabled"
Changed-Speed: "Changed Speed to %number%"
Auto-Teleport: "%value% auto teleport"
Target-Player:
Action-Bar: "%number% blocks away | Target %player%"
Night-Vision: "%value% night vision"
First-Person-Mode:
Action-Bar: "&eSNEAK &cto leave! | Target %player%"
Title: "&eSNEAK &cto leave!"
Visibility: "%value% other spectator players"
Messages:
Join: "%plugin_prefix% %player% joined the game (%arena_players_size%/%arena_max_players%)!"
Leave: "%plugin_prefix% %player% left the game (%arena_players_size%/%arena_max_players%)!"
Death: "%plugin_prefix% %player% died!"
Lobby:
Start-In: "%plugin_prefix% The game starts in %arena_time% seconds!"
Waiting-For-Players: "%plugin_prefix% Waiting for players... We need at least %arena_min_players% players to start."
Enough-Players-To-Start: "%plugin_prefix% We now have enough players. The game is starting soon!"
Reduced-Time: "%plugin_prefix% The time got reduced to %number% seconds"
Max-Players: "%plugin_prefix% We reached max players for this round. Let's shorten the time!"
Game-Started: "%plugin_prefix% The game has started!"
Kicked-For-Premium-Slot: "%color_chat_issue%%plugin_prefix% %player% got removed from the game to make a place for premium players!"
You-Were-Kicked-For-Premium-Slot: "%color_chat_issue%%plugin_prefix% You got kicked out of the game to make a place for a premium player!"
Not-Enough-Space-For-Party: "%color_chat_issue%%plugin_prefix% Your party is bigger than free places on the arena %arena_name%"
Game-End:
Summary:
- "&a&m--------------------------------------------------"
- "%plugin_name%"
- ""
- "%arena_summary%"
- "%arena_summary_player%"
- ""
- "&7Detective: %arena_detective_list%"
- "&7Murderer: %arena_murderer_list% (%arena_murderer_kills%)"
- "&7Hero: %arena_hero%"
- ""
- "&a&m--------------------------------------------------"
Placeholders:
Win: "&aYou won the game"
Lose: "%color_chat_issue%You lost the game"
Players: "&cThere are not enough players anymore. Arena got force stopped!"
Murderer:
Stopped: "The Murderer has been stopped!"
Killed:
You: "The murderer killed you!"
All: "The Murderer has killed everyone."
Innocent:
Killed:
You: "A player killed you with a Bow!"
Wrongly: "You killed an innocent player!"
Nobody: "Nobody"
Admin:
Set-Starting-In-To-0: "%plugin_prefix% An admin set waiting time to 0. The game starts now!"
Arena:
Chances:
Action-Bar: "&cMurderer Chance: %arena_murderer_chance% &a- &bDetective Chance: %arena_detective_chance%"
Cooldown: "&8&l[%value%&8&l] &6%number% seconds"
Locator:
Bow: "Bow locator"
Innocent: "Innocent locator"
Watch-Out: "5,20,5;Watch out!;The Murderer can now find survivors easily"
Pass:
Name: "Role pass menu"
Role:
Murderer:
Name: "&cBe murderer"
Lore:
- "Cost 1 murderer pass"
- "You got %number%"
Detective:
Name: "&bBe detective"
Lore:
- "Cost 1 detective pass"
- "You got %number%"
Fail: "%plugin_prefix% You do not got enough passes for %value% role"
Success: "%plugin_prefix% You will be %value% next round!"
Change: "%plugin_prefix% You now got %number% %value% passes!"
Playing:
Time-Left: "5,20,5;%arena_time% seconds left!;After %arena_time%s the Murderer will lose"
Role:
Change: "5,20,5;Previous %arena_player_role% has left!"
Murderer: "5,20,5;ROLE | MURDERER; Kill all players!"
Detective: "5,20,5;ROLE | DETECTIVE;Find and kill the murderer!"
Innocent: "5,20,5;ROLE | INNOCENT;Stay alive as long as possible!"
Score:
Bonus: "+%number% score (%value%)"
Gold: "Picked up gold!"
Action:
Kill:
Player: "for killing players"
Murderer: "for killing murderer"
Innocent: "for killing innocent"
Pickup:
Gold: "for gold pickup"
Surviving:
Time: "for surviving 30 seconds"
End: "for surviving till end"
Win: "for winning the game"
Detective: "for %number% innocents survived"
Sword:
Soon: "The Murderer gets their sword in %number% seconds!"
Special-Blocks:
Cauldron:
Potion: "Please drink your current potion!"
Hologram: "Mystery Potion - &e1 Gold"
Not-Enough-Gold: "You need %number% gold for this!"
Pray:
Hologram: "Click to give gift;Pull lever to pray"
Chat: "You prayed to the developer! Hope he will hear that!"
Pay: "%color_chat_issue%Pay to pray!"
Praise:
Heard:
- ""
- "&7Developer hears your prayer."
- "%feeling%"
- "%praise%"
Feeling:
Blessed: "&aYou feel blessed."
Cursed: "&cYou feel cursed."
Gifts:
Detective-Revelation: "&aYou know that &bCurrent detective &ais %detective%"
Gold-Rush: "&aYou received power of ancients. For each gold you collect, you will receive 3 gold now."
Single-Compensation: "&aDeveloper is proud of you! He rewarded you with 5 gold ingots!"
Bow: "&aYou received bow from pleased developer!"
Curses:
Slowness: "%color_chat_issue%Your legs are much heavier than before."
Blindness: "%color_chat_issue%Your eyes can't see that well anymore."
Gold: "%color_chat_issue%Developer cursed you with gold ban! You cannot longer pickup any gold!"
Death: "%color_chat_issue%You feel overpowering force of death. You know that you'll be dead in a minute!"
Bow:
Dropped: "5,20,5;The Bow has been dropped!;Find the Bow for a chance to kill the Murderer."
Pickup: "A player has picked up the Bow!"
Shot:
Gold: "&a+1 Bow Shot!"
Title: "5,20,5;;You collected 10 gold and got an arrow!"
#
# Sign messages
#
Signs:
Please-Type-Arena-Name: "%color_chat_issue%%plugin_prefix% Please type arena name in second line!"
Arena-Doesnt-Exists: "%color_chat_issue%%plugin_prefix% Arena with that name doesn't exists!"
Created: "%plugin_prefix% Sign created successfully!"
Removed: "%plugin_prefix% Sign successfully removed!"
Lines:
- "%plugin_prefix%"
- "%arena_state_placeholder%"
- "%arena_name%"
- "[%arena_players_size%/%arena_max_players%]"
#
# Arena Selector messages
#
Arena-Selector:
Inventory-Title: "%plugin_short_command% ▸ Arena selector"
Item:
Name: "%arena_name%"
Lore:
- "%plugin_name% - %arena_name%"
- " "
- " "
- " Online: %arena_players_size%/%arena_max_players%"
- " State: %arena_state_placeholder%"
- " "
- " "
- "&aClick to join this arena"
#
# Validator messages
#
Validator:
Invalid-Arena-Configuration: "Arena %arena_name% has invalid configuration! Missing node: %value%"
Instance-Started: "Arena %arena_name% instance successfully started!"
No-Instances-Created: "There are no arena instances created in configuration!"
#
# Placeholder messages inside plugin
#
Placeholders:
Game-States:
Waiting: "&lWaiting for players..."
Starting: "&e&lStarting"
Full-Game: "&4&lFULL"
In-Game: "&lIn-game"
Ending: "&lEnding"
Restarting: "&c&lRestarting"
Motd:
Waiting: "&lYou can join this game..."
Starting: "&e&lStarting"
Full-Game: "&4&lFULL | Use another Server"
In-Game: "&lIn-game | Click to spectate"
Ending: "&lEnding | Server is closing"
Restarting: "&c&lRestarting"
#
# Leaderboard messages
#
# Hologram function need to be enabled on config.yml
Leaderboard:
Type:
Hologram:
Header: "&6&lTop %number% in %value%"
Format: "&e%number%. %player% (%value%)"
Empty-Format: "&e%number%. Empty (0)"
Chat:
Header: "&8+-------+ &a&lYOUR STATS &8+-------+"
Header-Other: "&8+---------+ &aSTATS FOR &b%player% &8+---------+"
Footer: "&8+-----------------------------+"
Format: "%value% ▸ &a%number%"
Top:
Type-Name: "%color_chat_issue%Please type statistic name to view!"
Header: "&8&m+----------------+ [&6 Top 10 &8&m] +----------------+"
Format: "&e#%number% %player% - %value% %user_statistic%"
Statistics:
Wins: "Wins ▸ %number%"
Loses: "Loses ▸ %number%"
Games-Played: "Games Played ▸ %number%"
Level: "Level ▸ %number%"
Exp: "Experience ▸ %number%"
Next-Level-Exp: "Exp to Level Up ▸ %number%"
Kills: "Kills ▸ %number%"
Deaths: "Deaths ▸ %number%"
Highest-Score: "Highest score ▸ %number%"
Murderer-Pass: "Murderer passes ▸ %number%"
Detective-Pass: "Detective passes ▸ %number%"
Murderer-Contribution: "Murderer contribution ▸ %number%"
Detective-Contribution: "Detective contribution ▸ %number%"
Invalid-Name: "%color_chat_issue%Name of statistic is invalid! Type: %value%"
Unknown-Player: "%color_chat_issue%Unknown Player"
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 2
================================================
FILE: src/main/resources/lastwords.yml
================================================
Last-Words:
Hologram:
Title: "%player%'s last words:"
Content:
'default':
Message: "&fPlease respawn :("
'meme':
Message: "&fDespacito 2 is confirmed by God"
Permission: "murdermystery.lastwords.meme"
'rage':
Message: "&fWHY YOU KILLED ME?!!?"
Permission: "murdermystery.lastwords.rage"
'pro':
Message: "&fIt was lagging..."
Permission: "murdermystery.lastwords.pro"
'hacker':
Message: "Turn off your hacks..."
Permission: "murdermystery.lastwords.hacker"
================================================
FILE: src/main/resources/leaderboards.yml
================================================
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/locales/language_default.yml
================================================
###############################[IMPORTANT]###############################
#
# Leave this file as it is! It is kinda an internal backup file!
#
### !!!Do not change anything here!!!
#
### THIS FILE AUTOMATICALLY REGENERATES ON SERVER RESTART
#
# Needed when the external api isn't working
#
###############################[IMPORTANT]###############################
# You can translate MurderMystery messages here.
# Color codes (&) supported.
#
# Use \n to make new line
# Some messages like item
# descriptions don't support new lines
# they are wrapped every 40 characters automatically
#
# Some messages support their own placeholders
# like %player%, %kit% etc.
#
# Color scheme
#
Color:
Placeholder:
Value: "&4"
Number: "&4"
Player: "&b"
Other: "&4"
Chat:
Issue: "&c"
Messages: "&7"
Special-Char:
Contains: "[,],(,),{,},■,/,|,▸"
Before: "&8"
#
# Command messages
#
Commands:
Did-You-Mean: "%plugin_prefix% Did you mean /%value%?"
Command-Executed: "%plugin_prefix% Command successfully executed!"
Teleported-To-Lobby: "%plugin_prefix% Teleported to lobby!"
Removed-Game-Instance: "%color_chat_issue%%plugin_prefix% Successfully removed game instance!"
No-Arena-Like-That: "%color_chat_issue%%plugin_prefix% No arena with that ID!"
Look-At-Sign: "%color_chat_issue%%plugin_prefix% You have to look at a sign to perform this command!"
Type-Arena-Name: "%color_chat_issue%%plugin_prefix% Please type arena ID!"
Hold-Any-Item: "%color_chat_issue%%plugin_prefix% You must hold any item!"
No-Free-Arenas: "%color_chat_issue%%plugin_prefix% There are no free arenas!"
Only-By-Player: "%color_chat_issue%%plugin_prefix% You can execute this command only as player!"
Not-Playing: "%color_chat_issue%%plugin_prefix% You must play to execute this command!"
No-Permission: "%color_chat_issue%%plugin_prefix% You don't have permission to use this command!"
Player-Not-Found: "%color_chat_issue%%plugin_prefix% Target player %player% doesn't exist!"
Invalid-Location-Teleport: "%color_chat_issue%%plugin_prefix% Location to teleport is invalid!"
Wrong-Usage: "%color_chat_issue%%plugin_prefix% Wrong usage. Do %value%"
Admin:
Adjust-Statistic: "%plugin_prefix% Statistic %value% of %player% is now %number%!"
Reload-Success: "%plugin_prefix% Arenas reloaded!"
List:
Header: "%plugin_name% arenas: Name State Players"
Format: "%arena_name% %arena_state_placeholder% %arena_players_size%/%arena_max_players%"
No-Arenas: "%color_chat_issue%%plugin_prefix% There are no game instances!"
Spychat:
Toggled: "%plugin_prefix% Game spy chat toggled to %value%"
Main:
Header: "&6----------------{%plugin_name% commands}----------"
Description:
- "&aGame commands:"
- "&b/%plugin_short_command% stats: Shows your stats!"
- "&b/%plugin_short_command% leave: Quits current arena!"
- "&b/%plugin_short_command% join : Joins specified arena!"
- "&b/%plugin_short_command% top : Shows top 10 players!"
- "&b/%plugin_short_command% randomjoin: Join random arena!"
Admin-Bonus-Description: "&b/%plugin_short_command%: Shows all the admin commands"
Footer: "&6-------------------------------------------------"
#
# In-Game scoreboard messages
#
# Please do not use more chars than the scoreboard can handle!
# Scoreboard supports up to 122 chars for 1.14+ and 48 chars for 1.13- (COLOR CODES INCLUDED.)
# Placeholders:
# https://wiki.plugily.xyz/REPLACEWITHPROJECTNAME/placeholders/language
Scoreboard:
Title: "&a&l%plugin_name%"
Roles:
Detective: "&bDetective"
Murderer: "&cMurderer"
Innocent: "&eInnocent"
Dead: "Dead"
Detective:
Alive: "Detective &aAlive"
Bow:
Dropped: "%color_chat_issue%Bow Dropped"
Picked: "Bow Not Dropped"
Content:
Waiting:
- ""
- "■ Players | %arena_players_size%"
- ""
- "■ Minimum Players | %arena_min_players%"
- ""
- " www.plugily.xyz"
Starting:
- ""
- "■ Starting In | %arena_time%"
- ""
- "■ Players | %arena_players_size%"
- ""
- "■ Minimum Players | %arena_min_players%"
- ""
- " www.plugily.xyz"
# Contents of scoreboard while ingame
In-Game:
- ""
- "■ Role | %arena_player_role%"
- "&f"
- "■ Innocents | %arena_innocent_size%"
- "&f"
- "■ Time | %arena_time%"
- ""
- "■ %arena_detective_status%"
- ""
- "■ Score | %user_statistic_local_score%"
- ""
- " www.plugily.xyz"
In-Game-Murderer:
- ""
- "■ Role | %arena_player_role%"
- "&f"
- "■ Innocents | %arena_innocent_size%"
- "&f"
- "■ Time | %arena_time%"
- ""
- "■ %arena_detective_status%"
- ""
- "■ Kills | %user_statistic_local_kills%"
- ""
- "■ Score | %user_statistic_local_score%"
- ""
- " www.plugily.xyz"
# Contents of scoreboard while state is ending
Ending:
- "&f"
- "&f"
- "&cGAME ENDED"
- ""
- "&f"
- "&f"
- ""
- " www.plugily.xyz"
# Contents of scoreboard while state is restarting
Restarting:
- "&f"
- "&f"
- "&cRESTARTING GAME"
- ""
- "&f"
- "&f"
- ""
- " www.plugily.xyz"
#
# Bossbar messages
#
# Bossbar needs to be enabled on config.yml
Bossbar:
Title: "%plugin_name% - www.plugily.xyz"
Content:
Waiting:
- "Waiting for more players..."
Starting:
- "Starting in: %arena_time%"
In-Game:
- "Playing %plugin_name_uppercase% on PLUGILY.XYZ"
- "Check the plugin creator out on PLUGILY.XYZ"
- "Your role %arena_player_role%"
Ending:
- "Game has ended! You were playing on PLUGILY.XYZ"
Restarting:
- "Restarting the arena. You will be moved soon!"
#
# In-Game Messages
#
In-Game:
#Used in most game messages.
Plugin-Prefix: "(%plugin_name%)"
Game-Chat-Format: "[%user_statistic_level%] %player% | %message%"
You-Leveled-Up: "%plugin_prefix% You leveled up! You're now level %number%!"
Commands-Blocked: "%color_chat_issue%%plugin_prefix% You have to leave the game first to perform commands. The only command that works is /%plugin_short_command% leave!"
Join:
Already-Playing: "%color_chat_issue%%plugin_prefix% You are already queued for a game! You can leave a game with /%plugin_short_command% leave."
No-Permission: "%color_chat_issue%%plugin_prefix% You don't have %value% permission to join this arena!"
Full-Game: "%color_chat_issue%%plugin_prefix% You don't have the permission to join full games!"
No-Slots-For-Premium: "%color_chat_issue%%plugin_prefix% This game is already full of premium players! Sorry"
# Join cancelled via external plugin that uses the API of our plugin.
Cancelled-Via-API: "%color_chat_issue%%plugin_prefix% You can't join this game!"
As-Party-Member: "%color_chat_issue%%plugin_prefix% You joined %arena_name% because the party leader joined it!"
Arena-Not-Configured: "%color_chat_issue%%plugin_prefix% Arena is not configured yet! Contact your server's staff!"
Title: "20,30,20;%arena_name%;%arena_players_size%/%arena_max_players%"
Death:
Tag: "&8Dead"
Screen: "%color_chat_issue%You died!"
Spectator:
Blocked: "%color_chat_issue%%plugin_prefix% Spectators are disabled for this arena"
You-Are-Spectator: "%plugin_prefix% You're now a spectator! You can fly now!"
Spectator-Menu-Name: "%color_chat_issue%Alive players list"
Target-Player-Health: "%color_chat_issue%Health: %number% | Role: %arena_player_role%"
Spectator-Warning: "%plugin_prefix% You are a spectator!"
Teleport: "%plugin_prefix% Teleported to %player%"
Menu:
Settings:
Status:
Enabled: "Enabled"
Disabled: "Disabled"
Changed-Speed: "Changed Speed to %number%"
Auto-Teleport: "%value% auto teleport"
Target-Player:
Action-Bar: "%number% blocks away | Target %player%"
Night-Vision: "%value% night vision"
First-Person-Mode:
Action-Bar: "&eSNEAK &cto leave! | Target %player%"
Title: "&eSNEAK &cto leave!"
Visibility: "%value% other spectator players"
Messages:
Join: "%plugin_prefix% %player% joined the game (%arena_players_size%/%arena_max_players%)!"
Leave: "%plugin_prefix% %player% left the game (%arena_players_size%/%arena_max_players%)!"
Death: "%plugin_prefix% %player% died!"
Lobby:
Start-In: "%plugin_prefix% The game starts in %arena_time% seconds!"
Waiting-For-Players: "%plugin_prefix% Waiting for players... We need at least %arena_min_players% players to start."
Enough-Players-To-Start: "%plugin_prefix% We now have enough players. The game is starting soon!"
Reduced-Time: "%plugin_prefix% The time got reduced to %number% seconds"
Max-Players: "%plugin_prefix% We reached max players for this round. Let's shorten the time!"
Game-Started: "%plugin_prefix% The game has started!"
Kicked-For-Premium-Slot: "%color_chat_issue%%plugin_prefix% %player% got removed from the game to make a place for premium players!"
You-Were-Kicked-For-Premium-Slot: "%color_chat_issue%%plugin_prefix% You got kicked out of the game to make a place for a premium player!"
Not-Enough-Space-For-Party: "%color_chat_issue%%plugin_prefix% Your party is bigger than free places on the arena %arena_name%"
Game-End:
Summary:
- "&a&m--------------------------------------------------"
- "%plugin_name%"
- ""
- "%arena_summary%"
- "%arena_summary_player%"
- ""
- "&7Detective: %arena_detective_list%"
- "&7Murderer: %arena_murderer_list% (%arena_murderer_kills%)"
- "&7Hero: %arena_hero%"
- ""
- "&a&m--------------------------------------------------"
Placeholders:
Win: "&aYou won the game"
Lose: "%color_chat_issue%You lost the game"
Players: "&cThere are not enough players anymore. Arena got force stopped!"
Murderer:
Stopped: "The Murderer has been stopped!"
Killed:
You: "The murderer killed you!"
All: "The Murderer has killed everyone."
Innocent:
Killed:
You: "A player killed you with a Bow!"
Wrongly: "You killed an innocent player!"
Nobody: "Nobody"
Admin:
Set-Starting-In-To-0: "%plugin_prefix% An admin set waiting time to 0. The game starts now!"
Arena:
Chances:
Action-Bar: "&cMurderer Chance: %arena_murderer_chance% &a- &bDetective Chance: %arena_detective_chance%"
Cooldown: "&8&l[%value%&8&l] &6%number% seconds"
Locator:
Bow: "Bow locator"
Innocent: "Innocent locator"
Watch-Out: "5,20,5;Watch out!;The Murderer can now find survivors easily"
Pass:
Name: "Role pass menu"
Role:
Murderer:
Name: "&cBe murderer"
Lore:
- "Cost 1 murderer pass"
- "You got %number%"
Detective:
Name: "&bBe detective"
Lore:
- "Cost 1 detective pass"
- "You got %number%"
Fail: "You do not got enough passes for %value% role"
Success: "You will be %value% next round!"
Change: "You now got %number% %value% passes!"
Playing:
Time-Left: "5,20,5;%arena_time% seconds left!;After %arena_time%s the Murderer will lose"
Role:
Change: "5,20,5;Previous %arena_player_role% has left!"
Murderer: "5,20,5;ROLE | MURDERER; Kill all players!"
Detective: "5,20,5;ROLE | DETECTIVE;Find and kill the murderer!"
Innocent: "5,20,5;ROLE | INNOCENT;Stay alive as long as possible!"
Score:
Bonus: "+%number% score (%value%)"
Gold: "Picked up gold!"
Action:
Kill:
Player: "for killing players"
Murderer: "for killing murderer"
Innocent: "for killing innocent"
Pickup:
Gold: "for gold pickup"
Surviving:
Time: "for surviving 30 seconds"
End: "for surviving till end"
Win: "for winning the game"
Detective: "for %number% innocents survived"
Sword:
Soon: "The Murderer gets their sword in %number% seconds!"
Special-Blocks:
Cauldron:
Potion: "Please drink your current potion!"
Hologram: "Mystery Potion - &e1 Gold"
Not-Enough-Gold: "You need %number% gold for this!"
Pray:
Hologram: "Click to give gift;Pull lever to pray"
Chat: "You prayed to the developer! Hope he will hear that!"
Pay: "%color_chat_issue%Pay to pray!"
Praise:
Heard:
- ""
- "&7Developer hears your prayer."
- "%feeling%"
- "%praise%"
Feeling:
Blessed: "&aYou feel blessed."
Cursed: "&cYou feel cursed."
Gifts:
Detective-Revelation: "&aYou know that &bCurrent detective &ais %detective%"
Gold-Rush: "&aYou received power of ancients. For each gold you collect, you will receive 3 gold now."
Single-Compensation: "&aDeveloper is proud of you! He rewarded you with 5 gold ingots!"
Bow: "&aYou received bow from pleased developer!"
Curses:
Slowness: "%color_chat_issue%Your legs are much heavier than before."
Blindness: "%color_chat_issue%Your eyes can't see that well anymore."
Gold: "%color_chat_issue%Developer cursed you with gold ban! You cannot longer pickup any gold!"
Death: "%color_chat_issue%You feel overpowering force of death. You know that you'll be dead in a minute!"
Bow:
Dropped: "5,20,5;The Bow has been dropped!;Find the Bow for a chance to kill the Murderer."
Pickup: "A player has picked up the Bow!"
Shot:
Gold: "&a+1 Bow Shot!"
Title: "5,20,5;;You collected 10 gold and got an arrow!"
#
# Sign messages
#
Signs:
Please-Type-Arena-Name: "%color_chat_issue%%plugin_prefix% Please type arena name in second line!"
Arena-Doesnt-Exists: "%color_chat_issue%%plugin_prefix% Arena with that name doesn't exists!"
Created: "%plugin_prefix% Sign created successfully!"
Removed: "%plugin_prefix% Sign successfully removed!"
Lines:
- "%plugin_prefix%"
- "%arena_state_placeholder%"
- "%arena_name%"
- "[%arena_players_size%/%arena_max_players%]"
#
# Arena Selector messages
#
Arena-Selector:
Inventory-Title: "%plugin_short_command% ▸ Arena selector"
Item:
Name: "%arena_name%"
Lore:
- "%plugin_name% - %arena_name%"
- " "
- " "
- " Online: %arena_players_size%/%arena_max_players%"
- " State: %arena_state_placeholder%"
- " "
- " "
- "&aClick to join this arena"
#
# Validator messages
#
Validator:
Invalid-Arena-Configuration: "Arena %arena_name% has invalid configuration! Missing node: %value%"
Instance-Started: "Arena %arena_name% instance successfully started!"
No-Instances-Created: "There are no arena instances created in configuration!"
#
# Placeholder messages inside plugin
#
Placeholders:
Game-States:
Waiting: "&lWaiting for players..."
Starting: "&e&lStarting"
Full-Game: "&4&lFULL"
In-Game: "&lIn-game"
Ending: "&lEnding"
Restarting: "&c&lRestarting"
Motd:
Waiting: "&lYou can join this game..."
Starting: "&e&lStarting"
Full-Game: "&4&lFULL | Use another Server"
In-Game: "&lIn-game | Click to spectate"
Ending: "&lEnding | Server is closing"
Restarting: "&c&lRestarting"
#
# Leaderboard messages
#
# Hologram function need to be enabled on config.yml
Leaderboard:
Type:
Hologram:
Header: "&6&lTop %number% in %value%"
Format: "&e%number%. %player% (%value%)"
Empty-Format: "&e%number%. Empty (0)"
Chat:
Header: "&8+-------+ &a&lYOUR STATS &8+-------+"
Header-Other: "&8+---------+ &aSTATS FOR &b%player% &8+---------+"
Footer: "&8+-----------------------------+"
Format: "%value% ▸ &a%number%"
Top:
Type-Name: "%color_chat_issue%Please type statistic name to view!"
Header: "&8&m+----------------+ [&6 Top 10 &8&m] +----------------+"
Format: "&e#%number% %player% - %value% %user_statistic%"
Statistics:
Wins: "Wins ▸ %number%"
Loses: "Loses ▸ %number%"
Games-Played: "Games Played ▸ %number%"
Level: "Level ▸ %number%"
Exp: "Experience ▸ %number%"
Next-Level-Exp: "Exp to Level Up ▸ %number%"
Kills: "Kills ▸ %number%"
Deaths: "Deaths ▸ %number%"
Highest-Score: "Highest score ▸ %number%"
Murderer-Pass: "Murderer passes ▸ %number%"
Detective-Pass: "Detective passes ▸ %number%"
Murderer-Contribution: "Murderer contribution ▸ %number%"
Detective-Contribution: "Detective contribution ▸ %number%"
Invalid-Name: "%color_chat_issue%Name of statistic is invalid! Type: %value%"
Unknown-Player: "%color_chat_issue%Unknown Player"
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/mysql.yml
================================================
# MySQL database configuration, you don't need to touch this unless you enabled MySQL support.
# To enable MySQL support go to > config.yml and set 'Database' to true
# Replace with your database
address: jdbc:mysql://localhost:3306/?useSSL=false&autoReConnect=true
# MySQL user name
user:
# MySQL user password
password:
# MySQL tablename
table: mm_playerstats
# Maximum life time for HikariCP database.
# For documentation, see https://github.com/brettwooldridge/HikariCP#frequently-used
# Default 1800000 = 30 minute
maxLifeTime: 1800000
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/permissions.yml
================================================
# You can create custom players permissions here.
# Player with your custom permission will get int
# All chances include murderer and detective
Chances-Boost:
# Do not use dots (.), they won't work.
# Increase chance by 10 times
chances-boost-5: 10
chances-boost-50: 50
# Increase chance by 100 times
admin-boost: 100
Murderer-Boost:
# Do not use dots (.), they won't work.
# Increase murderer chance by 10
murderer-boost-5: 10
murderer-boost-50: 50
# Increase murderer chance by 100
admin-boost: 100
Detective-Boost:
# Do not use dots (.), they won't work.
# Increase detective chance by 10
detective-boost-5: 10
detective-boost-50: 50
# Increase detective chance by 100
admin-boost: 100
# Create custom exp boost permissions
Exp-Boost:
# Do not use dots (.), they won't work.
# Increase exp by 10 percent
exp-boost-10: 10
exp-boost-50: 50
# Increase exp by 300 percent
admin-boost: 300
# Basic permissions for game, permissions explained here: https://wiki.plugily.xyz/
Basic:
Full-Games: "plugilyprojects.fullgames"
# represents arena name (NOT MAP NAME!), for example: 'plugilyprojects.join.ARENAnice'
# use 'plugilyprojects.join.*' to enable access to all arenas
Join: "plugilyprojects.join."
Forcestart: "plugilyprojects.admin.forcestart"
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/plugin.yml
================================================
name: MurderMystery
main: plugily.projects.murdermystery.Main
authors: [ PlugilyProjects, Tigerpanzer_02 ]
version: ${project.version}
softdepend: [CorpseReborn, PlaceholderAPI, Parties, Spigot-Party-API-PAF, PartyAndFriends, ViaVersion, ProtocolSupport]
api-version: 1.13
commands:
MurderMystery:
description: MurderMystery Commands
usage: "\u00A76Correct usage: /murdermystery [option]"
aliases: [mm, murder]
MurderMysteryAdmin:
description: MurderMysteryAdmin commands
usage: "\u00A76Correct usage: /murdermysterya [option]"
aliases: [mma, murderadmin]
permissions:
murdermystery.admin.*:
default: op
children:
murdermystery.updatenotify: true
murdermystery.admin: true
murdermystery.admin.setup: true
murdermystery.admin.delete: true
murdermystery.admin.list: true
murdermystery.admin.spychat: true
murdermystery.admin.stopgame: true
murdermystery.admin.forcestart: true
murdermystery.admin.addsign: true
murdermystery.admin.clear: true
murdermystery.admin.sign.create: true
murdermystery.admin.sign.break: true
murdermystery.admin.reload: true
murdermystery.command.override: true
================================================
FILE: src/main/resources/powerups.yml
================================================
## Murder Mystery powerups.yml
#
Powerups:
Pickup:
Chat: "&a%player% picked the &4Powerup %value% up"
Ended:
Title: "&4Powerup %value% from %player%"
Subtitle: "&chas ended"
Chat: "&4Powerup %value% from %player% has ended%"
Drop:
Chance: 1
Content:
Speed:
active: true
name: "&a&lSPEED BOOSTER"
description: "&7Double speed for %number% seconds!"
material: FEATHER
# Add as many potion effects as you want
# Format: PotionName, Duration, Amplifier
potion-effect:
- "SPEED, 15, 1"
# PLAYER for pickup player | ALL for all arena players
potion-type: PLAYER
# like rewards
execute:
- ""
Speed-All:
active: true
name: "&a&lSPEED BOOSTER FOR ALL"
description: "&7Double speed for all players in the next %number% seconds!"
material: FEATHER
# Add as many potion effects as you want
# Format: PotionName, Duration, Amplifier
potion-effect:
- "SPEED, 15, 1"
# PLAYER for pickup player | ALL for all arena players
potion-type: ALL
# like rewards
execute:
- ""
# Don't edit it. But who's stopping you? It's your server!
# Really, don't edit ;p
# You edited it, huh? Next time hurt yourself!
Do-Not-Edit:
File-Version: 1
Core-Version: 1
================================================
FILE: src/main/resources/rewards.yml
================================================
#
# Plugily Projects rewards configuration
#
# Placeholders list:
# https://wiki.plugily.xyz/minigame/placeholders
#
# Commands are executed by default BY CONSOLE, use "p:" to preform command by player
# You can use chance to execute command adding "chance(NUMBER):" (ex chance(10):) at the beginning of command
#
# Commands examples:
# - p:say Hello everyone in %arena_name%! # Player will say "Hello everyone in