156 lines
6.7 KiB
Java
156 lines
6.7 KiB
Java
package eu.mhsl.minecraft.pixelpics;
|
|
|
|
import eu.mhsl.minecraft.pixelpics.assets.AssetReader;
|
|
import eu.mhsl.minecraft.pixelpics.assets.BlockModelRegistry;
|
|
import eu.mhsl.minecraft.pixelpics.assets.ResourcePack;
|
|
import eu.mhsl.minecraft.pixelpics.assets.ResourcePackLoader;
|
|
import eu.mhsl.minecraft.pixelpics.assets.SkinCache;
|
|
import eu.mhsl.minecraft.pixelpics.assets.TextureCache;
|
|
import eu.mhsl.minecraft.pixelpics.assets.font.BitmapFont;
|
|
import eu.mhsl.minecraft.pixelpics.assets.font.FontLoader;
|
|
import eu.mhsl.minecraft.pixelpics.commands.PixelPicsCommand;
|
|
import eu.mhsl.minecraft.pixelpics.listeners.OnMapInitialize;
|
|
import eu.mhsl.minecraft.pixelpics.render.RenderManager;
|
|
import eu.mhsl.minecraft.pixelpics.render.entity.cem.BlockEntityBaker;
|
|
import eu.mhsl.minecraft.pixelpics.render.entity.cem.CemBaker;
|
|
import eu.mhsl.minecraft.pixelpics.render.entity.cem.CemModelLoader;
|
|
import eu.mhsl.minecraft.pixelpics.render.render.DefaultScreenRenderer;
|
|
import eu.mhsl.minecraft.pixelpics.render.tint.BiomeTintProvider;
|
|
import eu.mhsl.minecraft.pixelpics.survival.CameraListener;
|
|
import eu.mhsl.minecraft.pixelpics.survival.CraftingListener;
|
|
import eu.mhsl.minecraft.pixelpics.survival.JoinListener;
|
|
import eu.mhsl.minecraft.pixelpics.survival.SurvivalRecipes;
|
|
import eu.mhsl.minecraft.pixelpics.utils.MapColorPalette;
|
|
import java.io.File;
|
|
import java.io.InputStream;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.NamespacedKey;
|
|
import org.bukkit.plugin.java.JavaPlugin;
|
|
|
|
public final class Main extends JavaPlugin {
|
|
|
|
private static Main instance;
|
|
|
|
private ResourcePack resourcePack;
|
|
private DefaultScreenRenderer screenRenderer;
|
|
private RenderManager renderManager;
|
|
|
|
public final NamespacedKey pictureIdFlag = new NamespacedKey(this, "imageid");
|
|
|
|
/** Marks a {@code PLAYER_HEAD} as a camera (BYTE 1). */
|
|
public final NamespacedKey cameraMarker = new NamespacedKey(this, "camera");
|
|
/** Loaded film count stored on a camera (INTEGER, 0..{@code CameraItems.MAX_FILM}). */
|
|
public final NamespacedKey filmCountKey = new NamespacedKey(this, "filmcount");
|
|
/** Marks a {@code PLAYER_HEAD} as a film roll (BYTE 1). */
|
|
public final NamespacedKey filmMarker = new NamespacedKey(this, "film");
|
|
|
|
@Override
|
|
public void onEnable() {
|
|
instance = this;
|
|
|
|
saveDefaultConfig();
|
|
initRenderManager();
|
|
|
|
Bukkit.getPluginManager().registerEvents(new OnMapInitialize(), this);
|
|
Objects.requireNonNull(Bukkit.getPluginCommand("pixelPic")).setExecutor(new PixelPicsCommand());
|
|
|
|
Bukkit.getPluginManager().registerEvents(new CameraListener(), this);
|
|
Bukkit.getPluginManager().registerEvents(new CraftingListener(), this);
|
|
Bukkit.getPluginManager().registerEvents(new JoinListener(), this);
|
|
SurvivalRecipes.register();
|
|
|
|
initRenderer();
|
|
}
|
|
|
|
private void initRenderManager() {
|
|
int cores = Runtime.getRuntime().availableProcessors();
|
|
int threads = getConfig().getInt("render.threads", 0);
|
|
if (threads <= 0) threads = Math.max(1, cores - 2);
|
|
threads = Math.min(threads, cores);
|
|
int maxConcurrent = Math.max(1, getConfig().getInt("render.max-concurrent", 2));
|
|
int queueSize = Math.max(0, getConfig().getInt("render.queue-size", 8));
|
|
int timeoutSeconds = Math.max(1, getConfig().getInt("render.timeout-seconds", 30));
|
|
|
|
this.renderManager = new RenderManager(this, threads, maxConcurrent, queueSize, timeoutSeconds);
|
|
getLogger()
|
|
.info("Render pool: " + threads + " core(s), max " + maxConcurrent + " concurrent, queue " + queueSize
|
|
+ ", timeout " + timeoutSeconds + "s.");
|
|
}
|
|
|
|
private void initRenderer() {
|
|
File resourcePackDir = new File(getDataFolder(), "resourcepack");
|
|
if (!resourcePackDir.exists() && !resourcePackDir.mkdirs()) {
|
|
getLogger().warning("Could not create resource pack directory: " + resourcePackDir);
|
|
}
|
|
|
|
Optional<ResourcePack> pack = ResourcePackLoader.load(resourcePackDir, getLogger());
|
|
if (pack.isEmpty()) {
|
|
getLogger()
|
|
.severe("No resource pack found in " + resourcePackDir.getPath()
|
|
+ " — place a vanilla resource pack (directory with assets/minecraft/... or a .zip) there. "
|
|
+ "/pixelPic is disabled until a pack is available.");
|
|
return;
|
|
}
|
|
|
|
this.resourcePack = pack.get();
|
|
AssetReader reader = new AssetReader(resourcePack);
|
|
TextureCache textures = new TextureCache(resourcePack);
|
|
BlockModelRegistry registry = new BlockModelRegistry(reader, textures);
|
|
BiomeTintProvider tintProvider = new BiomeTintProvider(textures);
|
|
|
|
CemModelLoader cemLoader = new CemModelLoader();
|
|
try (InputStream in = getResource("cem/cem_template_models.json")) {
|
|
int n = in == null ? 0 : cemLoader.load(in, getLogger());
|
|
getLogger().info("Loaded " + n + " CEM entity models.");
|
|
} catch (Exception e) {
|
|
getLogger().severe("Failed to load CEM entity models: " + e.getMessage());
|
|
}
|
|
SkinCache skinCache = new SkinCache();
|
|
BitmapFont font = FontLoader.load(resourcePack, textures, getLogger());
|
|
getLogger().info("Loaded sign font (" + (font.isEmpty() ? "no glyphs — text disabled" : "ok") + ").");
|
|
CemBaker entityBaker = new CemBaker(cemLoader, textures, skinCache);
|
|
BlockEntityBaker blockEntityBaker = new BlockEntityBaker(cemLoader, textures, skinCache, font);
|
|
|
|
this.screenRenderer = new DefaultScreenRenderer(
|
|
registry,
|
|
tintProvider,
|
|
textures,
|
|
entityBaker,
|
|
blockEntityBaker,
|
|
getLogger(),
|
|
renderManager.tracePool());
|
|
// Warm the map palette on the main thread so off-thread dithering never triggers its first init.
|
|
MapColorPalette.size();
|
|
getLogger().info("PixelPics renderer initialized with resource pack assets.");
|
|
}
|
|
|
|
@Override
|
|
public void onDisable() {
|
|
SurvivalRecipes.unregister();
|
|
if (renderManager != null) {
|
|
renderManager.shutdown();
|
|
renderManager = null;
|
|
}
|
|
if (resourcePack != null) {
|
|
resourcePack.close();
|
|
resourcePack = null;
|
|
}
|
|
}
|
|
|
|
/** The renderer, or {@code null} when no resource pack is available (degraded mode). */
|
|
public DefaultScreenRenderer getScreenRenderer() {
|
|
return this.screenRenderer;
|
|
}
|
|
|
|
/** The render queue/limiter; always available after {@code onEnable}. */
|
|
public RenderManager getRenderManager() {
|
|
return this.renderManager;
|
|
}
|
|
|
|
public static Main getInstance() {
|
|
return instance;
|
|
}
|
|
}
|