package com.hypixel.hytale.server.core.plugin;
import com.hypixel.hytale.assetstore.JsonAsset;
import com.hypixel.hytale.assetstore.codec.AssetCodecMapCodec;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.codecs.EnumCodec;
import com.hypixel.hytale.codec.lookup.MapKeyMapCodec;
import com.hypixel.hytale.codec.lookup.StringCodecMapCodec;
import com.hypixel.hytale.common.plugin.PluginIdentifier;
import com.hypixel.hytale.common.plugin.PluginManifest;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import com.hypixel.hytale.event.EventRegistry;
import com.hypixel.hytale.function.consumer.BooleanConsumer;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.metrics.MetricProvider;
import com.hypixel.hytale.metrics.MetricsRegistry;
import com.hypixel.hytale.server.core.HytaleServer;
import com.hypixel.hytale.server.core.command.system.CommandOwner;
import com.hypixel.hytale.server.core.command.system.CommandRegistry;
import com.hypixel.hytale.server.core.modules.entity.EntityRegistry;
import com.hypixel.hytale.server.core.plugin.registry.AssetRegistry;
import com.hypixel.hytale.server.core.plugin.registry.CodecMapRegistry;
import com.hypixel.hytale.server.core.plugin.registry.IRegistry;
import com.hypixel.hytale.server.core.plugin.registry.MapKeyMapRegistry;
import com.hypixel.hytale.server.core.registry.ClientFeatureRegistry;
import com.hypixel.hytale.server.core.task.TaskRegistry;
import com.hypixel.hytale.server.core.universe.world.meta.BlockStateRegistry;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.util.Config;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class PluginBase implements CommandOwner {
@Nonnull
public static final MetricsRegistry<PluginBase> METRICS_REGISTRY;
@Nonnull
private final HytaleLogger logger;
@Nonnull
private final PluginIdentifier identifier;
@Nonnull
private final PluginManifest manifest;
@Nonnull
private final Path dataDirectory;
@Nonnull
private final List<Config<?>> configs = new CopyOnWriteArrayList();
@Nonnull
private PluginState state;
private final String notEnabledString;
@Nonnull
private final CopyOnWriteArrayList<BooleanConsumer> shutdownTasks;
private final ClientFeatureRegistry clientFeatureRegistry;
private final CommandRegistry commandRegistry;
private final EventRegistry eventRegistry;
private final BlockStateRegistry blockStateRegistry;
private final EntityRegistry entityRegistry;
private final TaskRegistry taskRegistry;
private final ComponentRegistryProxy<EntityStore> entityStoreRegistry;
private final ComponentRegistryProxy<ChunkStore> chunkStoreRegistry;
private final AssetRegistry assetRegistry;
private final Map<Codec<?>, IRegistry> codecMapRegistries;
@Nonnull
private final String basePermission;
public PluginBase(@Nonnull PluginInit init) {
this.state = PluginState.NONE;
String var10001 = String.valueOf(this.getIdentifier());
this.notEnabledString = "The plugin " + var10001 + " is not enabled!";
this.shutdownTasks = new CopyOnWriteArrayList();
this.clientFeatureRegistry = new ClientFeatureRegistry(this.shutdownTasks, () -> this.state != PluginState.NONE && this.state != PluginState.DISABLED, this.notEnabledString, this);
this.commandRegistry = new CommandRegistry(this.shutdownTasks, () -> this.state != PluginState.NONE && this.state != PluginState.DISABLED, this.notEnabledString, this);
this.eventRegistry = new EventRegistry(this.shutdownTasks, () -> this.state != PluginState.NONE && this.state != PluginState.DISABLED, this.notEnabledString, HytaleServer.get().getEventBus());
this.blockStateRegistry = new BlockStateRegistry(this.shutdownTasks, () -> this.state != PluginState.NONE && this.state != PluginState.DISABLED, this.notEnabledString);
this.entityRegistry = new EntityRegistry(this.shutdownTasks, () -> this.state != PluginState.NONE && this.state != PluginState.DISABLED, this.notEnabledString);
this.taskRegistry = new TaskRegistry(this.shutdownTasks, () -> this.state != PluginState.NONE && this.state != PluginState.DISABLED, this.notEnabledString);
this.entityStoreRegistry = new ComponentRegistryProxy<EntityStore>(this.shutdownTasks, EntityStore.REGISTRY);
this.chunkStoreRegistry = new ComponentRegistryProxy<ChunkStore>(this.shutdownTasks, ChunkStore.REGISTRY);
this.assetRegistry = new AssetRegistry(this.shutdownTasks);
this.codecMapRegistries = new ConcurrentHashMap();
PluginManifest pluginManifest = init.getPluginManifest();
String pluginName = pluginManifest.getName();
boolean isPlugin = this.getType() == PluginType.PLUGIN;
this.logger = HytaleLogger.get(pluginName + (isPlugin ? "|P" : "|A"));
this.dataDirectory = init.getDataDirectory();
this.identifier = new PluginIdentifier(pluginManifest);
this.manifest = pluginManifest;
if (!init.isInServerClassPath()) {
this.logger.setPropagatesSentryToParent(false);
}
var10001 = pluginManifest.getGroup();
this.basePermission = (var10001 + "." + pluginName).toLowerCase();
}
@Nonnull
protected final <T> Config<T> withConfig(@Nonnull BuilderCodec<T> configCodec) {
return this.<T>withConfig("config", configCodec);
}
@Nonnull
protected final <T> Config<T> withConfig(@Nonnull String name, @Nonnull BuilderCodec<T> configCodec) {
if (this.state != PluginState.NONE) {
throw new IllegalStateException("Must be called before setup");
} else {
Config<T> config = new Config<T>(this.dataDirectory, name, configCodec);
this.configs.add(config);
return config;
}
}
@Nullable
public CompletableFuture<Void> preLoad() {
if (this.configs.isEmpty()) {
return null;
} else {
CompletableFuture<?>[] futures = new CompletableFuture[this.configs.size()];
for(int i = 0; i < this.configs.size(); ++i) {
futures[i] = ((Config)this.configs.get(i)).load();
}
return CompletableFuture.allOf(futures);
}
}
@Nonnull
public String getName() {
return this.identifier.toString();
}
@Nonnull
public HytaleLogger getLogger() {
return this.logger;
}
@Nonnull
public PluginIdentifier getIdentifier() {
return this.identifier;
}
@Nonnull
public PluginManifest getManifest() {
return this.manifest;
}
@Nonnull
public Path getDataDirectory() {
return this.dataDirectory;
}
@Nonnull
public PluginState getState() {
return this.state;
}
@Nonnull
public ClientFeatureRegistry getClientFeatureRegistry() {
return this.clientFeatureRegistry;
}
@Nonnull
public CommandRegistry getCommandRegistry() {
return this.commandRegistry;
}
@Nonnull
public EventRegistry getEventRegistry() {
return this.eventRegistry;
}
@Nonnull
public BlockStateRegistry getBlockStateRegistry() {
return this.blockStateRegistry;
}
@Nonnull
public EntityRegistry getEntityRegistry() {
return this.entityRegistry;
}
@Nonnull
public TaskRegistry getTaskRegistry() {
return this.taskRegistry;
}
@Nonnull
public ComponentRegistryProxy<EntityStore> getEntityStoreRegistry() {
return this.entityStoreRegistry;
}
@Nonnull
public ComponentRegistryProxy<ChunkStore> getChunkStoreRegistry() {
return this.chunkStoreRegistry;
}
@Nonnull
public AssetRegistry getAssetRegistry() {
return this.assetRegistry;
}
@Nonnull
public <T, C extends Codec<? extends T>> CodecMapRegistry<T, C> getCodecRegistry(@Nonnull StringCodecMapCodec<T, C> mapCodec) {
IRegistry registry = (IRegistry)this.codecMapRegistries.computeIfAbsent(mapCodec, (v) -> new CodecMapRegistry(this.shutdownTasks, mapCodec));
return (CodecMapRegistry)registry;
}
@Nonnull
public <K, T extends JsonAsset<K>> CodecMapRegistry.Assets<T, ?> getCodecRegistry(@Nonnull AssetCodecMapCodec<K, T> mapCodec) {
IRegistry registry = (IRegistry)this.codecMapRegistries.computeIfAbsent(mapCodec, (v) -> new CodecMapRegistry.Assets(this.shutdownTasks, mapCodec));
return (CodecMapRegistry.Assets)registry;
}
@Nonnull
public <V> MapKeyMapRegistry<V> getCodecRegistry(@Nonnull MapKeyMapCodec<V> mapCodec) {
IRegistry registry = (IRegistry)this.codecMapRegistries.computeIfAbsent(mapCodec, (v) -> new MapKeyMapRegistry(this.shutdownTasks, mapCodec));
return (MapKeyMapRegistry)registry;
}
@Nonnull
public final String getBasePermission() {
return this.basePermission;
}
public boolean isDisabled() {
return this.state == PluginState.NONE || this.state == PluginState.DISABLED || this.state == PluginState.SHUTDOWN;
}
public boolean isEnabled() {
return !this.isDisabled();
}
protected void setup0() {
if (this.state != PluginState.NONE && this.state != PluginState.DISABLED) {
throw new IllegalArgumentException(String.valueOf(this.state));
} else {
this.state = PluginState.SETUP;
try {
this.setup();
} catch (Throwable t) {
((HytaleLogger.Api)this.logger.at(Level.SEVERE).withCause(t)).log("Failed to setup plugin %s", this.identifier);
this.state = PluginState.DISABLED;
}
}
}
protected void setup() {
}
protected void start0() {
if (this.state != PluginState.SETUP) {
throw new IllegalArgumentException(String.valueOf(this.state));
} else {
this.state = PluginState.START;
try {
this.start();
this.state = PluginState.ENABLED;
} catch (Throwable t) {
((HytaleLogger.Api)this.logger.at(Level.SEVERE).withCause(t)).log("Failed to start %s", this.identifier);
this.state = PluginState.DISABLED;
}
}
}
protected void start() {
}
protected void shutdown0(boolean shutdown) {
this.state = PluginState.SHUTDOWN;
try {
this.shutdown();
this.state = PluginState.DISABLED;
} catch (Throwable t) {
((HytaleLogger.Api)this.logger.at(Level.SEVERE).withCause(t)).log("Failed to shutdown %s", this.identifier);
}
this.cleanup(shutdown);
}
protected void shutdown() {
}
void cleanup(boolean shutdown) {
this.commandRegistry.shutdown();
this.eventRegistry.shutdown();
this.clientFeatureRegistry.shutdown();
this.blockStateRegistry.shutdown();
this.taskRegistry.shutdown();
this.entityStoreRegistry.shutdown();
this.chunkStoreRegistry.shutdown();
this.codecMapRegistries.forEach((k, v) -> v.shutdown());
this.assetRegistry.shutdown();
for(int i = this.shutdownTasks.size() - 1; i >= 0; --i) {
((BooleanConsumer)this.shutdownTasks.get(i)).accept(shutdown);
}
}
@Nonnull
public abstract PluginType getType();
static {
METRICS_REGISTRY = (new MetricsRegistry(MetricProvider.maybe(Function.identity()))).register("Identifier", (plugin) -> plugin.identifier.toString(), Codec.STRING).register("Type", PluginBase::getType, new EnumCodec(PluginType.class)).register("Manifest", (plugin) -> plugin.manifest, PluginManifest.CODEC).register("State", (plugin) -> plugin.state, new EnumCodec(PluginState.class)).register("Builtin", (plugin) -> {
boolean var10000;
if (plugin instanceof JavaPlugin jp) {
if (jp.getClassLoader().isInServerClassPath()) {
var10000 = true;
return var10000;
}
}
var10000 = false;
return var10000;
}, Codec.BOOLEAN);
}
}