001package net.tnemc.plugincore; 002 003/* 004 * The New Plugin Core 005 * Copyright (C) 2022 - 2024 Daniel "creatorfromhell" Vidmar 006 * 007 * This program is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU Affero General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU Affero General Public License for more details. 016 * 017 * You should have received a copy of the GNU Affero General Public License 018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 019 */ 020 021import net.tnemc.plugincore.core.Platform; 022import net.tnemc.plugincore.core.PluginEngine; 023import net.tnemc.plugincore.core.api.CallbackManager; 024import net.tnemc.plugincore.core.api.CallbackProvider; 025import net.tnemc.plugincore.core.channel.ChannelMessageManager; 026import net.tnemc.plugincore.core.compatibility.LogProvider; 027import net.tnemc.plugincore.core.compatibility.ServerConnector; 028import net.tnemc.plugincore.core.compatibility.log.DebugLevel; 029import net.tnemc.plugincore.core.id.UUIDProvider; 030import net.tnemc.plugincore.core.id.impl.provider.BaseUUIDProvider; 031import net.tnemc.plugincore.core.io.message.MessageHandler; 032import net.tnemc.plugincore.core.io.message.TranslationProvider; 033import net.tnemc.plugincore.core.io.storage.StorageManager; 034import net.tnemc.plugincore.core.module.ModuleLoader; 035import net.tnemc.plugincore.core.module.cache.ModuleFileCache; 036import net.tnemc.plugincore.core.utils.UpdateChecker; 037import org.jetbrains.annotations.Nullable; 038import revxrsal.commands.Lamp; 039import revxrsal.commands.command.CommandActor; 040import revxrsal.commands.orphan.Orphans; 041 042import java.io.File; 043import java.util.UUID; 044import java.util.regex.Pattern; 045 046public class PluginCore { 047 048 /* 049 * Core final variables utilized within TNPC. 050 */ 051 public static final Pattern UUID_MATCHER_PATTERN = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})"); 052 public static final Pattern USERNAME_MATCHER_PATTERN = Pattern.compile("^\\w*$"); 053 054 /* Core non-final variables utilized within TNPC as settings */ 055 protected File directory; 056 057 //The DebugLevel that the server is currently running in. 058 protected DebugLevel level = DebugLevel.STANDARD; 059 060 /* Key Managers and Object instances utilized with TNE */ 061 062 //General Key Object Instances 063 protected LogProvider logger; 064 065 protected PluginEngine engine; 066 067 //Manager Instances 068 protected ServerConnector server; 069 protected UUIDProvider uuidProvider; 070 private final MessageHandler messenger; 071 072 /* Plugin Instance */ 073 private static PluginCore instance; 074 075 protected CallbackManager callbackManager; 076 protected ChannelMessageManager channelMessageManager; 077 078 protected ModuleLoader loader; 079 protected ModuleFileCache moduleCache; 080 081 private boolean enabled = false; 082 083 protected UUID serverID; 084 085 protected Platform platform; 086 protected String version; 087 088 public PluginCore(final PluginEngine engine, final ServerConnector server, final LogProvider logger, 089 final TranslationProvider provider, final CallbackProvider callbackProvider, 090 final Platform platform, final String version) { 091 this.server = server; 092 this.logger = logger; 093 this.engine = engine; 094 this.messenger = new MessageHandler(provider); 095 this.callbackManager = new CallbackManager(callbackProvider); 096 097 this.platform = platform; 098 this.version = version; 099 } 100 101 public static void setInstance(final PluginCore core) { 102 if(instance == null) { 103 instance = core; 104 } else { 105 throw new IllegalStateException("PluginCore has already been initiated. Please refrain from attempting" + 106 "to modify the instance variable."); 107 } 108 } 109 110 public void enable() { 111 if(!enabled) { 112 113 this.enabled = true; 114 this.loader = new ModuleLoader(); 115 onEnable(); 116 117 } else { 118 throw new IllegalStateException("PluginCore has already been enabled!"); 119 } 120 } 121 122 /** 123 * Used to enable the core. This should contain things that can't be initialized until after the 124 * server software is operational. 125 */ 126 protected void onEnable() { 127 128 if(!directory.exists()) { 129 final boolean created = directory.mkdir(); 130 if(!created) { 131 logger.error("Failed to create plugin directory. Disabling plugin.", DebugLevel.OFF); 132 return; 133 } 134 } 135 this.serverID = UUID.randomUUID(); 136 137 this.uuidProvider = new BaseUUIDProvider(); 138 139 this.engine.registerConfigs(); 140 141 this.engine.initComponents(platform, version); 142 this.engine.initRegistries(platform, version); 143 144 //Load our modules 145 loader.load(); 146 147 //Call onEnable for all modules loaded. 148 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().enable(this))); 149 150 //Call initConfigurations for all modules loaded. 151 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().initConfigurations(directory))); 152 153 this.engine.registerCallbacks(callbackManager); 154 155 //Register the callback listeners and callbacks for the modules 156 loader.getModules().values().forEach((moduleWrapper ->{ 157 moduleWrapper.getModule().registerCallbacks().forEach((key, entry)->{ 158 callbackManager.addCallback(key, entry); 159 }); 160 161 moduleWrapper.getModule().registerListeners().forEach((key, function)->{ 162 callbackManager.addConsumer(key, function); 163 }); 164 })); 165 166 this.engine.postConfigs(); 167 168 this.channelMessageManager = new ChannelMessageManager(); 169 170 this.engine.registerPluginChannels(); 171 172 this.channelMessageManager.register(); 173 174 this.engine.registerStorage(); 175 if(this.engine.storage() == null) { 176 logger.warning("Storage engine not initialized, proceeding without storage!", DebugLevel.OFF); 177 } else { 178 if(!storage().meetsRequirement()) { 179 logger.error("This server does not meet SQL requirements needed!", DebugLevel.OFF); 180 return; 181 } 182 } 183 184 this.engine.postStorage(); 185 186 //Call the enableSave method for all modules loaded. 187 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().enableSave(this.engine.storage()))); 188 189 //register our commands 190 this.engine.registerCommandHandler(); 191 192 //Register our help writer. 193 //command().setHelpWriter(engine::commandHelpWriter); 194 195 //Register our commands. 196 this.engine.registerCommands(); 197 198 //Call our command methods for the modules. 199 loader.getModules().values().forEach((moduleWrapper ->{ 200 moduleWrapper.getModule().registerCommands(this.engine.command()); 201 })); 202 203 204 this.engine.postCommands(); 205 206 this.engine.registerMenuHandler(); 207 208 //Call enableMenu for all modules loaded. 209 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().enableMenu(this.engine.menu()))); 210 211 this.moduleCache = new ModuleFileCache(); 212 213 this.engine.registerUpdateChecker(); 214 215 this.engine.postEnable(); 216 } 217 218 public void registerModuleCommands(final Lamp<?> lamp) { 219 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().registerAdminSub().forEach(orphanCommand -> { 220 lamp.register(Orphans.path("tne").handler(orphanCommand)); 221 }))); 222 223 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().registerMoneySub().forEach(orphanCommand -> { 224 lamp.register(Orphans.path("money").handler(orphanCommand)); 225 }))); 226 227 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().registerTransactionSub().forEach(orphanCommand -> { 228 lamp.register(Orphans.path("transaction").handler(orphanCommand)); 229 }))); 230 } 231 232 public void onDisable() { 233 234 loader.getModules().values().forEach((moduleWrapper -> moduleWrapper.getModule().disable(this))); 235 236 this.engine.postDisable(); 237 } 238 239 /** 240 * The implementation's {@link LogProvider}. 241 * 242 * @return The log provider. 243 */ 244 public static LogProvider log() { 245 return instance.logger; 246 } 247 248 /** 249 * The {@link StorageManager} we are utilizing. 250 * 251 * @return The {@link StorageManager}. 252 */ 253 public static StorageManager storage() { 254 return instance.engine.storage(); 255 } 256 257 /** 258 * The {@link ServerConnector} for the implementation. 259 * @return The {@link ServerConnector} for the implementation. 260 */ 261 public static ServerConnector server() { 262 return instance.server; 263 } 264 265 public static MessageHandler messenger() { 266 return instance.messenger; 267 } 268 269 public static File directory() { 270 return instance.directory; 271 } 272 273 public static CallbackManager callbacks() { 274 return instance.callbackManager; 275 } 276 277 public ChannelMessageManager getChannelMessageManager() { 278 return channelMessageManager; 279 } 280 281 public static ModuleLoader loader() { 282 return instance.loader; 283 } 284 285 @Nullable 286 public static UpdateChecker update() { 287 return instance.engine.update(); 288 } 289 290 public ModuleFileCache moduleCache() { 291 return moduleCache; 292 } 293 294 public DebugLevel getLevel() { 295 return level; 296 } 297 298 public void setLevel(final DebugLevel level) { 299 this.level = level; 300 } 301 302 public Lamp.Builder<? extends CommandActor> command() { 303 return engine.command(); 304 } 305 306 public static PluginCore instance() { 307 return instance; 308 } 309 310 public static UUIDProvider uuidProvider() { 311 return instance.uuidProvider; 312 } 313 314 public UUID getServerID() { 315 return serverID; 316 } 317 318 public void setServerID(final UUID serverID) { 319 this.serverID = serverID; 320 } 321 322 public void setCallbackManager(final CallbackManager callbackManager) { 323 this.callbackManager = callbackManager; 324 } 325 326 public static PluginEngine engine() { 327 return instance.engine; 328 } 329}