Advertisement
Guest User

Untitled

a guest
Jan 18th, 2018
340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 46.46 KB | None | 0 0
  1. package io.github.nucleuspowered.nucleus;
  2.  
  3. import static io.github.nucleuspowered.nucleus.PluginInfo.DESCRIPTION;
  4. import static io.github.nucleuspowered.nucleus.PluginInfo.ID;
  5. import static io.github.nucleuspowered.nucleus.PluginInfo.NAME;
  6. import static io.github.nucleuspowered.nucleus.PluginInfo.VERSION;
  7.  
  8. import com.google.common.collect.Lists;
  9. import com.google.common.collect.Maps;
  10. import com.google.common.collect.Sets;
  11. import com.google.gson.Gson;
  12. import com.google.gson.reflect.TypeToken;
  13. import com.typesafe.config.ConfigException;
  14. import io.github.nucleuspowered.nucleus.api.NucleusAPITokens;
  15. import io.github.nucleuspowered.nucleus.api.service.NucleusMessageTokenService;
  16. import io.github.nucleuspowered.nucleus.api.service.NucleusModuleService;
  17. import io.github.nucleuspowered.nucleus.api.service.NucleusWarmupManagerService;
  18. import io.github.nucleuspowered.nucleus.config.CommandsConfig;
  19. import io.github.nucleuspowered.nucleus.configurate.ConfigurateHelper;
  20. import io.github.nucleuspowered.nucleus.dataservices.ItemDataService;
  21. import io.github.nucleuspowered.nucleus.dataservices.KitService;
  22. import io.github.nucleuspowered.nucleus.dataservices.NameBanService;
  23. import io.github.nucleuspowered.nucleus.dataservices.UserCacheService;
  24. import io.github.nucleuspowered.nucleus.dataservices.dataproviders.DataProviders;
  25. import io.github.nucleuspowered.nucleus.dataservices.loaders.UserDataManager;
  26. import io.github.nucleuspowered.nucleus.dataservices.loaders.WorldDataManager;
  27. import io.github.nucleuspowered.nucleus.dataservices.modular.ModularGeneralService;
  28. import io.github.nucleuspowered.nucleus.internal.CatalogTypeFinalStaticProcessor;
  29. import io.github.nucleuspowered.nucleus.internal.CommandPermissionHandler;
  30. import io.github.nucleuspowered.nucleus.internal.EconHelper;
  31. import io.github.nucleuspowered.nucleus.internal.InternalServiceManager;
  32. import io.github.nucleuspowered.nucleus.internal.PermissionRegistry;
  33. import io.github.nucleuspowered.nucleus.internal.PreloadTasks;
  34. import io.github.nucleuspowered.nucleus.internal.TextFileController;
  35. import io.github.nucleuspowered.nucleus.internal.WorldCorrector;
  36. import io.github.nucleuspowered.nucleus.internal.client.ClientMessageReciever;
  37. import io.github.nucleuspowered.nucleus.internal.docgen.DocGenCache;
  38. import io.github.nucleuspowered.nucleus.internal.interfaces.Reloadable;
  39. import io.github.nucleuspowered.nucleus.internal.messages.ConfigMessageProvider;
  40. import io.github.nucleuspowered.nucleus.internal.messages.MessageProvider;
  41. import io.github.nucleuspowered.nucleus.internal.messages.ResourceMessageProvider;
  42. import io.github.nucleuspowered.nucleus.internal.permissions.PermissionInformation;
  43. import io.github.nucleuspowered.nucleus.internal.permissions.SuggestedLevel;
  44. import io.github.nucleuspowered.nucleus.internal.qsml.ModuleRegistrationProxyService;
  45. import io.github.nucleuspowered.nucleus.internal.qsml.NucleusConfigAdapter;
  46. import io.github.nucleuspowered.nucleus.internal.qsml.NucleusLoggerProxy;
  47. import io.github.nucleuspowered.nucleus.internal.qsml.QuickStartModuleConstructor;
  48. import io.github.nucleuspowered.nucleus.internal.qsml.event.BaseModuleEvent;
  49. import io.github.nucleuspowered.nucleus.internal.services.WarmupManager;
  50. import io.github.nucleuspowered.nucleus.internal.teleport.NucleusTeleportHandler;
  51. import io.github.nucleuspowered.nucleus.internal.text.NucleusTokenServiceImpl;
  52. import io.github.nucleuspowered.nucleus.internal.text.TextParsingUtils;
  53. import io.github.nucleuspowered.nucleus.logging.DebugLogger;
  54. import io.github.nucleuspowered.nucleus.modules.core.CoreModule;
  55. import io.github.nucleuspowered.nucleus.modules.core.config.CoreConfig;
  56. import io.github.nucleuspowered.nucleus.modules.core.config.CoreConfigAdapter;
  57. import io.github.nucleuspowered.nucleus.modules.core.config.WarmupConfig;
  58. import io.github.nucleuspowered.nucleus.modules.core.datamodules.UniqueUserCountTransientModule;
  59. import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
  60. import ninja.leaping.configurate.objectmapping.ObjectMappingException;
  61. import org.slf4j.Logger;
  62. import org.spongepowered.api.Game;
  63. import org.spongepowered.api.GameState;
  64. import org.spongepowered.api.Platform;
  65. import org.spongepowered.api.Sponge;
  66. import org.spongepowered.api.asset.Asset;
  67. import org.spongepowered.api.command.source.ConsoleSource;
  68. import org.spongepowered.api.config.ConfigDir;
  69. import org.spongepowered.api.event.Listener;
  70. import org.spongepowered.api.event.Order;
  71. import org.spongepowered.api.event.game.state.GameInitializationEvent;
  72. import org.spongepowered.api.event.game.state.GamePostInitializationEvent;
  73. import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
  74. import org.spongepowered.api.event.game.state.GameStartedServerEvent;
  75. import org.spongepowered.api.event.game.state.GameStartingServerEvent;
  76. import org.spongepowered.api.event.game.state.GameStoppedServerEvent;
  77. import org.spongepowered.api.plugin.Plugin;
  78. import org.spongepowered.api.plugin.PluginContainer;
  79. import org.spongepowered.api.scheduler.Task;
  80. import org.spongepowered.api.service.economy.EconomyService;
  81. import org.spongepowered.api.service.permission.PermissionDescription;
  82. import org.spongepowered.api.service.permission.PermissionService;
  83. import org.spongepowered.api.text.Text;
  84. import org.spongepowered.api.text.channel.MessageReceiver;
  85. import org.spongepowered.api.text.format.TextColors;
  86. import uk.co.drnaylor.quickstart.annotations.ModuleData;
  87. import uk.co.drnaylor.quickstart.enums.ConstructionPhase;
  88. import uk.co.drnaylor.quickstart.exceptions.IncorrectAdapterTypeException;
  89. import uk.co.drnaylor.quickstart.exceptions.NoModuleException;
  90. import uk.co.drnaylor.quickstart.exceptions.QuickStartModuleDiscoveryException;
  91. import uk.co.drnaylor.quickstart.exceptions.QuickStartModuleLoaderException;
  92. import uk.co.drnaylor.quickstart.modulecontainers.DiscoveryModuleContainer;
  93.  
  94. import java.io.IOException;
  95. import java.io.PrintWriter;
  96. import java.io.StringWriter;
  97. import java.nio.file.Files;
  98. import java.nio.file.Path;
  99. import java.nio.file.Paths;
  100. import java.time.Instant;
  101. import java.util.Collections;
  102. import java.util.List;
  103. import java.util.Map;
  104. import java.util.Optional;
  105. import java.util.Set;
  106. import java.util.function.Supplier;
  107.  
  108. import javax.annotation.Nullable;
  109. import javax.inject.Inject;
  110.  
  111. @Plugin(id = ID, name = NAME, version = VERSION, description = DESCRIPTION)
  112. public class NucleusPlugin extends Nucleus {
  113.  
  114. private static final String divider = "+------------------------------------------------------------+";
  115. private static final int length = divider.length() - 2;
  116.  
  117. private final PluginContainer pluginContainer;
  118. private Instant gameStartedTime = null;
  119. private boolean hasStarted = false;
  120. private Throwable isErrored = null;
  121. private CommandsConfig commandsConfig;
  122. private ModularGeneralService generalService;
  123. private ItemDataService itemDataService;
  124. private UserCacheService userCacheService;
  125. private UserDataManager userDataManager;
  126. private WorldDataManager worldDataManager;
  127. private NameBanService nameBanService;
  128. private KitService kitService;
  129. private TextParsingUtils textParsingUtils;
  130. private NameUtil nameUtil;
  131. private final List<Reloadable> reloadableList = Lists.newArrayList();
  132. private DocGenCache docGenCache = null;
  133. private final NucleusTeleportHandler teleportHandler = new NucleusTeleportHandler();
  134. private NucleusTokenServiceImpl nucleusChatService;
  135.  
  136. private final List<Text> startupMessages = Lists.newArrayList();
  137.  
  138. private final InternalServiceManager serviceManager = new InternalServiceManager(this);
  139. private MessageProvider messageProvider = new ResourceMessageProvider(ResourceMessageProvider.messagesBundle);
  140. private MessageProvider commandMessageProvider = new ResourceMessageProvider(ResourceMessageProvider.commandMessagesBundle);
  141.  
  142. private WarmupManager warmupManager;
  143. private final EconHelper econHelper = new EconHelper(this);
  144. private final PermissionRegistry permissionRegistry = new PermissionRegistry();
  145.  
  146. private DiscoveryModuleContainer moduleContainer;
  147.  
  148. private final Map<String, TextFileController> textFileControllers = Maps.newHashMap();
  149.  
  150. private final Logger logger;
  151. private final Path configDir;
  152. private final Supplier<Path> dataDir;
  153. private boolean isServer = false;
  154. private WarmupConfig warmupConfig;
  155. private final String versionFail;
  156.  
  157. private boolean isDebugMode = false;
  158. private boolean sessionDebugMode = false;
  159. private int isTraceUserCreations = 0;
  160. private boolean savesandloads = false;
  161.  
  162. @Nullable
  163. private static String versionCheck() {
  164. // So we can ensure we have the Cause Stack Manager.
  165. try {
  166. // Check the org.spongepowered.api.item.enchantment.EnchantmentType exists.
  167. Class.forName("org.spongepowered.api.item.enchantment.EnchantmentType");
  168. } catch (Throwable e) {
  169. return "EnchantmentType does not exist. Nucleus requires the EnchantmentType from API 7 to function. Update Nucleus to the latest "
  170. + "version.";
  171. }
  172.  
  173. return null;
  174. }
  175.  
  176. // We inject this into the constructor so we can build the config path ourselves.
  177. @Inject
  178. public NucleusPlugin(@ConfigDir(sharedRoot = true) Path configDir, Logger logger, PluginContainer container) {
  179. Nucleus.setNucleus(this);
  180. this.versionFail = versionCheck();
  181. this.logger = new DebugLogger(this, logger);
  182. this.configDir = configDir.resolve(PluginInfo.ID);
  183. Supplier<Path> sp;
  184. try {
  185. Path path = Sponge.getGame().getSavesDirectory().resolve("nucleus");
  186. sp = () -> path;
  187. this.isServer = true;
  188. } catch (NullPointerException e) {
  189. sp = () -> Sponge.getGame().getSavesDirectory().resolve("nucleus");
  190. }
  191.  
  192. this.dataDir = sp;
  193. this.pluginContainer = container;
  194. }
  195.  
  196. @Listener
  197. public void onPreInit(GamePreInitializationEvent preInitializationEvent) {
  198. // Setup object mapper.
  199. MessageReceiver s;
  200. if (Sponge.getGame().isServerAvailable()) {
  201. s = Sponge.getServer().getConsole();
  202. } else {
  203. s = new ClientMessageReciever();
  204. }
  205.  
  206. if (this.versionFail != null) {
  207. s.sendMessage(messageProvider.getTextMessageWithFormat("startup.nostart.compat", PluginInfo.NAME,
  208. Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getName(),
  209. Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getVersion().orElse("unknown")));
  210. s.sendMessage(messageProvider.getTextMessageWithFormat("startup.nostart.compat2", this.versionFail));
  211. s.sendMessage(messageProvider.getTextMessageWithFormat("startup.nostart.compat3", this.versionFail));
  212. disable();
  213. return;
  214. }
  215.  
  216. s.sendMessage(Text.of(TextColors.WHITE, "--------------------------"));
  217. s.sendMessage(messageProvider.getTextMessageWithFormat("startup.welcome", PluginInfo.NAME,
  218. PluginInfo.VERSION, Sponge.getPlatform().getContainer(Platform.Component.API).getVersion().orElse("unknown")));
  219. s.sendMessage(messageProvider.getTextMessageWithFormat("startup.welcome2"));
  220. s.sendMessage(messageProvider.getTextMessageWithFormat("startup.welcome3"));
  221. s.sendMessage(messageProvider.getTextMessageWithFormat("startup.welcome4"));
  222. s.sendMessage(Text.of(TextColors.WHITE, "--------------------------"));
  223.  
  224. logger.info(messageProvider.getMessageWithFormat("startup.preinit", PluginInfo.NAME));
  225. Game game = Sponge.getGame();
  226. NucleusAPITokens.onPreInit(this);
  227.  
  228. // Startup tasks, for the migrations I need to do.
  229. PreloadTasks.getPreloadTasks().forEach(x -> x.accept(this));
  230.  
  231. // Get the mandatory config files.
  232. try {
  233. Files.createDirectories(this.configDir);
  234. if (this.isServer) {
  235. Files.createDirectories(this.dataDir.get());
  236. }
  237. this.commandsConfig = new CommandsConfig(Paths.get(configDir.toString(), "commands.conf"));
  238.  
  239. DataProviders d = new DataProviders(this);
  240. this.generalService = new ModularGeneralService(d.getGeneralDataProvider());
  241. this.itemDataService = new ItemDataService(d.getItemDataProvider());
  242. this.itemDataService.loadInternal();
  243. this.userDataManager = new UserDataManager(this, d::getUserFileDataProviders, d::doesUserFileExist);
  244. this.worldDataManager = new WorldDataManager(this, d::getWorldFileDataProvider, d::doesWorldFileExist);
  245. this.kitService = new KitService(d.getKitsDataProvider());
  246. this.nameBanService = new NameBanService(d.getNameBanDataProvider());
  247. this.userCacheService = new UserCacheService(d.getUserCacheDataProvider());
  248. this.warmupManager = new WarmupManager();
  249. this.textParsingUtils = new TextParsingUtils(this);
  250. this.nameUtil = new NameUtil(this);
  251.  
  252. if (this.isServer) {
  253. allChange();
  254. }
  255. } catch (Exception e) {
  256. this.isErrored = e;
  257. disable();
  258. e.printStackTrace();
  259. return;
  260. }
  261.  
  262. PreloadTasks.getPreloadTasks2().forEach(x -> x.accept(this));
  263.  
  264. // We register the ModuleService NOW so that others can hook into it.
  265. game.getServiceManager().setProvider(this, NucleusModuleService.class, new ModuleRegistrationProxyService(this));
  266. game.getServiceManager().setProvider(this, NucleusWarmupManagerService.class, warmupManager);
  267. serviceManager.registerService(WarmupManager.class, warmupManager);
  268.  
  269. nucleusChatService = new NucleusTokenServiceImpl(this);
  270. serviceManager.registerService(NucleusTokenServiceImpl.class, nucleusChatService);
  271. Sponge.getServiceManager().setProvider(this, NucleusMessageTokenService.class, nucleusChatService);
  272.  
  273. try {
  274. final String he = this.messageProvider.getMessageWithFormat("config.main-header", PluginInfo.VERSION);
  275. HoconConfigurationLoader.Builder builder = HoconConfigurationLoader.builder();
  276. Optional<Asset> optionalAsset = Sponge.getAssetManager().getAsset(Nucleus.getNucleus(), "classes.json");
  277. DiscoveryModuleContainer.Builder db = DiscoveryModuleContainer.builder();
  278. if (optionalAsset.isPresent()) {
  279. Map<String, Map<String, List<String>>> m = new Gson().fromJson(
  280. optionalAsset.get().readString(),
  281. new TypeToken<Map<String, Map<String, List<String>>>>() {}.getType()
  282. );
  283.  
  284. Set<Class<?>> sc = Sets.newHashSet();
  285. for (String classString : m.keySet()) {
  286. sc.add(Class.forName(classString));
  287. }
  288.  
  289. db.setDiscoveryStrategy((string, classloader) -> sc)
  290. .setConstructor(new QuickStartModuleConstructor(m));
  291. } else {
  292. db.setConstructor(new QuickStartModuleConstructor(null));
  293. }
  294. this.moduleContainer = db
  295. .setConfigurationLoader(
  296. builder.setDefaultOptions(
  297. ConfigurateHelper.setOptions(builder.getDefaultOptions()).setHeader(he))
  298. .setPath(Paths.get(configDir.toString(), "main.conf"))
  299. .build())
  300. .setPackageToScan(getClass().getPackage().getName() + ".modules")
  301. .setLoggerProxy(new NucleusLoggerProxy(logger))
  302. .setConfigurationOptionsTransformer(x -> ConfigurateHelper.setOptions(x).setHeader(he))
  303. .setOnPreEnable(() -> {
  304. initDocGenIfApplicable();
  305. Sponge.getEventManager().post(new BaseModuleEvent.AboutToEnable(this));
  306. })
  307. .setOnEnable(() -> {
  308. Sponge.getEventManager().post(new BaseModuleEvent.PreEnable(this));
  309. })
  310. .setOnPostEnable(() -> Sponge.getEventManager().post(new BaseModuleEvent.Enabled(this)))
  311. .setRequireModuleDataAnnotation(true)
  312. .setNoMergeIfPresent(true)
  313. .setModuleConfigurationHeader(m -> {
  314. StringBuilder ssb = new StringBuilder().append(divider).append("\n");
  315. String name = m.getClass().getAnnotation(ModuleData.class).name();
  316. int nameLength = name.length() + 2;
  317. int dashes = (length - nameLength) / 2;
  318. ssb.append("|");
  319. for (int i = 0; i < dashes; i++) {
  320. ssb.append(" ");
  321. }
  322.  
  323. ssb.append(" ").append(name).append(" ");
  324. for (int i = 0; i < dashes; i++) {
  325. ssb.append(" ");
  326. }
  327.  
  328. if (length > dashes * 2 + nameLength) {
  329. ssb.append(" ");
  330. }
  331.  
  332. return ssb.append("|").append("\n").append(divider).toString();
  333. })
  334. .setModuleConfigSectionName("-modules")
  335. .setModuleConfigSectionDescription(this.messageProvider.getMessageWithFormat("config.module-desc"))
  336. .setModuleDescriptionHandler(m -> this.messageProvider.getMessageWithFormat("config.module." +
  337. m.getAnnotation(ModuleData.class).id().toLowerCase() + ".desc"))
  338. .build();
  339.  
  340. moduleContainer.startDiscover();
  341. } catch (Exception e) {
  342. isErrored = e;
  343. disable();
  344. e.printStackTrace();
  345. }
  346. }
  347.  
  348. @Listener(order = Order.FIRST)
  349. public void onInit(GameInitializationEvent event) {
  350. if (isErrored != null) {
  351. return;
  352. }
  353.  
  354. logger.info(messageProvider.getMessageWithFormat("startup.init", PluginInfo.NAME));
  355.  
  356. try {
  357. CatalogTypeFinalStaticProcessor.setEventContexts();
  358. } catch (Exception e) {
  359. isErrored = e;
  360. disable();
  361. e.printStackTrace();
  362. }
  363. }
  364.  
  365. @Listener(order = Order.FIRST)
  366. public void onPostInit(GamePostInitializationEvent event) {
  367. if (isErrored != null) {
  368. return;
  369. }
  370.  
  371. logger.info(messageProvider.getMessageWithFormat("startup.postinit", PluginInfo.NAME));
  372.  
  373. // Load up the general data files now, mods should have registered items by now.
  374. try {
  375. // Reloadable so that we can update the serialisers.
  376. moduleContainer.reloadSystemConfig();
  377. } catch (Exception e) {
  378. isErrored = e;
  379. disable();
  380. e.printStackTrace();
  381. return;
  382. }
  383.  
  384.  
  385. try {
  386. Sponge.getEventManager().post(new BaseModuleEvent.AboutToConstructEvent(this));
  387. logger.info(messageProvider.getMessageWithFormat("startup.moduleloading", PluginInfo.NAME));
  388. moduleContainer.loadModules(true);
  389.  
  390. CoreConfig coreConfig = moduleContainer.getConfigAdapterForModule(CoreModule.ID, CoreConfigAdapter.class).getNodeOrDefault();
  391.  
  392. if (coreConfig.isErrorOnStartup()) {
  393. throw new IllegalStateException("In main.conf, core.simulate-error-on-startup is set to TRUE. Remove this config entry to allow Nucleus to start. Simulating error and disabling Nucleus.");
  394. }
  395.  
  396. this.isDebugMode = coreConfig.isDebugmode();
  397. this.isTraceUserCreations = coreConfig.traceUserCreations();
  398. this.savesandloads = coreConfig.isPrintSaveLoad();
  399. } catch (Throwable construction) {
  400. logger.info(messageProvider.getMessageWithFormat("startup.modulenotloaded", PluginInfo.NAME));
  401. construction.printStackTrace();
  402. disable();
  403. isErrored = construction;
  404. return;
  405. }
  406.  
  407. // Register a reloadable.
  408. CommandPermissionHandler.onReload();
  409. registerReloadable(CommandPermissionHandler::onReload);
  410. getDocGenCache().ifPresent(x -> x.addTokenDocs(nucleusChatService.getNucleusTokenParser().getTokenNames()));
  411.  
  412. logger.info(messageProvider.getMessageWithFormat("startup.moduleloaded", PluginInfo.NAME));
  413. registerPermissions();
  414. Sponge.getEventManager().post(new BaseModuleEvent.Complete(this));
  415.  
  416. logger.info(messageProvider.getMessageWithFormat("startup.completeinit", PluginInfo.NAME));
  417. }
  418.  
  419. @Listener(order = Order.EARLY)
  420. public void onGameStartingEarly(GameStartingServerEvent event) {
  421. if (!this.isServer) {
  422. try {
  423. Files.createDirectories(this.dataDir.get());
  424. allChange();
  425. } catch (IOException e) {
  426. isErrored = e;
  427. disable();
  428. e.printStackTrace();
  429. }
  430. }
  431. }
  432.  
  433. private void allChange() {
  434. this.generalService.changeFile();
  435. this.kitService.changeFile();
  436. this.nameBanService.changeFile();
  437. this.userCacheService.changeFile();
  438.  
  439. this.userCacheService.load();
  440. this.nameBanService.load();
  441. }
  442.  
  443. @Listener
  444. public void onGameStarting(GameStartingServerEvent event) {
  445. if (isErrored == null) {
  446. logger.info(messageProvider.getMessageWithFormat("startup.gamestart", PluginInfo.NAME));
  447. try {
  448. if (this.getConfigValue(CoreModule.ID, CoreConfigAdapter.class, CoreConfig::isTrackWorldUUIDs).orElse(true)) {
  449. WorldCorrector.worldCheck();
  450. } else {
  451. WorldCorrector.delete();
  452. }
  453. } catch (IOException | ObjectMappingException e) {
  454. e.printStackTrace();
  455. }
  456.  
  457. // Load up the general data files now, mods should have registered items by now.
  458. try {
  459. this.generalService.loadInternal();
  460. this.kitService.loadInternal();
  461. } catch (Exception e) {
  462. isErrored = e;
  463. disable();
  464. e.printStackTrace();
  465. return;
  466. }
  467.  
  468. generalService.getTransient(UniqueUserCountTransientModule.class).resetUniqueUserCount();
  469.  
  470. // Start the user cache walk if required, the user storage service is loaded at this point.
  471. Task.builder().async().execute(() -> userCacheService.startFilewalkIfNeeded()).submit(this);
  472. logger.info(messageProvider.getMessageWithFormat("startup.started", PluginInfo.NAME));
  473. }
  474. }
  475.  
  476. @Listener
  477. public void onGameStarted(GameStartedServerEvent event) {
  478. if (isErrored == null) {
  479. try {
  480. // Save any additions.
  481. moduleContainer.refreshSystemConfig();
  482. fireReloadables();
  483. } catch (Throwable e) {
  484. isErrored = e;
  485. disable();
  486. errorOnStartup();
  487. return;
  488. }
  489.  
  490. this.hasStarted = true;
  491. Sponge.getScheduler().createSyncExecutor(this).submit(() -> this.gameStartedTime = Instant.now());
  492.  
  493. // What about perms and econ?
  494. List<Text> lt = Lists.newArrayList();
  495. boolean simplePerms = Sponge.getServiceManager().getRegistration(PermissionService.class)
  496. .map(x -> Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION).equals(x.getPlugin())).orElse(true);
  497. if (simplePerms) {
  498. addTri(lt, 0);
  499. lt.add(messageProvider.getTextMessageWithFormat("standard.line"));
  500. lt.add(messageProvider.getTextMessageWithFormat("standard.nopermplugin"));
  501. lt.add(messageProvider.getTextMessageWithFormat("standard.nopermplugin2"));
  502. }
  503.  
  504. if (!Sponge.getServiceManager().isRegistered(EconomyService.class)) {
  505. if (lt.isEmpty()) {
  506. addTri(lt, 0);
  507. }
  508.  
  509. lt.add(messageProvider.getTextMessageWithFormat("standard.line"));
  510. lt.add(messageProvider.getTextMessageWithFormat("standard.noeconplugin"));
  511. lt.add(messageProvider.getTextMessageWithFormat("standard.noeconplugin2"));
  512. }
  513.  
  514. if (!lt.isEmpty()) {
  515. lt.add(messageProvider.getTextMessageWithFormat("standard.line"));
  516. lt.add(messageProvider.getTextMessageWithFormat("standard.seesuggested"));
  517. }
  518.  
  519. if (!this.startupMessages.isEmpty()) {
  520. if (lt.isEmpty()) {
  521. addTri(lt, 0);
  522. }
  523.  
  524. lt.add(messageProvider.getTextMessageWithFormat("standard.line"));
  525. lt.addAll(this.startupMessages);
  526. this.startupMessages.clear();
  527. }
  528.  
  529. if (!lt.isEmpty()) {
  530. lt.add(messageProvider.getTextMessageWithFormat("standard.line"));
  531. ConsoleSource c = Sponge.getServer().getConsole();
  532. lt.forEach(c::sendMessage);
  533. }
  534. }
  535. }
  536.  
  537. @Listener
  538. public void onServerStop(GameStoppedServerEvent event) {
  539. if (this.hasStarted && this.isErrored == null) {
  540. this.gameStartedTime = null;
  541. logger.info(messageProvider.getMessageWithFormat("startup.stopped", PluginInfo.NAME));
  542. saveData();
  543. }
  544. }
  545.  
  546. @Override
  547. public void saveData() {
  548. userDataManager.saveAll();
  549. worldDataManager.saveAll();
  550.  
  551. if (Sponge.getGame().getState().ordinal() > GameState.SERVER_ABOUT_TO_START.ordinal()) {
  552. try {
  553. generalService.save();
  554. nameBanService.save();
  555. userCacheService.save();
  556. } catch (Exception e) {
  557. e.printStackTrace();
  558. }
  559. }
  560. }
  561.  
  562. @Override
  563. public Logger getLogger() {
  564. return logger;
  565. }
  566.  
  567. @Override
  568. public Path getConfigDirPath() {
  569. return configDir;
  570. }
  571.  
  572. @Override
  573. public Path getDataPath() {
  574. return this.dataDir.get();
  575. }
  576.  
  577. @Override
  578. public Supplier<Path> getDataPathSupplier() {
  579. return this.dataDir;
  580. }
  581.  
  582. @Override
  583. public UserDataManager getUserDataManager() {
  584. return userDataManager;
  585. }
  586.  
  587. @Override
  588. public WorldDataManager getWorldDataManager() {
  589. return worldDataManager;
  590. }
  591.  
  592. @Override public UserCacheService getUserCacheService() {
  593. return userCacheService;
  594. }
  595.  
  596. @Override
  597. public void saveSystemConfig() throws IOException {
  598. moduleContainer.saveSystemConfig();
  599. }
  600.  
  601. @Override
  602. public synchronized boolean reload() {
  603. try {
  604. this.moduleContainer.reloadSystemConfig();
  605. reloadMessages();
  606. this.commandsConfig.load();
  607. this.itemDataService.load();
  608. this.warmupConfig = null;
  609.  
  610. CoreConfig coreConfig = this.getInternalServiceManager().getService(CoreConfigAdapter.class).get().getNodeOrDefault();
  611. this.isDebugMode = coreConfig.isDebugmode();
  612. this.isTraceUserCreations = coreConfig.traceUserCreations();
  613. this.savesandloads = coreConfig.isPrintSaveLoad();
  614.  
  615. for (TextFileController tfc : textFileControllers.values()) {
  616. tfc.load();
  617. }
  618.  
  619. fireReloadables();
  620. return true;
  621. } catch (Exception e) {
  622. e.printStackTrace();
  623. return false;
  624. }
  625. }
  626.  
  627. private void fireReloadables() throws Exception {
  628. for (Reloadable r : this.reloadableList) {
  629. r.onReload();
  630. }
  631. }
  632.  
  633. @Override public boolean reloadMessages() {
  634. boolean r = true;
  635. if (getConfigValue("core", CoreConfigAdapter.class, CoreConfig::isCustommessages).orElse(false)) {
  636. try {
  637. this.messageProvider = new ConfigMessageProvider(configDir.resolve("messages.conf"), ResourceMessageProvider.messagesBundle);
  638. this.commandMessageProvider = new ConfigMessageProvider(configDir.resolve("command-help-messages.conf"), ResourceMessageProvider.commandMessagesBundle);
  639. return true;
  640. } catch (Throwable exception) {
  641. r = false;
  642. // On error, fallback.
  643. // Blegh, relocations
  644. if (exception instanceof IOException && exception.getCause().getClass().getName().contains(ConfigException.class.getSimpleName())) {
  645. MessageReceiver s;
  646. if (Sponge.getGame().isServerAvailable()) {
  647. s = Sponge.getServer().getConsole();
  648. } else {
  649. s = new ClientMessageReciever();
  650. }
  651.  
  652. exception = exception.getCause();
  653. s.sendMessage(Text.of(TextColors.RED, "It appears that there is an error in your messages file! The error is: "));
  654. s.sendMessage(Text.of(TextColors.RED, exception.getMessage()));
  655. s.sendMessage(Text.of(TextColors.RED, "Please correct this - then run ", TextColors.YELLOW, "/nucleus reload"));
  656. s.sendMessage(Text.of(TextColors.RED, "Ignoring messages.conf for now."));
  657. if (this.isDebugMode) {
  658. exception.printStackTrace();
  659. }
  660. } else {
  661. this.logger.warn("Could not load custom messages file. Falling back.");
  662. exception.printStackTrace();
  663. }
  664. }
  665. }
  666.  
  667. this.messageProvider = new ResourceMessageProvider(ResourceMessageProvider.messagesBundle);
  668. this.commandMessageProvider = new ResourceMessageProvider(ResourceMessageProvider.commandMessagesBundle);
  669. return r;
  670. }
  671.  
  672. @Override
  673. public WarmupManager getWarmupManager() {
  674. return warmupManager;
  675. }
  676.  
  677. @Override public WarmupConfig getWarmupConfig() {
  678. if (this.warmupConfig == null) {
  679. this.warmupConfig = getConfigValue(CoreModule.ID, CoreConfigAdapter.class, CoreConfig::getWarmupConfig).orElseGet(WarmupConfig::new);
  680. }
  681.  
  682. return this.warmupConfig;
  683. }
  684.  
  685. @Override
  686. public EconHelper getEconHelper() {
  687. return econHelper;
  688. }
  689.  
  690. @Override
  691. public PermissionRegistry getPermissionRegistry() {
  692. return permissionRegistry;
  693. }
  694.  
  695. @Override
  696. public DiscoveryModuleContainer getModuleContainer() {
  697. return moduleContainer;
  698. }
  699.  
  700. @Override public boolean isModuleLoaded(String moduleId) {
  701. try {
  702. return getModuleContainer().isModuleLoaded(moduleId);
  703. } catch (NoModuleException e) {
  704. return false;
  705. }
  706. }
  707.  
  708. @Override
  709. public <R extends NucleusConfigAdapter<?>> Optional<R> getConfigAdapter(String id, Class<R> configAdapterClass) {
  710. try {
  711. return Optional.of(getModuleContainer().getConfigAdapterForModule(id, configAdapterClass));
  712. } catch (NoModuleException | IncorrectAdapterTypeException e) {
  713. return Optional.empty();
  714. }
  715. }
  716.  
  717. @Override
  718. public InternalServiceManager getInternalServiceManager() {
  719. return serviceManager;
  720. }
  721.  
  722. @Override public Optional<Instant> getGameStartedTime() {
  723. return Optional.ofNullable(this.gameStartedTime);
  724. }
  725.  
  726. @Override
  727. public ModularGeneralService getGeneralService() {
  728. return generalService;
  729. }
  730.  
  731. @Override
  732. public ItemDataService getItemDataService() {
  733. return itemDataService;
  734. }
  735.  
  736. @Override public KitService getKitService() {
  737. return kitService;
  738. }
  739.  
  740. @Override public NameBanService getNameBanService() { return nameBanService; }
  741.  
  742. @Override
  743. public CommandsConfig getCommandsConfig() {
  744. return commandsConfig;
  745. }
  746.  
  747. @Override
  748. public NameUtil getNameUtil() {
  749. return nameUtil;
  750. }
  751.  
  752. public TextParsingUtils getTextParsingUtils() {
  753. return textParsingUtils;
  754. }
  755.  
  756. @Override
  757. public MessageProvider getMessageProvider() {
  758. return messageProvider;
  759. }
  760.  
  761. @Override
  762. public MessageProvider getCommandMessageProvider() {
  763. return commandMessageProvider;
  764. }
  765.  
  766. @Override
  767. public NucleusTeleportHandler getTeleportHandler() {
  768. return teleportHandler;
  769. }
  770.  
  771. @Override public NucleusMessageTokenService getMessageTokenService() {
  772. return nucleusChatService;
  773. }
  774.  
  775. @Override public boolean isDebugMode() {
  776. return this.isDebugMode || this.sessionDebugMode;
  777. }
  778.  
  779. @Override public void printStackTraceIfDebugMode(Throwable throwable) {
  780. if (isDebugMode()) {
  781. throwable.printStackTrace();
  782. }
  783. }
  784.  
  785. @Override public int traceUserCreations() {
  786. return this.isTraceUserCreations;
  787. }
  788.  
  789. /**
  790. * Gets the {@link TextFileController}
  791. *
  792. * @param getController The ID of the {@link TextFileController}.
  793. * @return An {@link Optional} that might contain a {@link TextFileController}.
  794. */
  795. @Override public Optional<TextFileController> getTextFileController(String getController) {
  796. return Optional.ofNullable(textFileControllers.get(getController));
  797. }
  798.  
  799. @Override public void addTextFileController(String id, Asset asset, Path file) throws IOException {
  800. if (!textFileControllers.containsKey(id)) {
  801. textFileControllers.put(id, new TextFileController(asset, file));
  802. }
  803. }
  804.  
  805. @Override public void registerReloadable(Reloadable reloadable) {
  806. reloadableList.add(reloadable);
  807. }
  808.  
  809. @Override public Optional<DocGenCache> getDocGenCache() {
  810. return Optional.ofNullable(docGenCache);
  811. }
  812.  
  813. @Override public PluginContainer getPluginContainer() {
  814. return pluginContainer;
  815. }
  816.  
  817. @Override public boolean isSessionDebug() {
  818. return this.sessionDebugMode;
  819. }
  820.  
  821. @Override public void setSessionDebug(boolean debug) {
  822. this.sessionDebugMode = debug;
  823. }
  824.  
  825. private void initDocGenIfApplicable() {
  826. if (moduleContainer.getCurrentPhase() == ConstructionPhase.ENABLING) {
  827. // If enable-doc-gen is enabled, we init the DocGen system here.
  828. try {
  829. if (moduleContainer.getConfigAdapterForModule("core", CoreConfigAdapter.class).getNodeOrDefault().isEnableDocGen()) {
  830. docGenCache = new DocGenCache(logger);
  831. }
  832. } catch (NoModuleException | IncorrectAdapterTypeException e) {
  833. e.printStackTrace();
  834. }
  835. }
  836. }
  837.  
  838. @Override protected void registerPermissions() {
  839. Optional<PermissionService> ops = Sponge.getServiceManager().provide(PermissionService.class);
  840. ops.ifPresent(permissionService -> {
  841. Map<String, PermissionInformation> m = this.getPermissionRegistry().getPermissions();
  842. m.entrySet().stream().filter(x -> x.getValue().level == SuggestedLevel.ADMIN)
  843. .filter(x -> x.getValue().isNormal)
  844. .forEach(k -> permissionService.newDescriptionBuilder(this).assign(PermissionDescription.ROLE_ADMIN, true)
  845. .description(k.getValue().description).id(k.getKey()).register());
  846. m.entrySet().stream().filter(x -> x.getValue().level == SuggestedLevel.MOD)
  847. .filter(x -> x.getValue().isNormal)
  848. .forEach(k -> permissionService.newDescriptionBuilder(this).assign(PermissionDescription.ROLE_STAFF, true)
  849. .description(k.getValue().description).id(k.getKey()).register());
  850. m.entrySet().stream().filter(x -> x.getValue().level == SuggestedLevel.USER)
  851. .filter(x -> x.getValue().isNormal)
  852. .forEach(k -> permissionService.newDescriptionBuilder(this).assign(PermissionDescription.ROLE_USER, true)
  853. .description(k.getValue().description).id(k.getKey()).register());
  854. });
  855. }
  856.  
  857. @Override
  858. public boolean isServer() {
  859. return this.isServer;
  860. }
  861.  
  862. @Override public void addStartupMessage(Text message) {
  863. this.startupMessages.add(message);
  864. }
  865.  
  866. @Override public boolean isPrintingSavesAndLoads() {
  867. return this.savesandloads;
  868. }
  869.  
  870. private void disable() {
  871. // Disable everything, just in case. Thanks to pie-flavor: https://forums.spongepowered.org/t/disable-plugin-disable-itself/15831/8
  872. Sponge.getEventManager().unregisterPluginListeners(this);
  873. Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping);
  874. Sponge.getScheduler().getScheduledTasks(this).forEach(Task::cancel);
  875.  
  876. // Re-register this to warn people about the error.
  877. Sponge.getEventManager().registerListener(this, GameStartedServerEvent.class, e -> errorOnStartup());
  878. }
  879.  
  880. private void errorOnStartup() {
  881. Sponge.getServer().setHasWhitelist(true);
  882. if (this.versionFail != null) {
  883. Sponge.getServer().getConsole().sendMessages(getIncorrectVersion());
  884. } else {
  885. Sponge.getServer().getConsole().sendMessages(getErrorMessage());
  886. }
  887. }
  888.  
  889. private List<Text> getIncorrectVersion() {
  890. List<Text> messages = Lists.newArrayList();
  891. messages.add(Text.of(TextColors.RED, "------------------------------"));
  892. messages.add(Text.of(TextColors.RED, "- NUCLEUS FAILED TO LOAD -"));
  893. messages.add(Text.of(TextColors.RED, "------------------------------"));
  894. addX(messages, 7);
  895. messages.add(Text.of(TextColors.RED, "------------------------------"));
  896. messages.add(Text.of(TextColors.RED, "- INCORRECT SPONGE VERSION -"));
  897. messages.add(Text.of(TextColors.RED, "------------------------------"));
  898. messages.add(Text.EMPTY);
  899. messages.add(Text.of(TextColors.RED, "You are running an old version of Sponge on your server - new versions of Nucleus (like this one!) "
  900. + "will not run."));
  901. messages.add(Text.of(TextColors.RED, "Nucleus has not started. Update Sponge to the latest version and try again."));
  902. messages.add(Text.of(TextColors.RED, "The server has been automatically whitelisted - this is to protect your server and players if you rely on some of Nucleus' functionality (such as fly states, etc.)"));
  903. messages.add(Text.of(TextColors.RED, "------------------------------"));
  904. messages.add(Text.of(TextColors.YELLOW, "Reason: "));
  905. messages.add(Text.of(TextColors.YELLOW, this.versionFail));
  906. messages.add(Text.of(TextColors.RED, "------------------------------"));
  907. messages.add(Text.of(TextColors.YELLOW, "Current Sponge Implementation: ",
  908. Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getName(), ", version ",
  909. Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getVersion().orElse("unknown"), "."));
  910. return messages;
  911. }
  912.  
  913. private void addTri(List<Text> messages, int spacing) {
  914. Text space = Text.of(String.join("", Collections.nCopies(spacing, " ")));
  915.  
  916. messages.add(Text.of(space, TextColors.YELLOW, " /\\"));
  917. messages.add(Text.of(space, TextColors.YELLOW, " / \\"));
  918. messages.add(Text.of(space, TextColors.YELLOW, " / || \\"));
  919. messages.add(Text.of(space, TextColors.YELLOW, " / || \\"));
  920. messages.add(Text.of(space, TextColors.YELLOW, " / || \\"));
  921. messages.add(Text.of(space, TextColors.YELLOW, " / || \\"));
  922. messages.add(Text.of(space, TextColors.YELLOW, " / \\"));
  923. messages.add(Text.of(space, TextColors.YELLOW, " / ** \\"));
  924. messages.add(Text.of(space, TextColors.YELLOW, "------------------"));
  925. }
  926.  
  927. @Override
  928. public void addX(List<Text> messages, int spacing) {
  929. Text space = Text.of(String.join("", Collections.nCopies(spacing, " ")));
  930. messages.add(Text.of(space, TextColors.RED, "\\ /"));
  931. messages.add(Text.of(space, TextColors.RED, " \\ /"));
  932. messages.add(Text.of(space, TextColors.RED, " \\ /"));
  933. messages.add(Text.of(space, TextColors.RED, " \\ /"));
  934. messages.add(Text.of(space, TextColors.RED, " \\ /"));
  935. messages.add(Text.of(space, TextColors.RED, " \\ /"));
  936. messages.add(Text.of(space, TextColors.RED, " \\ /"));
  937. messages.add(Text.of(space, TextColors.RED, " \\/"));
  938. messages.add(Text.of(space, TextColors.RED, " /\\"));
  939. messages.add(Text.of(space, TextColors.RED, " / \\"));
  940. messages.add(Text.of(space, TextColors.RED, " / \\"));
  941. messages.add(Text.of(space, TextColors.RED, " / \\"));
  942. messages.add(Text.of(space, TextColors.RED, " / \\"));
  943. messages.add(Text.of(space, TextColors.RED, " / \\"));
  944. messages.add(Text.of(space, TextColors.RED, " / \\"));
  945. messages.add(Text.of(space, TextColors.RED, "/ \\"));
  946. }
  947.  
  948. private List<Text> getErrorMessage() {
  949. List<Text> messages = Lists.newArrayList();
  950. messages.add(Text.of(TextColors.RED, "----------------------------"));
  951. messages.add(Text.of(TextColors.RED, "- NUCLEUS FAILED TO LOAD -"));
  952. messages.add(Text.of(TextColors.RED, "----------------------------"));
  953. addX(messages, 5);
  954. messages.add(Text.of(TextColors.RED, "----------------------------"));
  955.  
  956. messages.add(Text.EMPTY);
  957. messages.add(Text.of(TextColors.RED, "Nucleus encountered an error during server start up and did not enable successfully. No commands, listeners or tasks are registered."));
  958. messages.add(Text.of(TextColors.RED, "The server has been automatically whitelisted - this is to protect your server and players if you rely on some of Nucleus' functionality (such as fly states, etc.)"));
  959. messages.add(Text.of(TextColors.RED, "The error that Nucleus encountered will be reproduced below for your convenience."));
  960.  
  961. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  962. if (isErrored == null) {
  963. messages.add(Text.of(TextColors.YELLOW, "No exception was saved."));
  964. } else {
  965. Throwable exception = isErrored;
  966. if (exception.getCause() != null &&
  967. (exception instanceof QuickStartModuleLoaderException || exception instanceof QuickStartModuleDiscoveryException)) {
  968. exception = exception.getCause();
  969. }
  970.  
  971. // Blegh, relocations
  972. if (exception instanceof IOException && exception.getCause().getClass().getName().contains(ConfigException.class.getSimpleName())) {
  973. exception = exception.getCause();
  974. messages.add(Text.of(TextColors.RED, "It appears that there is an error in your configuration file! The error is: "));
  975. messages.add(Text.of(TextColors.RED, exception.getMessage()));
  976. messages.add(Text.of(TextColors.RED, "Please correct this and restart your server."));
  977. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  978. messages.add(Text.of(TextColors.YELLOW, "(The error that was thrown is shown below)"));
  979. }
  980.  
  981. try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
  982. exception.printStackTrace(pw);
  983. pw.flush();
  984. String[] stackTrace = sw.toString().split("(\r)?\n");
  985. for (String s : stackTrace) {
  986. messages.add(Text.of(TextColors.YELLOW, s));
  987. }
  988. } catch (IOException e) {
  989. exception.printStackTrace();
  990. }
  991. }
  992.  
  993. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  994. messages.add(Text.of(TextColors.RED, "If this error persists, check your configuration files and ensure that you have the latest version of Nucleus which matches the current version of the Sponge API."));
  995. messages.add(Text.of(TextColors.RED, "If you do, please report this error to the Nucleus team at https://github.com/NucleusPowered/Nucleus/issues"));
  996. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  997. messages.add(Text.of(TextColors.YELLOW, "Server Information"));
  998. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  999. messages.add(Text.of(TextColors.YELLOW, "Nucleus version: " + PluginInfo.VERSION + ", (Git: " + PluginInfo.GIT_HASH + ")"));
  1000.  
  1001. Platform platform = Sponge.getPlatform();
  1002. messages.add(Text.of(TextColors.YELLOW, "Minecraft version: " + platform.getMinecraftVersion().getName()));
  1003. messages.add(Text.of(TextColors.YELLOW, String.format("Sponge Version: %s %s", platform.getContainer(Platform.Component.IMPLEMENTATION).getName(),
  1004. platform.getContainer(Platform.Component.IMPLEMENTATION).getVersion().orElse("unknown"))));
  1005. messages.add(Text.of(TextColors.YELLOW, String.format("Sponge API Version: %s %s", platform.getContainer(Platform.Component.API).getName(),
  1006. platform.getContainer(Platform.Component.API).getVersion().orElse("unknown"))));
  1007.  
  1008. messages.add(Text.EMPTY);
  1009. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  1010. messages.add(Text.of(TextColors.YELLOW, "Installed Plugins"));
  1011. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  1012. Sponge.getPluginManager().getPlugins().forEach(x -> messages.add(Text.of(TextColors.YELLOW, x.getName() + " (" + x.getId() + ") version " + x.getVersion().orElse("unknown"))));
  1013.  
  1014. messages.add(Text.EMPTY);
  1015. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  1016. messages.add(Text.of(TextColors.YELLOW, "- END NUCLEUS ERROR REPORT -"));
  1017. messages.add(Text.of(TextColors.YELLOW, "----------------------------"));
  1018. return messages;
  1019. }
  1020. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement