add commonInterface sub-project

This commit is contained in:
James Seibel
2022-09-05 11:27:16 -05:00
parent 758b5b6db6
commit b33f7bbabd
3 changed files with 38 additions and 0 deletions
@@ -1,333 +0,0 @@
/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2022 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.api.internal.a7;
import com.seibel.lod.core.a7.level.IClientLevel;
import com.seibel.lod.core.a7.world.*;
import com.seibel.lod.core.api.external.methods.events.abstractEvents.*;
import com.seibel.lod.core.api.external.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.lod.core.api.implementation.wrappers.DhApiLevelWrapper;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.enums.rendering.EDebugMode;
import com.seibel.lod.core.enums.rendering.ERendererMode;
import com.seibel.lod.core.handlers.dependencyInjection.DhApiEventInjector;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
import com.seibel.lod.core.logging.SpamReducedLogger;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.render.GLProxy;
import com.seibel.lod.core.render.RenderSystemTest;
import com.seibel.lod.core.render.RenderUtil;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IClientLevelWrapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
/**
* This holds the methods that should be called
* by the host mod loader (Fabric, Forge, etc.).
* Specifically for the client.
*
* @author James Seibel
* @version 2022-8-23
*/
public class ClientApi
{
public static final Logger LOGGER = LogManager.getLogger(ClientApi.class.getSimpleName());
public static boolean prefLoggerEnabled = false;
public static final boolean ENABLE_EVENT_LOGGING = true;
public static final ClientApi INSTANCE = new ClientApi();
public static RenderSystemTest testRenderer = new RenderSystemTest();
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
public static final boolean ENABLE_LAG_SPIKE_LOGGING = false;
public static final long LAG_SPIKE_THRESHOLD_NS = TimeUnit.NANOSECONDS.convert(16, TimeUnit.MILLISECONDS);
public static final long SPAM_LOGGER_FLUSH_NS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
private boolean configOverrideReminderPrinted = false;
public boolean rendererDisabledBecauseOfExceptions = false;
private long lastFlush = 0;
public static class LagSpikeCatcher
{
long timer = System.nanoTime();
public LagSpikeCatcher()
{
}
public void end(String source)
{
if (!ENABLE_LAG_SPIKE_LOGGING)
return;
timer = System.nanoTime() - timer;
if (timer > LAG_SPIKE_THRESHOLD_NS)
{
LOGGER.info("LagSpikeCatcher: " + source + " took " + Duration.ofNanos(timer) + "!");
}
}
}
//==============//
// constructors //
//==============//
private ClientApi()
{
}
//========//
// events //
//========//
public void onClientOnlyConnected()
{
if (ENABLE_EVENT_LOGGING)
LOGGER.info("Client on ClientOnly mode connecting.");
SharedApi.currentWorld = new DhClientWorld();
}
public void onClientOnlyDisconnected()
{
if (ENABLE_EVENT_LOGGING)
LOGGER.info("Client on ClientOnly mode disconnecting.");
SharedApi.currentWorld.close();
SharedApi.currentWorld = null;
}
public void clientChunkLoadEvent(IChunkWrapper chunk, IClientLevelWrapper level)
{
if (SharedApi.getEnvironment() == WorldEnvironment.Client_Only)
{
//TODO: Implement
}
}
public void clientChunkSaveEvent(IChunkWrapper chunk, IClientLevelWrapper level)
{
if (SharedApi.getEnvironment() == WorldEnvironment.Client_Only)
{
//TODO: Implement
// TODO: potentially add a list of chunks that were updated during the save
DhApiEventInjector.INSTANCE.fireAllEvents(DhApiLevelSaveEvent.class, new DhApiLevelSaveEvent.EventParam(new DhApiLevelWrapper(level)));
}
}
public void clientLevelUnloadEvent(IClientLevelWrapper level)
{
if (ENABLE_EVENT_LOGGING)
LOGGER.info("Client level {} unloading.", level);
if (SharedApi.currentWorld != null)
{
SharedApi.currentWorld.unloadLevel(level);
DhApiEventInjector.INSTANCE.fireAllEvents(DhApiLevelUnloadEvent.class, new DhApiLevelUnloadEvent.EventParam(new DhApiLevelWrapper(level)));
}
}
public void clientLevelLoadEvent(IClientLevelWrapper level)
{
if (ENABLE_EVENT_LOGGING)
LOGGER.info("Client level {} loading.", level);
if (SharedApi.currentWorld != null)
{
SharedApi.currentWorld.getOrLoadLevel(level);
DhApiEventInjector.INSTANCE.fireAllEvents(DhApiLevelLoadEvent.class, new DhApiLevelLoadEvent.EventParam(new DhApiLevelWrapper(level)));
}
}
public void rendererShutdownEvent()
{
if (ENABLE_EVENT_LOGGING)
LOGGER.info("Renderer shutting down.");
IProfilerWrapper profiler = MC.getProfiler();
profiler.push("DH-RendererShutdown");
profiler.pop();
}
public void rendererStartupEvent()
{
if (ENABLE_EVENT_LOGGING)
LOGGER.info("Renderer starting up.");
IProfilerWrapper profiler = MC.getProfiler();
profiler.push("DH-RendererStartup");
// make sure the GLProxy is created before the LodBufferBuilder needs it
GLProxy.getInstance();
profiler.pop();
}
public void clientTickEvent()
{
IProfilerWrapper profiler = MC.getProfiler();
profiler.push("DH-ClientTick");
boolean doFlush = System.nanoTime() - lastFlush >= SPAM_LOGGER_FLUSH_NS;
if (doFlush)
{
lastFlush = System.nanoTime();
SpamReducedLogger.flushAll();
}
ConfigBasedLogger.updateAll();
ConfigBasedSpamLogger.updateAll(doFlush);
if (SharedApi.currentWorld instanceof IClientWorld)
{
((IClientWorld) SharedApi.currentWorld).clientTick();
}
profiler.pop();
}
//===========//
// rendering //
//===========//
public void renderLods(IClientLevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks)
{
if (ModInfo.IS_DEV_BUILD && !configOverrideReminderPrinted && MC.playerExists())
{
// remind the user that this is a development build
MC.sendChatMessage(ModInfo.READABLE_NAME + " experimental build " + ModInfo.VERSION);
MC.sendChatMessage("You are running an unsupported version of Distant Horizons!");
MC.sendChatMessage("Here be dragons!");
configOverrideReminderPrinted = true;
}
IProfilerWrapper profiler = MC.getProfiler();
profiler.pop(); // get out of "terrain"
profiler.push("DH-RenderLevel");
try
{
if (!RenderUtil.shouldLodsRender(levelWrapper))
return;
//FIXME: Improve class hierarchy of DhWorld, IClientWorld, IServerWorld to fix all this hard casting
// (also in RenderUtil)
DhWorld dhWorld = SharedApi.currentWorld;
IClientLevel level = (IClientLevel) dhWorld.getOrLoadLevel(levelWrapper);
if (prefLoggerEnabled)
{
level.dumpRamUsage();
}
profiler.push("Render" + ( Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEFAULT ? "-lods" : "-debug"));
try
{
if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEFAULT)
{
DhApiRenderParam renderEventParam =
new DhApiRenderParam(mcProjectionMatrix, mcModelViewMatrix,
RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks),
RenderUtil.createLodModelViewMatrix(mcModelViewMatrix), partialTicks);
boolean renderingCanceled = DhApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, new DhApiBeforeRenderEvent.EventParam(renderEventParam));
if (!rendererDisabledBecauseOfExceptions && !renderingCanceled)
{
level.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler);
DhApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, new DhApiAfterRenderEvent.EventParam(renderEventParam));
}
}
else if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEBUG)
{
ClientApi.testRenderer.render();
}
// the other rendererMode is DISABLED
}
catch (RuntimeException e)
{
rendererDisabledBecauseOfExceptions = true;
LOGGER.error("Renderer thrown an uncaught exception: ", e);
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons"
+ " renderer has encountered an exception!");
MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues.");
MC.sendChatMessage("\u00A74Exception detail: " + e);
}
profiler.pop();
}
catch (Exception e)
{
LOGGER.error("client level rendering uncaught exception: ", e);
}
finally
{
profiler.pop(); // end LOD
profiler.push("terrain"); // go back into "terrain"
}
}
//=================//
// DEBUG USE //
//=================//
// Trigger once on key press, with CLIENT PLAYER.
public void keyPressedEvent(int glfwKey)
{
if (!Config.Client.Advanced.Debugging.enableDebugKeybindings.get())
return;
if (glfwKey == GLFW.GLFW_KEY_F8)
{
Config.Client.Advanced.Debugging.debugMode.set(EDebugMode.next(Config.Client.Advanced.Debugging.debugMode.get()));
MC.sendChatMessage("F8: Set debug mode to " + Config.Client.Advanced.Debugging.debugMode.get());
}
if (glfwKey == GLFW.GLFW_KEY_F6)
{
Config.Client.Advanced.Debugging.rendererMode.set(ERendererMode.next(Config.Client.Advanced.Debugging.rendererMode.get()));
MC.sendChatMessage("F6: Set rendering to " + Config.Client.Advanced.Debugging.rendererMode.get());
}
if (glfwKey == GLFW.GLFW_KEY_P)
{
prefLoggerEnabled = !prefLoggerEnabled;
MC.sendChatMessage("P: Debug Pref Logger is " + (prefLoggerEnabled ? "enabled" : "disabled"));
}
}
}
@@ -1,136 +0,0 @@
/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2022 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.api.internal.a7;
import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.a7.world.DhClientServerWorld;
import com.seibel.lod.core.a7.world.DhServerWorld;
import com.seibel.lod.core.a7.world.IServerWorld;
import com.seibel.lod.core.api.external.methods.events.abstractEvents.DhApiLevelLoadEvent;
import com.seibel.lod.core.api.external.methods.events.abstractEvents.DhApiLevelSaveEvent;
import com.seibel.lod.core.api.external.methods.events.abstractEvents.DhApiLevelUnloadEvent;
import com.seibel.lod.core.api.implementation.wrappers.DhApiLevelWrapper;
import com.seibel.lod.core.handlers.dependencyInjection.DhApiEventInjector;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IServerLevelWrapper;
import org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandles;
/**
* This holds the methods that should be called by the host mod loader (Fabric,
* Forge, etc.). Specifically server events.
*
* @author James Seibel
* @version 2022-8-23
*/
public class ServerApi
{
public static final boolean ENABLE_STACK_DUMP_LOGGING = false;
public static final ServerApi INSTANCE = new ServerApi();
public static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class);
public static final boolean ENABLE_EVENT_LOGGING = true;
private ServerApi()
{
}
// =============//
// tick events //
// =============//
private int lastWorldGenTickDelta = 0;
public void serverTickEvent()
{
if (SharedApi.currentWorld instanceof IServerWorld) {
IServerWorld serverWorld = (IServerWorld) SharedApi.currentWorld;
serverWorld.serverTick();
lastWorldGenTickDelta--;
if (lastWorldGenTickDelta <= 0) {
serverWorld.doWorldGen();
lastWorldGenTickDelta = 20;
}
}
}
public void serverLevelTickEvent(IServerLevelWrapper level) {
//TODO
}
//TODO: rename to serverLoadEvent
public void serverWorldLoadEvent(boolean isDedicatedEnvironment) {
if (ENABLE_EVENT_LOGGING) LOGGER.info("Server World loading with (dedicated?:{})", isDedicatedEnvironment);
if (isDedicatedEnvironment) {
SharedApi.currentWorld = new DhServerWorld();
} else {
SharedApi.currentWorld = new DhClientServerWorld();
}
}
//TODO: rename to serverUnloadEvent
public void serverWorldUnloadEvent() {
if (ENABLE_EVENT_LOGGING) LOGGER.info("Server World {} unloading", SharedApi.currentWorld);
SharedApi.currentWorld.close();
SharedApi.currentWorld = null;
}
public void serverLevelLoadEvent(IServerLevelWrapper level) {
if (ENABLE_EVENT_LOGGING) LOGGER.info("Server Level {} loading", level);
if (SharedApi.currentWorld != null)
{
SharedApi.currentWorld.getOrLoadLevel(level);
DhApiEventInjector.INSTANCE.fireAllEvents(DhApiLevelLoadEvent.class, new DhApiLevelLoadEvent.EventParam(new DhApiLevelWrapper(level)));
}
}
public void serverLevelUnloadEvent(IServerLevelWrapper level) {
if (ENABLE_EVENT_LOGGING) LOGGER.info("Server Level {} unloading", level);
if (SharedApi.currentWorld != null)
{
SharedApi.currentWorld.unloadLevel(level);
DhApiEventInjector.INSTANCE.fireAllEvents(DhApiLevelUnloadEvent.class, new DhApiLevelUnloadEvent.EventParam(new DhApiLevelWrapper(level)));
}
}
@Deprecated
public void serverSaveEvent() {
if (ENABLE_EVENT_LOGGING) LOGGER.info("Server world {} saving", SharedApi.currentWorld);
if (SharedApi.currentWorld instanceof IServerWorld)
{
SharedApi.currentWorld.saveAndFlush();
for (ILevel level : SharedApi.currentWorld.getAllLoadedLevels())
{
DhApiEventInjector.INSTANCE.fireAllEvents(DhApiLevelSaveEvent.class, new DhApiLevelSaveEvent.EventParam(new DhApiLevelWrapper(level.getLevelWrapper())));
}
}
}
public void serverChunkLoadEvent(IChunkWrapper chunk, ILevelWrapper world) {
//TODO
}
public void serverChunkSaveEvent(IChunkWrapper chunk, ILevelWrapper world) {
//TODO
}
}