/*
* Copyright 2015 Demigods RPG
* Copyright 2015 Alexander Chauncey
* Copyright 2015 Alex Bennett
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.demigodsrpg;
import com.demigodsrpg.aspect.Aspects;
import com.demigodsrpg.chitchat.Chitchat;
import com.demigodsrpg.chitchat.FactionChatTag;
import com.demigodsrpg.chitchat.FactionIdTag;
import com.demigodsrpg.command.*;
import com.demigodsrpg.command.admin.*;
import com.demigodsrpg.enchantment.CustomEnchantments;
import com.demigodsrpg.family.Family;
import com.demigodsrpg.listener.*;
import com.demigodsrpg.model.PlayerModel;
import com.demigodsrpg.model.TributeModel;
import com.demigodsrpg.registry.config.AreaRegistry;
import com.demigodsrpg.util.ZoneUtil;
import com.iciql.Db;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitScheduler;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
public class DGGame {
// -- PLUGIN RELATED CONSTANTS -- //
private static DGGame INST;
private static DGBukkitPlugin PLUGIN;
// -- ENABLE/DISABLE -- //
public DGGame(DGBukkitPlugin plugin) {
// Define the instances
INST = this;
PLUGIN = plugin;
DGData.PLUGIN = plugin;
// Define the console
DGData.CONSOLE = plugin.getLogger();
// Test for SQL connection if it is enabled
if (Setting.PSQL_PERSISTENCE) {
try {
Class.forName("org.postgresql.Driver");
Db.open(Setting.PSQL_CONNECTION).close();
DGData.CONSOLE.info("PSQL database saving enabled.");
} catch (Exception oops) {
oops.printStackTrace();
DGData.CONSOLE.warning("Could not load the PSQL driver.");
DGData.CONSOLE.warning("Defaulting to json file save.");
Setting.PSQL_PERSISTENCE = false;
}
} else {
DGData.CONSOLE.info("Json file database saving enabled.");
}
// Define the save path
DGData.SAVE_PATH = plugin.getDataFolder().getPath() + "/data/";
// Get custom factions and deities
DGData.FAMILY_R.registerFromDatabase();
DGData.DEITY_R.registerFromDatabase();
// Register default factions
DGData.FAMILY_R.register(Family.NEUTRAL);
DGData.FAMILY_R.register(Family.EXCOMMUNICATED);
// Debug data
if (Setting.DEBUG_DATA) {
DGData.CONSOLE.info("Enabling demo mode.");
// Debug deities
DGData.CONSOLE.info("Enabling demo deities.");
DGData.DEITY_R.register(Demo.D.LOREM);
DGData.DEITY_R.register(Demo.D.IPSUM);
DGData.DEITY_R.register(Demo.D.DOLOR);
DGData.DEITY_R.register(Demo.D.SIT);
DGData.DEITY_R.register(Demo.D.AMET);
// Debug factions
DGData.CONSOLE.info("Enabling demo factions.");
DGData.FAMILY_R.register(Demo.F.KŌHAI);
DGData.FAMILY_R.register(Demo.F.SENPAI);
DGData.FAMILY_R.register(Demo.F.SENSEI);
}
// Determine territory registries
for (World world : Bukkit.getWorlds()) {
AreaRegistry area_r = new AreaRegistry(world);
area_r.registerFromDatabase();
DGData.AREA_R.put(world.getName(), new AreaRegistry(world));
}
// Register the abilities
DGData.ABILITY_R.registerAbilities(Aspects.values());
// Regen shrines
DGData.SHRINE_R.generate();
// Fill up tribute data
if (DGData.TRIBUTE_R.getRegistered().isEmpty()) {
DGData.TRIBUTE_R.initializeTributeTracking();
}
// Start the threads
startThreads(plugin);
// Register the listeners
PluginManager manager = plugin.getServer().getPluginManager();
manager.registerEvents(new InventoryListener(), plugin);
manager.registerEvents(new PlayerListener(), plugin);
manager.registerEvents(new BattleListener(), plugin);
manager.registerEvents(new ShrineListener(), plugin);
manager.registerEvents(new TributeListener(), plugin);
manager.registerEvents(new AreaListener(), plugin);
manager.registerEvents(new AbilityListener(), plugin);
manager.registerEvents(DGData.ABILITY_R, plugin);
// Register commands
plugin.getCommand("family").setExecutor(new FamilyCommand());
plugin.getCommand("binds").setExecutor(new BindsCommand());
plugin.getCommand("check").setExecutor(new CheckCommand());
plugin.getCommand("aspect").setExecutor(new AspectCommand());
plugin.getCommand("cleanse").setExecutor(new CleanseCommand());
plugin.getCommand("shrine").setExecutor(new ShrineCommand());
plugin.getCommand("values").setExecutor(new ValuesCommand());
// Admin commands
plugin.getCommand("adminmode").setExecutor(new AdminModeComand());
plugin.getCommand("selectarea").setExecutor(new SelectAreaCommand());
plugin.getCommand("createfamily").setExecutor(new CreateFamilyCommand());
plugin.getCommand("createfamilyarea").setExecutor(new CreateFamilyAreaCommand());
plugin.getCommand("checkplayer").setExecutor(new CheckPlayerCommand());
plugin.getCommand("adddevotion").setExecutor(new AddDevotionCommand());
plugin.getCommand("removedevotion").setExecutor(new RemoveDevotionCommand());
plugin.getCommand("giveaspect").setExecutor(new GiveAspectCommand());
plugin.getCommand("removeaspect").setExecutor(new RemoveAspectCommand());
plugin.getCommand("setfamilyn").setExecutor(new SetFamilyCommand());
// Enable ZoneUtil
ZoneUtil.init(plugin);
// Handle Chitchat integration
if (manager.isPluginEnabled("Chitchat")) {
Chitchat.getChatFormat().add(new FactionChatTag());
Chitchat.getChatFormat().add(new FactionIdTag());
}
// Register custom enchantments
handleCustomEnchatments();
// Let the console know
DGData.CONSOLE.info(" ____ _ _");
DGData.CONSOLE.info(" | \\ ___ _____|_|___ ___ _| |___");
DGData.CONSOLE.info(" | | | -_| | | . | . | . |_ -|");
DGData.CONSOLE.info(" |____/|___|_|_|_|_|_ |___|___|___|");
DGData.CONSOLE.info(" Battle of the |___| Chosen");
DGData.CONSOLE.info(" ");
DGData.CONSOLE.info(" v. " + DGData.PLUGIN.getDescription().getVersion() + " enabled.");
}
public void onDisable(DGBukkitPlugin plugin) {
// Ensure that we unregister our commands and tasks
HandlerList.unregisterAll(plugin);
Bukkit.getScheduler().cancelTasks(plugin);
// Clear the cache.
DGData.clearCache();
// Let the console know
DGData.CONSOLE.info("Disabled successfully.");
}
// -- TASK RELATED -- //
private Runnable SYNC, ASYNC, FIRE_SPREAD, BATTLE, VALUE;
@SuppressWarnings("deprecation")
void startThreads(DGBukkitPlugin plugin) {
BukkitScheduler scheduler = Bukkit.getScheduler();
// Define the runnables
SYNC = () -> {
// Update online players
for (Player player : Bukkit.getOnlinePlayers()) {
if (ZoneUtil.inNoDGZone(player.getLocation())) continue;
PlayerModel model = DGData.PLAYER_R.fromPlayer(player);
if (model != null) {
model.updateCanPvp();
}
}
};
ASYNC = DGData.SERVER_R::clearExpired;
FIRE_SPREAD = () -> {
for (World world : Bukkit.getWorlds()) {
world.getLivingEntities().stream().filter(entity -> entity.getFireTicks() > 0).forEach(entity ->
entity.getNearbyEntities(0.5, 0.5, 0.5).stream().filter(nearby -> nearby instanceof LivingEntity && !nearby.equals(entity)).forEach(nearby -> nearby.setFireTicks(100))
);
}
};
BATTLE = DGData.BATTLE_R::endExpired;
VALUE = new TributeModel.ValueTask();
// Start sync demigods runnable
scheduler.scheduleSyncRepeatingTask(plugin, SYNC, 20, 20);
DGData.CONSOLE.info("Main Demigods SYNC thread enabled...");
// Start async demigods runnable
scheduler.scheduleAsyncRepeatingTask(plugin, ASYNC, 20, 20);
DGData.CONSOLE.info("Main Demigods ASYNC thread enabled...");
// Start sync fire runnable
scheduler.scheduleSyncRepeatingTask(plugin, FIRE_SPREAD, 3, 20);
DGData.CONSOLE.info("Demigods FIRE SPREAD task enabled...");
// Start sync fire runnable
scheduler.scheduleSyncRepeatingTask(plugin, BATTLE, 3, 20);
DGData.CONSOLE.info("Demigods BATTLE task enabled...");
// Start async value runnable
scheduler.scheduleAsyncRepeatingTask(plugin, VALUE, 60, 400);
DGData.CONSOLE.info("Demigods VALUE task enabled...");
}
@SuppressWarnings("unchecked")
void handleCustomEnchatments() {
try {
// Set the server to accept new enchantments
Field acceptNew = Enchantment.class.getDeclaredField("acceptingNew");
acceptNew.setAccessible(true);
acceptNew.set(null, true);
// Use reflection to get the maps from these fields
Field byIdField = Enchantment.class.getDeclaredField("byId");
Field byNameField = Enchantment.class.getDeclaredField("byName");
byIdField.setAccessible(true);
byNameField.setAccessible(true);
Map<Integer, Enchantment> byId = (Map<Integer, Enchantment>) byIdField.get(null);
Map<String, Enchantment> byName = (Map<String, Enchantment>) byNameField.get(null);
// Iterate over the custom enchantments
for (Enchantment enchant : CustomEnchantments.values()) {
// Remove the enchantments if they are already there
if (byId.containsKey(enchant.getId())) {
byId.remove(enchant.getId());
}
if (byName.containsKey(enchant.getName())) {
byName.remove(enchant.getName());
}
// Add the enchantments
try {
Enchantment.registerEnchantment(enchant);
} catch (Exception oops) {
DGData.CONSOLE.warning("Couldn't register a custom enchantment.");
oops.printStackTrace();
}
}
// Set the server to stop accepting new enchantments, just to be safe
acceptNew.set(null, false);
} catch (Exception ignored) {
}
DGData.CONSOLE.info("Custom enchantments injected.");
}
public static DGGame getInst() {
return INST;
}
public static DGBukkitPlugin getPlugin() {
return PLUGIN;
}
// -- DIRTY PRIVATE HELPER METHOD -- //
private void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
}