2018-09-21 03:42:18 +02:00
package com.songoda.epicheads ;
import com.songoda.epicheads.cache.CacheFile ;
import com.songoda.epicheads.cache.CacheHead ;
import com.songoda.epicheads.cache.ModsFile ;
import com.songoda.epicheads.cache.ModsFileHeader ;
import com.songoda.epicheads.cache.legacy.CacheFileConverter ;
import com.songoda.epicheads.cache.legacy.LegacyCacheConfig ;
import com.songoda.epicheads.command.CommandManager ;
import com.songoda.epicheads.config.FileConfigFile ;
import com.songoda.epicheads.config.MainConfig ;
import com.songoda.epicheads.config.menu.Menus ;
import com.songoda.epicheads.config.oldmenu.MenuConfig ;
import com.songoda.epicheads.economy.* ;
import com.songoda.epicheads.handlers.HeadNamer ;
import com.songoda.epicheads.handlers.LegacyIDs ;
import com.songoda.epicheads.menu.ui.InventoryMenu ;
import com.songoda.epicheads.oldmenu.ClickInventory ;
import com.songoda.epicheads.util.Clock ;
import com.songoda.epicheads.util.Methods ;
import com.songoda.epicheads.volatilecode.injection.ProtocolHackFixer ;
import com.songoda.epicheads.volatilecode.reflection.Version ;
import org.bukkit.Bukkit ;
import org.bukkit.GameMode ;
import org.bukkit.Location ;
import org.bukkit.command.ConsoleCommandSender ;
import org.bukkit.entity.Player ;
import org.bukkit.event.EventHandler ;
import org.bukkit.event.EventPriority ;
import org.bukkit.event.Listener ;
import org.bukkit.event.inventory.InventoryClickEvent ;
import org.bukkit.inventory.Inventory ;
import org.bukkit.inventory.InventoryHolder ;
import org.bukkit.plugin.Plugin ;
import org.bukkit.plugin.java.JavaPlugin ;
import org.bukkit.scheduler.BukkitRunnable ;
import java.io.File ;
import java.io.IOException ;
import java.util.function.Consumer ;
public class EpicHeads extends JavaPlugin implements Listener {
private static EpicHeads INSTANCE ;
private static ConsoleCommandSender console ;
private CacheFile cache ;
private MenuConfig oldMenuConfig ;
private Menus menus ;
private MainConfig mainConfig ;
private Economy economy ;
private LegacyIDs legacyIDs ;
private boolean blockStoreAvailable = false ;
private References references ;
private CommandManager commandManager ;
private Locale locale ;
@Override
public void onEnable ( ) {
console = this . getServer ( ) . getConsoleSender ( ) ;
INSTANCE = this ;
if ( Version . isBelow ( Version . v1_8 ) ) {
Methods . formatText ( " &c------------------------------------------------------------------- " ) ;
Methods . formatText ( " &c EpicHeads no longer supports versions below Minecraft 1.8. " ) ;
Methods . formatText ( " &c Please switch to Heads version 1.15.1 or before. " ) ;
Methods . formatText ( " &c------------------------------------------------------------------- " ) ;
Bukkit . getPluginManager ( ) . disablePlugin ( this ) ;
return ;
}
console . sendMessage ( Methods . formatText ( " &a============================= " ) ) ;
console . sendMessage ( Methods . formatText ( " &7EpicHeads " + this . getDescription ( ) . getVersion ( ) + " by &5Brianna <3! " ) ) ;
console . sendMessage ( Methods . formatText ( " &7Action: &aEnabling&7... " ) ) ;
Clock timer = Clock . start ( ) ;
loadCache ( ) ;
try {
legacyIDs = LegacyIDs . readResource ( " legacy-ids.txt " ) ;
} catch ( IOException exception ) {
legacyIDs = LegacyIDs . EMPTY ;
Methods . formatText ( " Unable to load legacy IDs to perform conversion from older Spigot versions " ) ;
exception . printStackTrace ( ) ;
}
// Locales
Locale . init ( this ) ;
Locale . saveDefaultLocale ( " en_US " ) ;
this . locale = Locale . getLocale ( getConfig ( ) . getString ( " Locale " , " en_US " ) ) ;
this . references = new References ( ) ;
this . menus = new Menus ( ) ;
this . menus . reload ( ) ;
this . oldMenuConfig = new MenuConfig ( getVersionedConfig ( " menus.yml " ) ) ;
this . mainConfig = new MainConfig ( ) ;
this . economy = hookEconomy ( ) ;
this . commandManager = new CommandManager ( this ) ;
ProtocolHackFixer . fix ( ) ;
tryHookBlockStore ( ) ;
2018-09-21 04:19:03 +02:00
new HeadNamer ( this ) . registerEvents ( ) ;
2018-09-21 03:42:18 +02:00
Bukkit . getPluginManager ( ) . registerEvents ( this , this ) ;
console . sendMessage ( Methods . formatText ( getDescription ( ) . getName ( ) + " has been enabled with " + cache . getHeadCount ( ) + " heads " + timer + " . " ) ) ;
console . sendMessage ( Methods . formatText ( " &a============================= " ) ) ;
}
@Override
public void onDisable ( ) {
INSTANCE = null ;
console . sendMessage ( Methods . formatText ( " &a============================= " ) ) ;
console . sendMessage ( Methods . formatText ( " &7EpicHeads " + this . getDescription ( ) . getVersion ( ) + " by &5Brianna <3! " ) ) ;
console . sendMessage ( Methods . formatText ( " &7Action: &cDisabling&7... " ) ) ;
console . sendMessage ( Methods . formatText ( " &a============================= " ) ) ;
}
public void reloadConfigs ( ) {
this . oldMenuConfig . reload ( ) ;
this . menus . reload ( ) ;
this . mainConfig . reload ( ) ;
this . locale . reloadMessages ( ) ;
this . economy = hookEconomy ( ) ;
this . tryHookBlockStore ( ) ;
}
public File getCacheFile ( ) {
if ( ! getDataFolder ( ) . exists ( ) & & ! getDataFolder ( ) . mkdirs ( ) )
throw new RuntimeException ( " Unable to create the data folder to save plugin files " ) ;
if ( ! getDataFolder ( ) . isDirectory ( ) )
throw new RuntimeException ( " plugins/EpicHeads should be a directory, yet there is a file with the same name " ) ;
return new File ( getDataFolder ( ) , " heads.cache " ) ;
}
private CacheFile loadCache ( ) {
File file = getCacheFile ( ) ;
FileConfigFile legacyConfig = new FileConfigFile ( " cache.yml " ) ;
boolean requiresWrite = false ;
if ( ! file . exists ( ) ) {
requiresWrite = true ;
if ( legacyConfig . getFile ( ) . exists ( ) ) {
Clock timer = Clock . start ( ) ;
LegacyCacheConfig legacy = new LegacyCacheConfig ( legacyConfig ) ;
cache = CacheFileConverter . convertToCacheFile ( " main-cache " , legacy ) ;
Methods . formatText ( " Converted legacy yaml cache file to new binary file " + timer ) ;
} else {
cache = new CacheFile ( " main-cache " ) ;
}
} else {
try {
Clock timer = Clock . start ( ) ;
cache = CacheFile . read ( file ) ;
Methods . formatText ( " Loaded cache file " + timer ) ;
} catch ( IOException e ) {
Methods . formatText ( " Unable to read heads.cache file " ) ;
throw new RuntimeException ( " There was an exception reading the heads.cache file " , e ) ;
}
}
if ( installAddons ( ) | | requiresWrite ) {
saveCache ( ) ;
}
if ( legacyConfig . getFile ( ) . exists ( ) & & ! legacyConfig . getFile ( ) . delete ( ) ) {
Methods . formatText ( " Unable to delete legacy yaml cache file " ) ;
}
return cache ;
}
public void saveCache ( ) {
File file = getCacheFile ( ) ;
try {
Clock timer = Clock . start ( ) ;
cache . write ( file ) ;
Methods . formatText ( " Saved cache file " + timer ) ;
} catch ( IOException e ) {
Methods . formatText ( " Unable to save the cache to heads.cache " ) ;
throw new RuntimeException ( " There was an exception saving the cache " , e ) ;
}
}
private ModsFileHeader readModsFileHeader ( ) {
try {
return ModsFileHeader . readResource ( " cache.mods " ) ;
} catch ( IOException e ) {
Methods . formatText ( " Unable to read header of cache.mods " ) ;
throw new RuntimeException ( " Unable to read header of cache.mods " , e ) ;
}
}
private ModsFile readModsFile ( ) {
try {
return ModsFile . readResource ( " cache.mods " ) ;
} catch ( IOException e ) {
Methods . formatText ( " Unable to read mods from cache.mods " ) ;
throw new RuntimeException ( " Unable to read mods from cache.mods " , e ) ;
}
}
private boolean installAddons ( ) {
Clock timer = Clock . start ( ) ;
ModsFileHeader header = readModsFileHeader ( ) ;
int newMods = header . getUninstalledMods ( cache ) ;
if ( newMods = = 0 )
return false ;
ModsFile mods = readModsFile ( ) ;
int newHeads = mods . installMods ( cache ) ;
if ( newHeads > 0 ) {
Methods . formatText ( " Added " + newHeads + " new heads from " + newMods + " addons " + timer ) ;
} else {
Methods . formatText ( " Installed " + newMods + " addons " + timer ) ;
}
return true ;
}
private Economy hookEconomy ( ) {
if ( ! mainConfig . isEconomyEnabled ( ) )
return new NoEconomy ( ) ;
Economy economy = null ;
if ( mainConfig . isVaultEconomyEnabled ( ) ) {
economy = tryHookEconomy ( null , new VaultEconomy ( ) ) ;
}
if ( mainConfig . isItemEconomyEnabled ( ) ) {
economy = tryHookEconomy ( economy , new ItemEconomy ( ) ) ;
}
if ( mainConfig . isPlayerPointsEconomyEnabled ( ) ) {
economy = tryHookEconomy ( economy , new PlayerPointsEconomy ( ) ) ;
}
if ( economy = = null | | economy instanceof NoEconomy ) {
Methods . formatText ( " Economy enabled in config.yml yet Vault, PlayerPoints and Item economies disabled. " + " Player's will not be able to purchase heads. " ) ;
economy = ( economy ! = null ? economy : new NoEconomy ( ) ) ;
}
return economy ;
}
private Economy tryHookEconomy ( Economy currentlyHooked , Economy toHook ) {
if ( currentlyHooked ! = null ) {
Methods . formatText ( toHook . getName ( ) + " economy is not the only economy enabled in the config.yml. " ) ;
if ( ! ( currentlyHooked instanceof NoEconomy ) )
return currentlyHooked ;
}
if ( ! toHook . tryHook ( ) ) {
Methods . formatText ( toHook . getName ( ) + " enabled in config.yml, yet Heads was unable to hook into it. " ) ;
return new NoEconomy ( ) ;
}
Methods . formatText ( " Loaded " + toHook . getName ( ) + " economy " ) ;
return toHook ;
}
private void tryHookBlockStore ( ) {
if ( mainConfig . shouldUseBlockStore ( ) & & Bukkit . getPluginManager ( ) . getPlugin ( " BlockStore " ) ! = null ) {
blockStoreAvailable = false ;
try {
Class < ? > apiClass = Class . forName ( " net.sothatsit.blockstore.BlockStoreApi " ) ;
apiClass . getDeclaredMethod ( " retrieveBlockMeta " , Plugin . class , Location . class , Plugin . class , String . class , Consumer . class ) ;
Methods . formatText ( " Hooked BlockStore " ) ;
blockStoreAvailable = true ;
} catch ( ClassNotFoundException | NoSuchMethodException e ) {
Methods . formatText ( " Unable to hook BlockStore, the version of BlockStore you are " + " using may be outdated. Heads requires BlockStore v1.5.0. " ) ;
Methods . formatText ( " Please update BlockStore and report this to Sothatsit if the problem persists. " ) ;
}
}
}
@EventHandler ( priority = EventPriority . HIGHEST )
public void onInventoryClick ( InventoryClickEvent e ) {
Inventory inventory = e . getInventory ( ) ;
if ( inventory = = null )
return ;
InventoryHolder holder = inventory . getHolder ( ) ;
if ( holder instanceof ClickInventory ) {
( ( ClickInventory ) holder ) . onClick ( e ) ;
} else if ( holder instanceof InventoryMenu ) {
( ( InventoryMenu ) holder ) . onClick ( e ) ;
}
}
2018-09-21 04:19:03 +02:00
private boolean isExemptFromCost ( Player player ) {
2018-09-21 03:42:18 +02:00
if ( ! mainConfig . isEconomyEnabled ( ) | | player . hasPermission ( " EpicHeads.bypasscost " ) )
return true ;
return mainConfig . isFreeInCreative ( ) & & player . getGameMode ( ) = = GameMode . CREATIVE ;
}
public boolean chargeForHead ( Player player , CacheHead head ) {
if ( isExemptFromCost ( player ) )
return true ;
double cost = head . getCost ( ) ;
if ( cost < = 0 )
return true ;
if ( ! economy . hasBalance ( player , cost ) ) {
2018-09-21 04:19:03 +02:00
player . sendMessage ( getLocale ( ) . getMessage ( " interface.get.notenoughmoney " , head . getName ( ) , head . getCost ( ) ) ) ;
2018-09-21 03:42:18 +02:00
return false ;
}
if ( ! economy . takeBalance ( player , cost ) ) {
2018-09-21 04:19:03 +02:00
player . sendMessage ( getLocale ( ) . getMessage ( " interface.get.transactionerror " , head . getName ( ) , head . getCost ( ) ) ) ;
2018-09-21 03:42:18 +02:00
return false ;
}
2018-09-21 04:19:03 +02:00
player . sendMessage ( getLocale ( ) . getMessage ( " interface.get.purchased " , head . getName ( ) , head . getCost ( ) ) ) ;
2018-09-21 03:42:18 +02:00
return true ;
}
2018-09-21 04:19:03 +02:00
public String getCategoryPermission ( String category ) {
2018-09-21 03:42:18 +02:00
return " EpicHeads.category. " + category . toLowerCase ( ) . replace ( ' ' , '_' ) ;
}
//ToDO: these shouldn't be static.
public static EpicHeads getInstance ( ) {
return INSTANCE ;
}
2018-09-21 04:19:03 +02:00
public LegacyIDs getLegacyIDs ( ) {
2018-09-21 03:42:18 +02:00
return INSTANCE . legacyIDs ;
}
2018-09-21 04:19:03 +02:00
public MainConfig getMainConfig ( ) {
2018-09-21 03:42:18 +02:00
return INSTANCE . mainConfig ;
}
2018-09-21 04:19:03 +02:00
public CacheFile getCache ( ) {
2018-09-21 03:42:18 +02:00
return INSTANCE . cache ;
}
2018-09-21 04:19:03 +02:00
public Menus getMenus ( ) {
2018-09-21 03:42:18 +02:00
return INSTANCE . menus ;
}
2018-09-21 04:19:03 +02:00
public MenuConfig getMenuConfig ( ) {
2018-09-21 03:42:18 +02:00
return INSTANCE . oldMenuConfig ;
}
2018-09-21 04:19:03 +02:00
public Economy getEconomy ( ) {
2018-09-21 03:42:18 +02:00
return INSTANCE . economy ;
}
2018-09-21 04:19:03 +02:00
public boolean isBlockStoreAvailable ( ) {
2018-09-21 03:42:18 +02:00
return INSTANCE . blockStoreAvailable ;
}
2018-09-21 04:19:03 +02:00
public void sync ( Runnable task ) {
2018-09-21 03:42:18 +02:00
Bukkit . getScheduler ( ) . runTask ( INSTANCE , task ) ;
}
2018-09-21 04:19:03 +02:00
public FileConfigFile getVersionedConfig ( String resource ) {
2018-09-21 03:42:18 +02:00
if ( Version . isBelow ( Version . v1_13 ) )
return new FileConfigFile ( resource , " pre1_13/ " + resource ) ;
return new FileConfigFile ( resource ) ;
}
public CommandManager getCommandManager ( ) {
return commandManager ;
}
public Locale getLocale ( ) {
return locale ;
}
public References getReferences ( ) {
return references ;
}
}