/* * To change this template, choose Tools | Templates and open the template in * the editor. */ package com.bekvon.bukkit.residence; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.regex.Pattern; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import com.bekvon.bukkit.residence.chat.ChatManager; import com.bekvon.bukkit.residence.commandmain.CommandRc; import com.bekvon.bukkit.residence.commandmain.CommandRes; import com.bekvon.bukkit.residence.commandmain.CommandResLoad; import com.bekvon.bukkit.residence.commandmain.CommandResReload; import com.bekvon.bukkit.residence.commandmain.CommandResWorld; import com.bekvon.bukkit.residence.economy.EconomyInterface; import com.bekvon.bukkit.residence.economy.EssentialsEcoAdapter; import com.bekvon.bukkit.residence.economy.TransactionManager; import com.bekvon.bukkit.residence.economy.rent.RentManager; import com.bekvon.bukkit.residence.event.ResidenceCommandEvent; import com.bekvon.bukkit.residence.itemlist.WorldItemManager; import com.bekvon.bukkit.residence.listeners.ResidenceBlockListener; import com.bekvon.bukkit.residence.listeners.ResidenceEntityListener; import com.bekvon.bukkit.residence.listeners.ResidencePlayerListener; import com.bekvon.bukkit.residence.listeners.ResidencePlayerListener_1_8; import com.bekvon.bukkit.residence.listeners.bugfix.ResidenceBugFix; import com.bekvon.bukkit.residence.manager.ConfigManager; import com.bekvon.bukkit.residence.manager.EntityManager; import com.bekvon.bukkit.residence.manager.FlagManager; import com.bekvon.bukkit.residence.permissions.PermissionManager; import com.bekvon.bukkit.residence.persistance.YMLSaveHelper; import com.bekvon.bukkit.residence.protection.ClaimedResidence; import com.bekvon.bukkit.residence.protection.FlagPermissions; import com.bekvon.bukkit.residence.protection.LeaseManager; import com.bekvon.bukkit.residence.protection.PermissionListManager; import com.bekvon.bukkit.residence.protection.ResidenceManager; import com.bekvon.bukkit.residence.protection.WorldFlagManager; import com.bekvon.bukkit.residence.runnable.AutoSaveTask; import com.bekvon.bukkit.residence.runnable.HealTask; import com.bekvon.bukkit.residence.runnable.LeaseTask; import com.bekvon.bukkit.residence.runnable.RentTask; import com.bekvon.bukkit.residence.runnable.TaskManager; import com.bekvon.bukkit.residence.selection.SelectionManager; import com.bekvon.bukkit.residence.selection.WorldEditSelectionManager; import com.bekvon.bukkit.residence.text.Language; import com.bekvon.bukkit.residence.text.help.HelpEntry; import com.bekvon.bukkit.residence.text.help.InformationPager; import com.bekvon.bukkit.residence.utils.DataBackup; import com.bekvon.bukkit.residence.vaultinterface.ResidenceVaultAdapter; import com.earth2me.essentials.Essentials; import cn.citycraft.PluginHelper.commands.HandlerMainCommand; import cn.citycraft.PluginHelper.config.FileConfig; import cn.citycraft.PluginHelper.utils.VersionChecker; /** * * @author Gary Smoak - bekvon * */ public class ResidenceMain extends JavaPlugin { public static float bukkitver; public final static int saveVersion = 1; public final static String[] validLanguages = { "English", "Chinese" }; public final static Pattern VER_REGEX = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)"); protected static ResidenceMain instance; protected DataBackup backup; protected ResidenceBlockListener blistener; protected ChatManager chatmanager; protected ConfigManager cmanager; protected FileConfig config; protected File dataFolder; protected Map deleteConfirm; protected EconomyInterface economy; protected ResidenceEntityListener elistener; protected EntityManager entitymanager; protected boolean firstenable = true; protected FlagManager fmanager; protected PermissionManager gmanager; protected HandlerMainCommand hdmcnd; protected HelpEntry helppages; protected WorldItemManager imanager; protected boolean init; protected Language language; protected LeaseManager leasemanager; protected ResidencePlayerListener plistener; protected ResidencePlayerListener_1_8 plistener1_8; protected PermissionListManager pmanager; protected RentManager rentmanager; protected List resadminToggle; protected ResidenceManager rmanager; protected SelectionManager smanager; protected TaskManager taskmanager; protected TransactionManager tmanager; protected boolean useWorldEdit; protected WorldFlagManager wmanager; public static ResidenceMain getInstance() { return instance; } public DataBackup getBackup() { return backup; } public ResidenceBlockListener getBlockListener() { return blistener; } public ChatManager getChatManager() { return chatmanager; } @Override public FileConfiguration getConfig() { return config; } public ConfigManager getConfigManager() { return cmanager; } public File getDataLocation() { return dataFolder; } public Map getDeleteConfirm() { return deleteConfirm; } public EconomyInterface getEconomyManager() { return economy; } public ResidenceEntityListener getEntityListener() { return elistener; } public EntityManager getEntityManager() { return entitymanager; } public HelpEntry getHelppages() { return helppages; } public WorldItemManager getItemManager() { return imanager; } public Language getLanguage() { if (language == null) { language = new Language(); } return language; } public LeaseManager getLeaseManager() { return leasemanager; } public PermissionListManager getPermissionListManager() { return pmanager; } public PermissionManager getPermissionManager() { return gmanager; } public FlagPermissions getPermsByLoc(final Location loc) { final ClaimedResidence res = rmanager.getByLoc(loc); if (res != null) { return res.getPermissions(); } else { return wmanager.getPerms(loc.getWorld().getName()); } } public FlagPermissions getPermsByLocForPlayer(final Location loc, final Player player) { final ClaimedResidence res = rmanager.getByLoc(loc); if (res != null) { return res.getPermissions(); } else if (player != null) { return wmanager.getPerms(player); } else { return wmanager.getPerms(loc.getWorld().getName()); } } public ResidencePlayerListener getPlayerListener() { return plistener; } public RentManager getRentManager() { return rentmanager; } public ResidenceManager getResidenceManager() { return rmanager; } public SelectionManager getSelectionManager() { return smanager; } public TransactionManager getTransactionManager() { return tmanager; } public WorldFlagManager getWorldFlags() { return wmanager; } public boolean is1_8() { return bukkitver == 1.8; } public boolean isInit() { return init; } public boolean isResAdminOn(final Player player) { if (resadminToggle.contains(player.getName())) { return true; } return false; } public boolean isResAdminOn(final String player) { if (resadminToggle.contains(player.toLowerCase())) { return true; } return false; } public boolean isUseWorldEdit() { return useWorldEdit; } public void loadLang(final File langFile) throws FileNotFoundException, IOException, InvalidConfigurationException { final FileConfig langconfig = new FileConfig(this, langFile); helppages = HelpEntry.parseHelp(this, langconfig, "CommandHelp"); HelpEntry.setLinesPerPage(langconfig.getInt("HelpLinesPerPage", 7)); InformationPager.setLinesPerPage(langconfig.getInt("HelpLinesPerPage", 7)); language = Language.parseText(langconfig, "Language"); } @SuppressWarnings("unchecked") public boolean loadYml() throws Exception { final File saveFolder = new File(dataFolder, "Save"); try { final File worldFolder = new File(saveFolder, "Worlds"); if (!saveFolder.isDirectory()) { this.getLogger().warning("领地数据保存目录不存在..."); this.getLogger().warning("请重新启动服务器生成新的文件..."); return true; } YMLSaveHelper yml; File loadFile; final long time = System.currentTimeMillis(); final HashMap worlds = new HashMap(); for (final World world : this.getServer().getWorlds()) { loadFile = new File(worldFolder, "res_" + world.getName() + ".yml"); if (loadFile.isFile()) { yml = new YMLSaveHelper(loadFile); yml.load(); worlds.put(world.getName(), yml.getRoot().get("Residences")); } } rmanager = ResidenceManager.load(this, worlds); loadFile = new File(saveFolder, "forsale.yml"); if (loadFile.isFile()) { yml = new YMLSaveHelper(loadFile); yml.load(); tmanager = TransactionManager.load(this, (Map) yml.getRoot().get("Economy"), gmanager, rmanager); } loadFile = new File(saveFolder, "leases.yml"); if (loadFile.isFile()) { yml = new YMLSaveHelper(loadFile); yml.load(); leasemanager = LeaseManager.load(this, (Map) yml.getRoot().get("Leases"), rmanager); } loadFile = new File(saveFolder, "permlists.yml"); if (loadFile.isFile()) { yml = new YMLSaveHelper(loadFile); yml.load(); pmanager = PermissionListManager.load(this, (Map) yml.getRoot().get("PermissionLists")); } loadFile = new File(saveFolder, "rent.yml"); if (loadFile.isFile()) { yml = new YMLSaveHelper(loadFile); yml.load(); rentmanager = RentManager.load(this, (Map) yml.getRoot().get("RentSystem")); } this.getLogger().info("从配置文件中读取领地数据,耗时 " + ((float) (System.currentTimeMillis() - time) / 1000) + " 秒"); return true; } catch (final Exception ex) { this.getLogger().warning("领地数据载入时发生错误,请报告以下内容给作者: "); this.getLogger().warning("错误: " + ex); throw ex; } } @Override public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) { final ResidenceCommandEvent cevent = new ResidenceCommandEvent(command.getName(), args, sender); this.getServer().getPluginManager().callEvent(cevent); if (cevent.isCancelled()) { return true; } return hdmcnd.onCommand(sender, command, label, args); } @Override public void onDisable() { taskmanager.cancelall(); if (this.init) { try { this.saveYml(); this.backup.backup(); } catch (final Exception ex) { this.getLogger().warning("领地数据保存错误,可能造成部分领地丢失,请尝试恢复备份文件!"); this.getLogger().warning("错误: " + ex); } } } @Override public void onEnable() { try { instance = this; this.getLogger().info("Bukkit 版本: " + this.getServer().getBukkitVersion()); bukkitver = Float.parseFloat(this.getServer().getBukkitVersion().substring(0, 3)); init = false; deleteConfirm = new HashMap(); resadminToggle = new ArrayList(); dataFolder = this.getDataFolder(); if (!dataFolder.isDirectory()) { dataFolder.mkdirs(); } cmanager = new ConfigManager(this); final String multiworld = cmanager.getMultiworldPlugin(); if (multiworld != null) { final Plugin plugin = this.getServer().getPluginManager().getPlugin(multiworld); if (plugin != null) { if (!plugin.isEnabled()) { this.getLogger().info("加载多世界插件: " + multiworld); this.getServer().getPluginManager().enablePlugin(plugin); } } } gmanager = new PermissionManager(this); imanager = new WorldItemManager(this.getConfig()); wmanager = new WorldFlagManager(this); entitymanager = new EntityManager(this); chatmanager = new ChatManager(this); rentmanager = new RentManager(this); for (final String lang : validLanguages) { try { if (this.checkNewLanguageVersion(lang)) { this.writeDefaultLanguageFile(lang); } } catch (final Exception ex) { this.getLogger().warning("语言文件升级失败: " + lang + ".yml"); helppages = new HelpEntry(this, ""); language = new Language(); } } final File langFile = new File(new File(dataFolder, "Language"), cmanager.getLanguage() + ".yml"); try { if (langFile.isFile()) { loadLang(langFile); } else { this.getLogger().warning("语言文件不存在..."); } } catch (final Exception ex) { this.getLogger().warning("语言文件载入失败: " + cmanager.getLanguage() + ".yml 写入默认语言文件"); this.writeDefaultLanguageFile(cmanager.getLanguage()); loadLang(langFile); } economy = null; if (this.getConfig().getBoolean("Global.EnableEconomy", false)) { if (gmanager.getPermissionsPlugin() instanceof ResidenceVaultAdapter) { final ResidenceVaultAdapter vault = (ResidenceVaultAdapter) gmanager.getPermissionsPlugin(); if (vault.economyOK()) { economy = vault; this.getLogger().info("发现 Vault 使用经济系统: " + vault.getEconomyName()); } } if (economy == null) { this.loadVaultEconomy(); } if (economy == null) { this.loadEssentialsEconomy(); } if (economy == null) { this.getLogger().warning("经济系统已启用,但是未找到经济插件..."); } } try { this.loadYml(); } catch (final Exception e) { this.getLogger().warning("领地数据载入错误,可能造成插件无法启动,请尝试恢复备份文件!"); this.getLogger().warning("错误: " + e); } if (rmanager == null) { rmanager = new ResidenceManager(this); } if (leasemanager == null) { leasemanager = new LeaseManager(this, rmanager); } if (tmanager == null) { tmanager = new TransactionManager(this, rmanager, gmanager); } if (pmanager == null) { pmanager = new PermissionListManager(this); } if (taskmanager == null) { taskmanager = new TaskManager(this); } final PluginManager pm = getServer().getPluginManager(); if (firstenable) { if (!this.isEnabled()) { return; } FlagPermissions.initValidFlags(this); final Plugin wep = this.getServer().getPluginManager().getPlugin("WorldEdit"); if (wep != null) { smanager = new WorldEditSelectionManager(this); useWorldEdit = true; this.getLogger().info("发现 WorldEdit 已启用相关支持..."); } else { smanager = new SelectionManager(this); useWorldEdit = false; } blistener = new ResidenceBlockListener(this); plistener = new ResidencePlayerListener(this); elistener = new ResidenceEntityListener(this); plistener1_8 = new ResidencePlayerListener_1_8(this); pm.registerEvents(blistener, this); pm.registerEvents(plistener, this); if (is1_8()) { pm.registerEvents(plistener1_8, this); } pm.registerEvents(elistener, this); firstenable = false; } else { plistener = new ResidencePlayerListener(this); } fmanager = new FlagManager(this); fmanager.init(); this.getLogger().info("开始加载领地补丁..."); pm.registerEvents(new ResidenceBugFix(this), this); taskmanager.add(this.getServer().getScheduler().runTaskTimer(this, new HealTask(this), 20, 20)); hdmcnd = new HandlerMainCommand(this); hdmcnd.registerCommand(new CommandRc(this)); hdmcnd.registerCommand(new CommandRes(this)); hdmcnd.registerCommand(new CommandResLoad(this)); hdmcnd.registerCommand(new CommandResReload(this)); hdmcnd.registerCommand(new CommandResWorld(this)); int autosaveInt = cmanager.getAutoSaveInterval(); autosaveInt = autosaveInt < 1 ? 1 : autosaveInt * 60 * 20; taskmanager.add(this.getServer().getScheduler().runTaskTimer(this, new AutoSaveTask(this), autosaveInt, autosaveInt)); if (cmanager.useLeases()) { int leaseInterval = cmanager.getLeaseCheckInterval(); leaseInterval = leaseInterval < 1 ? 1 : leaseInterval * 60 * 20; taskmanager.add(this.getServer().getScheduler().runTaskTimer(this, new LeaseTask(this), leaseInterval, leaseInterval)); } if (cmanager.enabledRentSystem()) { int rentint = cmanager.getRentCheckInterval(); rentint = rentint < 1 ? 1 : rentint * 60 * 20; taskmanager.add(this.getServer().getScheduler().runTaskTimer(this, new RentTask(this), rentint, rentint)); } for (final Player player : Bukkit.getServer().getOnlinePlayers()) { if (this.getPermissionManager().isResidenceAdmin(player)) { turnResAdminOn(player); } } this.getLogger().info("载入完成! 版本: " + this.getDescription().getVersion() + " 重制 by 喵♂呜"); backup = new DataBackup(this); init = true; } catch (final Exception ex) { this.getServer().getPluginManager().disablePlugin(this); this.getLogger().warning(" - 初始化失败! 卸载插件! 请报告以下错误给作者,谢谢!"); this.getLogger().warning("错误: " + ex); ex.printStackTrace(); init = false; } final CommandSender console = Bukkit.getConsoleSender(); try { new Residence(this); this.getLogger().info("旧版本兼容接口初始化成功..."); } catch (final Exception e) { console.sendMessage("§6[§a领地插件§6] §c旧版本兼容接口初始化失败 可能导致部分插件不可用!"); console.sendMessage("§6[§a领地插件§6] §e请报告以下错误给作者 §6错误原因: §4" + e.getMessage()); } new VersionChecker(this); } @Override public void onLoad() { config = new FileConfig(this); } @Override public void reloadConfig() { config.reload(); } public void reloadPlugin() { final PluginManager pm = this.getServer().getPluginManager(); pm.disablePlugin(this); pm.enablePlugin(this); } @Override public void saveConfig() { config.save(); }; public void saveYml() throws IOException { final File saveFolder = new File(dataFolder, "Save"); final File worldFolder = new File(saveFolder, "Worlds"); worldFolder.mkdirs(); YMLSaveHelper yml; final long time = System.currentTimeMillis(); final Map save = rmanager.save(); for (final Entry entry : save.entrySet()) { final File ymlSaveLoc = new File(worldFolder, "res_" + entry.getKey() + ".yml"); final File tmpFile = new File(worldFolder, "tmp_res_" + entry.getKey() + ".yml"); yml = new YMLSaveHelper(tmpFile); yml.getRoot().put("Version", saveVersion); final World world = this.getServer().getWorld(entry.getKey()); if (world != null) { yml.getRoot().put("Seed", world.getSeed()); } yml.getRoot().put("Residences", entry.getValue()); yml.save(); if (ymlSaveLoc.isFile()) { final File backupFolder = new File(worldFolder, "Backup"); backupFolder.mkdirs(); final File backupFile = new File(backupFolder, "res_" + entry.getKey() + ".yml"); if (backupFile.isFile()) { backupFile.delete(); } ymlSaveLoc.renameTo(backupFile); } tmpFile.renameTo(ymlSaveLoc); } // For Sale save File ymlSaveLoc = new File(saveFolder, "forsale.yml"); File tmpFile = new File(saveFolder, "tmp_forsale.yml"); yml = new YMLSaveHelper(tmpFile); yml.getRoot().put("Version", saveVersion); yml.getRoot().put("Economy", tmanager.save()); yml.save(); if (ymlSaveLoc.isFile()) { final File backupFolder = new File(saveFolder, "Backup"); backupFolder.mkdirs(); final File backupFile = new File(backupFolder, "forsale.yml"); if (backupFile.isFile()) { backupFile.delete(); } ymlSaveLoc.renameTo(backupFile); } tmpFile.renameTo(ymlSaveLoc); // Leases save ymlSaveLoc = new File(saveFolder, "leases.yml"); tmpFile = new File(saveFolder, "tmp_leases.yml"); yml = new YMLSaveHelper(tmpFile); yml.getRoot().put("Version", saveVersion); yml.getRoot().put("Leases", leasemanager.save()); yml.save(); if (ymlSaveLoc.isFile()) { final File backupFolder = new File(saveFolder, "Backup"); backupFolder.mkdirs(); final File backupFile = new File(backupFolder, "leases.yml"); if (backupFile.isFile()) { backupFile.delete(); } ymlSaveLoc.renameTo(backupFile); } tmpFile.renameTo(ymlSaveLoc); // permlist save ymlSaveLoc = new File(saveFolder, "permlists.yml"); tmpFile = new File(saveFolder, "tmp_permlists.yml"); yml = new YMLSaveHelper(tmpFile); yml.getRoot().put("Version", saveVersion); yml.getRoot().put("PermissionLists", pmanager.save()); yml.save(); if (ymlSaveLoc.isFile()) { final File backupFolder = new File(saveFolder, "Backup"); backupFolder.mkdirs(); final File backupFile = new File(backupFolder, "permlists.yml"); if (backupFile.isFile()) { backupFile.delete(); } ymlSaveLoc.renameTo(backupFile); } tmpFile.renameTo(ymlSaveLoc); // rent save ymlSaveLoc = new File(saveFolder, "rent.yml"); tmpFile = new File(saveFolder, "tmp_rent.yml"); yml = new YMLSaveHelper(tmpFile); yml.getRoot().put("Version", saveVersion); yml.getRoot().put("RentSystem", rentmanager.save()); yml.save(); if (ymlSaveLoc.isFile()) { final File backupFolder = new File(saveFolder, "Backup"); backupFolder.mkdirs(); final File backupFile = new File(backupFolder, "rent.yml"); if (backupFile.isFile()) { backupFile.delete(); } ymlSaveLoc.renameTo(backupFile); } tmpFile.renameTo(ymlSaveLoc); this.getLogger().info("保存领地数据到文件中,耗时 " + ((float) (System.currentTimeMillis() - time) / 1000) + " 秒"); if (cmanager.showIntervalMessages()) { this.getLogger().info(" - 保存插件数据..."); } } public void turnResAdminOn(final Player player) { resadminToggle.add(player.getName()); } public boolean validName(final String name) { if (name.contains(":") || name.contains(".")) { return false; } if (cmanager.getResidenceNameRegex() == null) { return true; } else { final String namecheck = name.replaceAll(cmanager.getResidenceNameRegex(), ""); if (!name.equals(namecheck)) { return false; } return true; } } private boolean checkNewLanguageVersion(final String lang) throws IOException, FileNotFoundException, InvalidConfigurationException { final File outFile = new File(new File(this.getDataFolder(), "Language"), lang + ".yml"); final File checkFile = new File(new File(this.getDataFolder(), "Language"), "temp-" + lang + ".yml"); if (outFile.isFile()) { final FileConfig testconfig = new FileConfig(this, outFile); final int oldversion = testconfig.getInt("FieldsVersion", 0); if (!this.writeDefaultFileFromJar(checkFile, "languagefiles/" + lang + ".yml", false)) { return false; } final FileConfig testconfig2 = new FileConfig(this, checkFile); testconfig2.load(checkFile); final int newversion = testconfig2.getInt("FieldsVersion", oldversion); if (checkFile.isFile()) { checkFile.delete(); } if (newversion > oldversion) { return true; } return false; } return true; } private void loadEssentialsEconomy() { final Plugin p = getServer().getPluginManager().getPlugin("Essentials"); if (p != null) { economy = new EssentialsEcoAdapter((Essentials) p); this.getLogger().info("成功关联Essentials Economy!"); } else { this.getLogger().info("Essentials Economy 未找到!"); } } private void loadVaultEconomy() { final Plugin p = getServer().getPluginManager().getPlugin("Vault"); if (p != null) { final ResidenceVaultAdapter vault = new ResidenceVaultAdapter(getServer()); if (vault.economyOK()) { this.getLogger().info("发现 Vault 使用经济系统: " + vault.getEconomyName()); economy = vault; } else { this.getLogger().info("发现 Vault, 但是 Vault 未找到经济系统..."); } } else { this.getLogger().info("Vault 未找到!"); } } @SuppressWarnings("resource") private boolean writeDefaultFileFromJar(final File writeName, final String jarPath, final boolean backupOld) { try { final File fileBackup = new File(this.getDataFolder(), "backup-" + writeName); final File jarloc = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getCanonicalFile(); if (jarloc.isFile()) { final JarFile jar = new JarFile(jarloc); final JarEntry entry = jar.getJarEntry(jarPath); if (entry != null && !entry.isDirectory()) { final InputStream in = jar.getInputStream(entry); final InputStreamReader isr = new InputStreamReader(in, "UTF8"); if (writeName.isFile()) { if (backupOld) { if (fileBackup.isFile()) { fileBackup.delete(); } writeName.renameTo(fileBackup); } else { writeName.delete(); } } final FileOutputStream out = new FileOutputStream(writeName); final OutputStreamWriter osw = new OutputStreamWriter(out, "UTF8"); final char[] tempbytes = new char[512]; int readbytes = isr.read(tempbytes, 0, 512); while (readbytes > -1) { osw.write(tempbytes, 0, readbytes); readbytes = isr.read(tempbytes, 0, 512); } osw.close(); isr.close(); return true; } } return false; } catch (final Exception ex) { this.getLogger().warning("文件写入失败: " + writeName); return false; } } private void writeDefaultLanguageFile(final String lang) { final File outFile = new File(new File(this.getDataFolder(), "Language"), lang + ".yml"); outFile.getParentFile().mkdirs(); if (this.writeDefaultFileFromJar(outFile, "languagefiles/" + lang + ".yml", true)) { this.getLogger().info("保存默认 " + lang + " 语言文件..."); } } }