portal guns WORK NOW BABYYYYYYY
This commit is contained in:
1 parent
39688c70ad
commit
dcf5eb3cb1
44 files changed
+1566
-2441
No files matched your search
-116
@@ -1,116 +0,0 @@
|
||||
package com.craisinlord.antarchy.content.client;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.item.PortalGunItem;
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
|
||||
import com.craisinlord.antarchy.content.client.PortalGunIndicatorClientState;
|
||||
import com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload;
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
||||
public final class PortalGunCrosshairRenderer {
|
||||
private static final ResourceLocation CROSSHAIR = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/gui/portal_gun_crosshair.png");
|
||||
private static final int WIDTH = 34;
|
||||
private static final int HEIGHT = 33;
|
||||
private static ClientLevel cachedLevel;
|
||||
private static long cachedGameTime = Long.MIN_VALUE;
|
||||
private static UUID cachedOwnerId;
|
||||
private static Set<PortalKey> cachedPortals = Set.of();
|
||||
|
||||
private PortalGunCrosshairRenderer() {
|
||||
}
|
||||
|
||||
public static void render(GuiGraphics guiGraphics) {
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
if (PortalGunGrabClientState.isActive()) {
|
||||
return;
|
||||
}
|
||||
if (minecraft.player == null || minecraft.screen != null || minecraft.options.hideGui || !minecraft.options.getCameraType().isFirstPerson()) {
|
||||
return;
|
||||
}
|
||||
ItemStack held = minecraft.player.getMainHandItem();
|
||||
if (!(held.getItem() instanceof PortalGunItem)) {
|
||||
held = minecraft.player.getOffhandItem();
|
||||
if (!(held.getItem() instanceof PortalGunItem)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
UUID gunId = PortalGunItem.getGunId(held);
|
||||
UUID ownerId = PortalGunItem.getPortalOwnerId(held, minecraft.player.getUUID());
|
||||
String channelName = PortalGunItem.getChannelName(held);
|
||||
PortalGunIndicatorClientState.requestIfNeeded(minecraft, gunId);
|
||||
Set<PortalKey> portals = portalsFor(minecraft, ownerId, channelName);
|
||||
PortalGunIndicatorPayload serverState = PortalGunIndicatorClientState.get(gunId);
|
||||
boolean blueAvailable = serverState == null
|
||||
? portals.contains(new PortalKey(channelName, PortalGunPortalEntity.PortalSide.BLUE))
|
||||
: serverState.blueAvailable();
|
||||
boolean orangeAvailable = serverState == null
|
||||
? portals.contains(new PortalKey(channelName, PortalGunPortalEntity.PortalSide.ORANGE))
|
||||
: serverState.orangeAvailable();
|
||||
|
||||
int left = (minecraft.getWindow().getGuiScaledWidth() - WIDTH) / 2;
|
||||
int top = (minecraft.getWindow().getGuiScaledHeight() - HEIGHT) / 2;
|
||||
guiGraphics.blit(CROSSHAIR, left + 6, top, 0.0F, 0.0F, 17, HEIGHT, WIDTH, HEIGHT);
|
||||
guiGraphics.blit(CROSSHAIR, left + 11, top, 17.0F, 0.0F, 17, HEIGHT, WIDTH, HEIGHT);
|
||||
if (!blueAvailable) {
|
||||
guiGraphics.fill(left + 6, top, left + 23, top + HEIGHT, 0x99000000);
|
||||
}
|
||||
if (!orangeAvailable) {
|
||||
guiGraphics.fill(left + 11, top, left + 28, top + HEIGHT, 0x99000000);
|
||||
}
|
||||
int indicatorSize = AntarchySettings.portalGunIndicatorSize();
|
||||
if (indicatorSize > 0) {
|
||||
int dot = Math.max(1, Math.round(HEIGHT * indicatorSize / 100.0F));
|
||||
int gap = Math.max(1, dot / 3);
|
||||
int indicatorLeft = left + (WIDTH - dot * 2 - gap) / 2;
|
||||
int indicatorTop = top + HEIGHT + 2;
|
||||
guiGraphics.fill(indicatorLeft, indicatorTop, indicatorLeft + dot, indicatorTop + dot,
|
||||
blueAvailable ? 0xFF21A8FF : 0xFF33414A);
|
||||
int orangeLeft = indicatorLeft + dot + gap;
|
||||
guiGraphics.fill(orangeLeft, indicatorTop, orangeLeft + dot, indicatorTop + dot,
|
||||
orangeAvailable ? 0xFFFF8A24 : 0xFF4A4035);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<PortalKey> portalsFor(Minecraft minecraft, UUID ownerId, String channelName) {
|
||||
ClientLevel level = minecraft.level;
|
||||
long gameTime = level.getGameTime();
|
||||
if (cachedLevel != level || cachedGameTime != gameTime || !ownerId.equals(cachedOwnerId)) {
|
||||
Set<PortalKey> portals = new HashSet<>();
|
||||
if (minecraft.player != null) {
|
||||
AABB bounds = minecraft.player.getBoundingBox().inflate(128.0D);
|
||||
for (PortalGunPortalEntity portal : level.getEntitiesOfClass(PortalGunPortalEntity.class, bounds, Entity::isAlive)) {
|
||||
UUID portalOwnerId = portal.getOwnerId();
|
||||
String portalChannelName = portal.getChannelName();
|
||||
if (ownerId.equals(portalOwnerId) && portalChannelName != null && !portalChannelName.isEmpty()) {
|
||||
portals.add(new PortalKey(portalChannelName, portal.getPortalSide()));
|
||||
if (portal.getLinkedPortalId() != null) {
|
||||
portals.add(new PortalKey(portalChannelName, PortalGunPortalEntity.PortalSide.BLUE));
|
||||
portals.add(new PortalKey(portalChannelName, PortalGunPortalEntity.PortalSide.ORANGE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cachedLevel = level;
|
||||
cachedGameTime = gameTime;
|
||||
cachedOwnerId = ownerId;
|
||||
cachedPortals = Set.copyOf(portals);
|
||||
}
|
||||
if (channelName == null || channelName.isEmpty()) {
|
||||
return Set.of();
|
||||
}
|
||||
return cachedPortals;
|
||||
}
|
||||
|
||||
private record PortalKey(String channelName, PortalGunPortalEntity.PortalSide side) {
|
||||
}
|
||||
}
|
||||
-183
@@ -1,183 +0,0 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.mixins.client.SectionRenderDispatcherPortalUploadsAccessor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderBuffers;
|
||||
import net.minecraft.client.renderer.chunk.RenderRegionCache;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
|
||||
public final class PortalGunPortalRendererPool {
|
||||
private static final int MAX_RENDERERS = 8;
|
||||
private static final long PORTAL_SECTION_BUDGET_NANOS = 4_166_666L;
|
||||
private static final long PORTAL_UPLOAD_BUDGET_NANOS = 1_000_000L;
|
||||
private static final int MAX_PORTAL_UPLOADS_PER_FRAME = 16;
|
||||
private static final RenderBuffers PORTAL_RENDER_BUFFERS = new RenderBuffers(2);
|
||||
private static final LinkedHashMap<UUID, PortalRenderer> RENDERERS = new LinkedHashMap<>(8, 0.75F, true);
|
||||
private static final Set<LevelRenderer> PROXY_RENDERERS = java.util.Collections.newSetFromMap(new IdentityHashMap<>());
|
||||
private static final ThreadLocal<Long> SECTION_BUDGET_DEADLINE = ThreadLocal.withInitial(() -> 0L);
|
||||
private static final ThreadLocal<Integer> SCHEDULED_SECTION_REBUILDS = ThreadLocal.withInitial(() -> 0);
|
||||
private static final ThreadLocal<Boolean> SKIP_SET_NOT_DIRTY = ThreadLocal.withInitial(() -> false);
|
||||
private static final ThreadLocal<Integer> UPLOADED_THIS_FRAME = ThreadLocal.withInitial(() -> 0);
|
||||
private static ClientLevel ownerLevel;
|
||||
|
||||
private PortalGunPortalRendererPool() {
|
||||
}
|
||||
|
||||
public static LevelRenderer acquire(Minecraft minecraft, UUID destinationId, int width, int height) {
|
||||
if (ownerLevel != minecraft.level) {
|
||||
clear();
|
||||
ownerLevel = minecraft.level;
|
||||
}
|
||||
PortalRenderer state = RENDERERS.get(destinationId);
|
||||
if (state == null) {
|
||||
LevelRenderer renderer = new LevelRenderer(
|
||||
minecraft,
|
||||
minecraft.getEntityRenderDispatcher(),
|
||||
minecraft.getBlockEntityRenderDispatcher(),
|
||||
PORTAL_RENDER_BUFFERS
|
||||
);
|
||||
PROXY_RENDERERS.add(renderer);
|
||||
renderer.setLevel(minecraft.level);
|
||||
renderer.resize(width, height);
|
||||
state = new PortalRenderer(renderer, width, height);
|
||||
RENDERERS.put(destinationId, state);
|
||||
trim();
|
||||
} else if (state.width() != width || state.height() != height) {
|
||||
state.renderer().resize(width, height);
|
||||
RENDERERS.put(destinationId, new PortalRenderer(state.renderer(), width, height));
|
||||
}
|
||||
return state.renderer();
|
||||
}
|
||||
|
||||
public static boolean isProxy(LevelRenderer renderer) {
|
||||
return PROXY_RENDERERS.contains(renderer);
|
||||
}
|
||||
|
||||
public static net.minecraft.client.renderer.MultiBufferSource.BufferSource bufferSource() {
|
||||
return PORTAL_RENDER_BUFFERS.bufferSource();
|
||||
}
|
||||
|
||||
public static void beginFrame() {
|
||||
SECTION_BUDGET_DEADLINE.set(System.nanoTime() + PORTAL_SECTION_BUDGET_NANOS);
|
||||
SCHEDULED_SECTION_REBUILDS.set(0);
|
||||
SKIP_SET_NOT_DIRTY.set(false);
|
||||
UPLOADED_THIS_FRAME.set(0);
|
||||
}
|
||||
|
||||
public static void uploadPending(LevelRenderer renderer, SectionRenderDispatcher dispatcher) {
|
||||
if (!isProxy(renderer)) {
|
||||
dispatcher.uploadAllPendingUploads();
|
||||
return;
|
||||
}
|
||||
java.util.Queue<Runnable> uploads = ((SectionRenderDispatcherPortalUploadsAccessor) dispatcher).antarchy$getToUpload();
|
||||
long deadline = System.nanoTime() + PORTAL_UPLOAD_BUDGET_NANOS;
|
||||
int uploaded = UPLOADED_THIS_FRAME.get();
|
||||
while (uploaded < MAX_PORTAL_UPLOADS_PER_FRAME) {
|
||||
if (uploaded > 0 && System.nanoTime() >= deadline) {
|
||||
break;
|
||||
}
|
||||
Runnable upload = uploads.poll();
|
||||
if (upload == null) {
|
||||
break;
|
||||
}
|
||||
upload.run();
|
||||
uploaded++;
|
||||
}
|
||||
UPLOADED_THIS_FRAME.set(uploaded);
|
||||
}
|
||||
|
||||
public static int scheduledSectionRebuilds() {
|
||||
return SCHEDULED_SECTION_REBUILDS.get();
|
||||
}
|
||||
|
||||
public static int uploadedThisFrame() {
|
||||
return UPLOADED_THIS_FRAME.get();
|
||||
}
|
||||
|
||||
public static long remainingSectionBudgetNanos() {
|
||||
return Math.max(0L, SECTION_BUDGET_DEADLINE.get() - System.nanoTime());
|
||||
}
|
||||
|
||||
public static void rebuildSection(LevelRenderer renderer, SectionRenderDispatcher dispatcher, SectionRenderDispatcher.RenderSection section, RenderRegionCache cache) {
|
||||
if (!isProxy(renderer)) {
|
||||
dispatcher.rebuildSectionSync(section, cache);
|
||||
SKIP_SET_NOT_DIRTY.set(false);
|
||||
return;
|
||||
}
|
||||
if (remainingSectionBudgetNanos() <= 0L) {
|
||||
SKIP_SET_NOT_DIRTY.set(true);
|
||||
return;
|
||||
}
|
||||
section.rebuildSectionAsync(dispatcher, cache);
|
||||
SCHEDULED_SECTION_REBUILDS.set(SCHEDULED_SECTION_REBUILDS.get() + 1);
|
||||
SKIP_SET_NOT_DIRTY.set(false);
|
||||
}
|
||||
|
||||
public static void rebuildSectionAsync(LevelRenderer renderer, SectionRenderDispatcher dispatcher, SectionRenderDispatcher.RenderSection section, RenderRegionCache cache) {
|
||||
if (!isProxy(renderer)) {
|
||||
section.rebuildSectionAsync(dispatcher, cache);
|
||||
SKIP_SET_NOT_DIRTY.set(false);
|
||||
return;
|
||||
}
|
||||
if (remainingSectionBudgetNanos() <= 0L) {
|
||||
SKIP_SET_NOT_DIRTY.set(true);
|
||||
return;
|
||||
}
|
||||
section.rebuildSectionAsync(dispatcher, cache);
|
||||
SCHEDULED_SECTION_REBUILDS.set(SCHEDULED_SECTION_REBUILDS.get() + 1);
|
||||
SKIP_SET_NOT_DIRTY.set(false);
|
||||
}
|
||||
|
||||
public static void setNotDirty(SectionRenderDispatcher.RenderSection section) {
|
||||
boolean leaveDirty = SKIP_SET_NOT_DIRTY.get();
|
||||
SKIP_SET_NOT_DIRTY.set(false);
|
||||
if (!leaveDirty) {
|
||||
section.setNotDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
for (PortalRenderer state : new ArrayList<>(RENDERERS.values())) {
|
||||
LevelRenderer renderer = state.renderer();
|
||||
PortalGunPortalViewAreaManager.releaseRenderer(renderer);
|
||||
try {
|
||||
renderer.close();
|
||||
} finally {
|
||||
PROXY_RENDERERS.remove(renderer);
|
||||
}
|
||||
}
|
||||
RENDERERS.clear();
|
||||
ownerLevel = null;
|
||||
SECTION_BUDGET_DEADLINE.remove();
|
||||
SCHEDULED_SECTION_REBUILDS.remove();
|
||||
SKIP_SET_NOT_DIRTY.remove();
|
||||
UPLOADED_THIS_FRAME.remove();
|
||||
}
|
||||
|
||||
private static void trim() {
|
||||
Iterator<Map.Entry<UUID, PortalRenderer>> iterator = RENDERERS.entrySet().iterator();
|
||||
while (RENDERERS.size() > MAX_RENDERERS && iterator.hasNext()) {
|
||||
PortalRenderer state = iterator.next().getValue();
|
||||
iterator.remove();
|
||||
LevelRenderer renderer = state.renderer();
|
||||
PortalGunPortalViewAreaManager.releaseRenderer(renderer);
|
||||
try {
|
||||
renderer.close();
|
||||
} finally {
|
||||
PROXY_RENDERERS.remove(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record PortalRenderer(LevelRenderer renderer, int width, int height) {
|
||||
}
|
||||
}
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
|
||||
import com.craisinlord.antarchy.mixins.client.LevelRendererPortalSceneInvoker;
|
||||
import com.craisinlord.antarchy.mixins.client.LevelRendererPortalViewAreaAccessor;
|
||||
import com.mojang.blaze3d.platform.Lighting;
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferUploader;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.MeshData;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexSorting;
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderBuffers;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fStack;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public final class PortalGunPortalSceneRenderer {
|
||||
private static RenderBuffers portalBuffers;
|
||||
private static boolean renderingScene;
|
||||
|
||||
private PortalGunPortalSceneRenderer() {
|
||||
}
|
||||
|
||||
public static MultiBufferSource.BufferSource bufferSource() {
|
||||
if (portalBuffers == null) {
|
||||
portalBuffers = new RenderBuffers(1);
|
||||
}
|
||||
return portalBuffers.bufferSource();
|
||||
}
|
||||
|
||||
public static boolean isRenderingScene() {
|
||||
return renderingScene;
|
||||
}
|
||||
|
||||
public static void render(Minecraft minecraft, Camera camera, float partialTick, Matrix4f viewMatrix,
|
||||
Matrix4f projection, Matrix4f skyProjection, Frustum frustum,
|
||||
PortalTerrain terrain, Consumer<PoseStack> crossingEntities, String tracePair) {
|
||||
LevelRenderer renderer = minecraft.levelRenderer;
|
||||
LevelRendererPortalViewAreaAccessor state = (LevelRendererPortalViewAreaAccessor) renderer;
|
||||
LevelRendererPortalSceneInvoker scene = (LevelRendererPortalSceneInvoker) renderer;
|
||||
Vec3 cameraPosition = camera.getPosition();
|
||||
double cameraX = cameraPosition.x;
|
||||
double cameraY = cameraPosition.y;
|
||||
double cameraZ = cameraPosition.z;
|
||||
|
||||
int previousRainSoundTime = state.antarchy$getRainSoundTime();
|
||||
Matrix4fStack modelViewStack = RenderSystem.getModelViewStack();
|
||||
Matrix4f previousProjection = new Matrix4f(RenderSystem.getProjectionMatrix());
|
||||
VertexSorting previousSorting = RenderSystem.getVertexSorting();
|
||||
float previousFogStart = RenderSystem.getShaderFogStart();
|
||||
float previousFogEnd = RenderSystem.getShaderFogEnd();
|
||||
float[] previousFogColor = RenderSystem.getShaderFogColor().clone();
|
||||
FogShape previousFogShape = RenderSystem.getShaderFogShape();
|
||||
Camera previousBlockEntityCamera = minecraft.getBlockEntityRenderDispatcher().camera;
|
||||
modelViewStack.pushMatrix();
|
||||
modelViewStack.identity();
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
renderingScene = true;
|
||||
terrain.begin(minecraft);
|
||||
try {
|
||||
float renderDistance = minecraft.gameRenderer.getRenderDistance();
|
||||
BlockPos cameraBlockPos = BlockPos.containing(cameraX, cameraY, cameraZ);
|
||||
boolean foggy = minecraft.level.effects().isFoggyAt(cameraBlockPos.getX(), cameraBlockPos.getY())
|
||||
|| minecraft.gui.getBossOverlay().shouldCreateWorldFog();
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "background-and-sky", "sections=" + terrain.sectionCount())) {
|
||||
RenderSystem.setShaderGameTime(minecraft.level.getGameTime(), partialTick);
|
||||
minecraft.getBlockEntityRenderDispatcher().prepare(minecraft.level, camera, minecraft.hitResult);
|
||||
minecraft.getEntityRenderDispatcher().prepare(minecraft.level, camera, minecraft.crosshairPickEntity);
|
||||
FogRenderer.setupColor(camera, partialTick, minecraft.level, minecraft.options.getEffectiveRenderDistance(),
|
||||
minecraft.gameRenderer.getDarkenWorldAmount(partialTick));
|
||||
FogRenderer.levelFogColor();
|
||||
fillBackground(RenderSystem.getShaderFogColor());
|
||||
RenderSystem.setProjectionMatrix(skyProjection, VertexSorting.DISTANCE_TO_ORIGIN);
|
||||
FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_SKY, renderDistance, foggy, partialTick);
|
||||
RenderSystem.setShader(GameRenderer::getPositionShader);
|
||||
renderer.renderSky(viewMatrix, skyProjection, partialTick, camera, foggy,
|
||||
() -> FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_SKY, renderDistance, foggy, partialTick));
|
||||
}
|
||||
|
||||
RenderSystem.setProjectionMatrix(projection, VertexSorting.DISTANCE_TO_ORIGIN);
|
||||
FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_TERRAIN, Math.max(renderDistance, 32.0F), foggy, partialTick);
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "opaque-terrain", "sections=" + terrain.sectionCount())) {
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.depthMask(true);
|
||||
terrain.drawLayer(minecraft, RenderType.solid(), cameraPosition, viewMatrix, projection);
|
||||
terrain.drawLayer(minecraft, RenderType.cutoutMipped(), cameraPosition, viewMatrix, projection);
|
||||
terrain.drawLayer(minecraft, RenderType.cutout(), cameraPosition, viewMatrix, projection);
|
||||
}
|
||||
|
||||
if (minecraft.level.effects().constantAmbientLight()) {
|
||||
Lighting.setupNetherLevel();
|
||||
} else {
|
||||
Lighting.setupLevel();
|
||||
}
|
||||
modelViewStack.pushMatrix();
|
||||
modelViewStack.mul(viewMatrix);
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
PoseStack poseStack = new PoseStack();
|
||||
MultiBufferSource.BufferSource buffers = bufferSource();
|
||||
try {
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "entities", "rendering")) {
|
||||
for (Entity entity : minecraft.level.entitiesForRendering()) {
|
||||
if (!minecraft.getEntityRenderDispatcher().shouldRender(entity, frustum, cameraX, cameraY, cameraZ)
|
||||
&& !entity.hasIndirectPassenger(minecraft.player)) {
|
||||
continue;
|
||||
}
|
||||
if (entity instanceof PortalGunPortalEntity portal && !portal.shouldRenderFront(cameraPosition)) {
|
||||
continue;
|
||||
}
|
||||
if (entity == camera.getEntity()
|
||||
&& entity.getBoundingBox().inflate(0.1D).contains(cameraPosition)
|
||||
&& (!(entity instanceof LivingEntity living) || !living.isSleeping())) {
|
||||
continue;
|
||||
}
|
||||
scene.antarchy$renderPortalEntity(entity, cameraX, cameraY, cameraZ, partialTick, poseStack, buffers);
|
||||
}
|
||||
crossingEntities.accept(poseStack);
|
||||
}
|
||||
buffers.endBatch();
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "block-entities", "rendering")) {
|
||||
terrain.forEachBlockEntity(minecraft, frustum, blockEntity ->
|
||||
renderBlockEntity(minecraft, blockEntity, cameraX, cameraY, cameraZ, partialTick, poseStack, buffers));
|
||||
}
|
||||
buffers.endBatch();
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "translucent-and-particles", "rendering")) {
|
||||
terrain.drawLayer(minecraft, RenderType.translucent(), cameraPosition, viewMatrix, projection);
|
||||
buffers.endBatch();
|
||||
terrain.drawLayer(minecraft, RenderType.tripwire(), cameraPosition, viewMatrix, projection);
|
||||
minecraft.particleEngine.render(minecraft.gameRenderer.lightTexture(), camera, partialTick);
|
||||
}
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "weather-and-border", "rendering")) {
|
||||
RenderSystem.depthMask(false);
|
||||
scene.antarchy$renderPortalWeather(minecraft.gameRenderer.lightTexture(), partialTick, cameraX, cameraY, cameraZ);
|
||||
scene.antarchy$renderPortalWorldBorder(camera);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
buffers.endBatch();
|
||||
} finally {
|
||||
modelViewStack.popMatrix();
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
renderingScene = false;
|
||||
terrain.end(minecraft);
|
||||
state.antarchy$setRainSoundTime(previousRainSoundTime);
|
||||
modelViewStack.popMatrix();
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
RenderSystem.setProjectionMatrix(previousProjection, previousSorting);
|
||||
RenderSystem.setShaderFogStart(previousFogStart);
|
||||
RenderSystem.setShaderFogEnd(previousFogEnd);
|
||||
RenderSystem.setShaderFogColor(previousFogColor[0], previousFogColor[1], previousFogColor[2], previousFogColor[3]);
|
||||
RenderSystem.setShaderFogShape(previousFogShape);
|
||||
if (previousBlockEntityCamera != null) {
|
||||
minecraft.getBlockEntityRenderDispatcher().prepare(minecraft.level, previousBlockEntityCamera, minecraft.hitResult);
|
||||
}
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.enableCull();
|
||||
RenderSystem.disableBlend();
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
private static void fillBackground(float[] fogColor) {
|
||||
int previousDepthFunction = GL11.glGetInteger(GL11.GL_DEPTH_FUNC);
|
||||
Matrix4f previousProjection = new Matrix4f(RenderSystem.getProjectionMatrix());
|
||||
VertexSorting previousSorting = RenderSystem.getVertexSorting();
|
||||
BufferBuilder buffer = Tesselator.getInstance().begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION);
|
||||
buffer.addVertex(-1.0F, -1.0F, 0.99999F);
|
||||
buffer.addVertex(3.0F, -1.0F, 0.99999F);
|
||||
buffer.addVertex(-1.0F, 3.0F, 0.99999F);
|
||||
MeshData mesh = buffer.build();
|
||||
try {
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.disableBlend();
|
||||
RenderSystem.disableCull();
|
||||
GL11.glDepthFunc(GL11.GL_ALWAYS);
|
||||
RenderSystem.setProjectionMatrix(new Matrix4f(), previousSorting);
|
||||
RenderSystem.setShader(GameRenderer::getPositionShader);
|
||||
RenderSystem.setShaderColor(fogColor[0], fogColor[1], fogColor[2], 1.0F);
|
||||
if (mesh != null) {
|
||||
BufferUploader.drawWithShader(mesh);
|
||||
}
|
||||
} finally {
|
||||
GL11.glDepthFunc(previousDepthFunction);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.setProjectionMatrix(previousProjection, previousSorting);
|
||||
RenderSystem.enableCull();
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderBlockEntity(Minecraft minecraft, BlockEntity blockEntity, double cameraX, double cameraY, double cameraZ,
|
||||
float partialTick, PoseStack poseStack, MultiBufferSource.BufferSource buffers) {
|
||||
if (!blockEntity.hasLevel() || !blockEntity.getType().isValid(blockEntity.getBlockState())) {
|
||||
return;
|
||||
}
|
||||
BlockPos pos = blockEntity.getBlockPos();
|
||||
poseStack.pushPose();
|
||||
try {
|
||||
poseStack.translate(pos.getX() - cameraX, pos.getY() - cameraY, pos.getZ() - cameraZ);
|
||||
minecraft.getBlockEntityRenderDispatcher().render(blockEntity, partialTick, poseStack, buffers);
|
||||
} finally {
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.mixins.client.LevelRendererPortalViewAreaAccessor;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.SectionOcclusionGraph;
|
||||
import net.minecraft.client.renderer.ViewArea;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
public final class PortalGunPortalSectionViews {
|
||||
private static final int MAX_VIEWS = 8;
|
||||
private static final double SEED_OFFSET = 0.5D;
|
||||
private static final LinkedHashMap<UUID, View> VIEWS = new LinkedHashMap<>(8, 0.75F, true);
|
||||
private static volatile SectionOcclusionGraph[] graphs = new SectionOcclusionGraph[0];
|
||||
private static ViewArea ownerArea;
|
||||
private static int mainSectionX = Integer.MIN_VALUE;
|
||||
private static int mainSectionY = Integer.MIN_VALUE;
|
||||
private static int mainSectionZ = Integer.MIN_VALUE;
|
||||
|
||||
private PortalGunPortalSectionViews() {
|
||||
}
|
||||
|
||||
public static boolean canView(Minecraft minecraft, Vec3 exitCenter) {
|
||||
ViewArea area = ((LevelRendererPortalViewAreaAccessor) minecraft.levelRenderer).antarchy$getViewArea();
|
||||
if (area == null) {
|
||||
return false;
|
||||
}
|
||||
LevelRendererPortalViewAreaAccessor accessor = (LevelRendererPortalViewAreaAccessor) minecraft.levelRenderer;
|
||||
int limit = area.getViewDistance() - 1;
|
||||
return Math.abs(SectionPos.posToSectionCoord(exitCenter.x) - accessor.antarchy$getLastCameraSectionX()) <= limit
|
||||
&& Math.abs(SectionPos.posToSectionCoord(exitCenter.z) - accessor.antarchy$getLastCameraSectionZ()) <= limit;
|
||||
}
|
||||
|
||||
public static View prepare(Minecraft minecraft, UUID exitId, Vec3 exitCenter, Vec3 exitNormal, Frustum frustum) {
|
||||
LevelRendererPortalViewAreaAccessor accessor = (LevelRendererPortalViewAreaAccessor) minecraft.levelRenderer;
|
||||
ViewArea area = accessor.antarchy$getViewArea();
|
||||
if (area != ownerArea) {
|
||||
clear();
|
||||
ownerArea = area;
|
||||
}
|
||||
int sectionX = accessor.antarchy$getLastCameraSectionX();
|
||||
int sectionY = accessor.antarchy$getLastCameraSectionY();
|
||||
int sectionZ = accessor.antarchy$getLastCameraSectionZ();
|
||||
if (sectionX != mainSectionX || sectionY != mainSectionY || sectionZ != mainSectionZ) {
|
||||
mainSectionX = sectionX;
|
||||
mainSectionY = sectionY;
|
||||
mainSectionZ = sectionZ;
|
||||
for (View view : VIEWS.values()) {
|
||||
view.graph.invalidate();
|
||||
}
|
||||
}
|
||||
View view = VIEWS.get(exitId);
|
||||
if (view == null) {
|
||||
view = new View(area);
|
||||
VIEWS.put(exitId, view);
|
||||
trim();
|
||||
publishGraphs();
|
||||
}
|
||||
Vec3 seed = exitCenter.add(exitNormal.normalize().scale(SEED_OFFSET));
|
||||
if (!seed.equals(view.seed)) {
|
||||
view.seed = seed;
|
||||
view.seedCamera = new SeedCamera(seed);
|
||||
view.updateFrustum = centredFrustum(seed);
|
||||
view.graph.invalidate();
|
||||
}
|
||||
view.partialUpdates.clear();
|
||||
view.graph.update(minecraft.smartCull, view.seedCamera, view.updateFrustum(), view.partialUpdates);
|
||||
view.visibleSections.clear();
|
||||
view.graph.addSectionsInFrustum(frustum, view.visibleSections);
|
||||
return view;
|
||||
}
|
||||
|
||||
public static void onSectionCompiled(SectionRenderDispatcher.RenderSection section) {
|
||||
for (SectionOcclusionGraph graph : graphs) {
|
||||
graph.onSectionCompiled(section);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onChunkLoaded(ChunkPos pos) {
|
||||
for (SectionOcclusionGraph graph : graphs) {
|
||||
graph.onChunkLoaded(pos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onChunkDropped(ChunkPos pos) {
|
||||
for (SectionOcclusionGraph graph : graphs) {
|
||||
graph.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
for (View view : VIEWS.values()) {
|
||||
view.release();
|
||||
}
|
||||
VIEWS.clear();
|
||||
publishGraphs();
|
||||
ownerArea = null;
|
||||
mainSectionX = Integer.MIN_VALUE;
|
||||
mainSectionY = Integer.MIN_VALUE;
|
||||
mainSectionZ = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
private static void publishGraphs() {
|
||||
graphs = VIEWS.values().stream().map(view -> view.graph).toArray(SectionOcclusionGraph[]::new);
|
||||
}
|
||||
|
||||
private static void trim() {
|
||||
Iterator<Map.Entry<UUID, View>> iterator = VIEWS.entrySet().iterator();
|
||||
while (VIEWS.size() > MAX_VIEWS && iterator.hasNext()) {
|
||||
View view = iterator.next().getValue();
|
||||
iterator.remove();
|
||||
view.release();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class View {
|
||||
private final SectionOcclusionGraph graph = new SectionOcclusionGraph();
|
||||
private final List<SectionRenderDispatcher.RenderSection> partialUpdates = new ArrayList<>();
|
||||
private final ObjectArrayList<SectionRenderDispatcher.RenderSection> visibleSections = new ObjectArrayList<>();
|
||||
private Vec3 seed;
|
||||
private Camera seedCamera;
|
||||
private Frustum updateFrustum;
|
||||
|
||||
private View(ViewArea area) {
|
||||
((PortalSectionGraphMarker) this.graph).antarchy$markPortalGraph();
|
||||
this.graph.waitAndReset(area);
|
||||
}
|
||||
|
||||
public ObjectArrayList<SectionRenderDispatcher.RenderSection> visibleSections() {
|
||||
return this.visibleSections;
|
||||
}
|
||||
|
||||
private Frustum updateFrustum() {
|
||||
return this.updateFrustum;
|
||||
}
|
||||
|
||||
private void release() {
|
||||
this.graph.waitAndReset(null);
|
||||
}
|
||||
}
|
||||
|
||||
private static Frustum centredFrustum(Vec3 position) {
|
||||
Frustum frustum = new Frustum(new Matrix4f(), new Matrix4f().setPerspective((float) Math.toRadians(90.0D), 1.0F, 0.05F, 1024.0F));
|
||||
frustum.prepare(position.x, position.y, position.z);
|
||||
return frustum;
|
||||
}
|
||||
|
||||
private static final class SeedCamera extends Camera {
|
||||
private SeedCamera(Vec3 position) {
|
||||
this.setPosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
-386
@@ -1,386 +0,0 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.mixins.client.LevelRendererPortalViewAreaAccessor;
|
||||
import com.mojang.blaze3d.vertex.VertexBuffer;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.client.CloudStatus;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.SectionOcclusionGraph;
|
||||
import net.minecraft.client.renderer.ViewArea;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public final class PortalGunPortalViewAreaManager {
|
||||
private static final int MAX_VIEW_AREAS = 8;
|
||||
private static final LinkedHashMap<ViewKey, ViewState> VIEW_AREAS = new LinkedHashMap<>(8, 0.75F, true);
|
||||
private static final Map<SectionRenderDispatcher.RenderSection, ViewState> SECTION_OWNERS = Collections.synchronizedMap(new IdentityHashMap<>());
|
||||
private static ClientLevel ownerLevel;
|
||||
private static int ownerViewDistance = -1;
|
||||
|
||||
private PortalGunPortalViewAreaManager() {
|
||||
}
|
||||
|
||||
public static Scope enter(Minecraft minecraft, LevelRenderer renderer, UUID destinationId, Vec3 cameraPos, net.minecraft.client.Camera portalCamera) {
|
||||
if (SodiumCompat.isLoaded()) {
|
||||
return new SodiumScope(SodiumCompat.beginPortalView());
|
||||
}
|
||||
LevelRendererPortalViewAreaAccessor accessor = (LevelRendererPortalViewAreaAccessor) renderer;
|
||||
int viewDistance = minecraft.options.getEffectiveRenderDistance();
|
||||
if (ownerLevel != minecraft.level || ownerViewDistance != viewDistance) {
|
||||
clear();
|
||||
ownerLevel = minecraft.level;
|
||||
ownerViewDistance = viewDistance;
|
||||
}
|
||||
ViewKey viewKey = new ViewKey(renderer, destinationId);
|
||||
ViewState state = VIEW_AREAS.get(viewKey);
|
||||
if (state == null) {
|
||||
ViewArea area = accessor.antarchy$getViewArea();
|
||||
SectionOcclusionGraph graph = accessor.antarchy$getSectionOcclusionGraph();
|
||||
ObjectArrayList<SectionRenderDispatcher.RenderSection> sections = accessor.antarchy$getVisibleSections();
|
||||
state = new ViewState(area, graph, sections, accessor.antarchy$getGlobalBlockEntities());
|
||||
state.cloudBuffer = accessor.antarchy$getCloudBuffer();
|
||||
state.generateClouds = accessor.antarchy$getGenerateClouds();
|
||||
state.prevCloudX = accessor.antarchy$getPrevCloudX();
|
||||
state.prevCloudY = accessor.antarchy$getPrevCloudY();
|
||||
state.prevCloudZ = accessor.antarchy$getPrevCloudZ();
|
||||
state.prevCloudColor = accessor.antarchy$getPrevCloudColor();
|
||||
state.prevCloudsType = accessor.antarchy$getPrevCloudsType();
|
||||
for (SectionRenderDispatcher.RenderSection section : area.sections) {
|
||||
((PortalViewSectionMarker) section).antarchy$markPortalViewSection();
|
||||
SECTION_OWNERS.put(section, state);
|
||||
}
|
||||
VIEW_AREAS.put(viewKey, state);
|
||||
trimOldViews();
|
||||
}
|
||||
state.area.repositionCamera(cameraPos.x, cameraPos.z);
|
||||
int sectionX = SectionPos.posToSectionCoord(cameraPos.x);
|
||||
int sectionY = SectionPos.posToSectionCoord(cameraPos.y);
|
||||
int sectionZ = SectionPos.posToSectionCoord(cameraPos.z);
|
||||
state.cameraPos = cameraPos;
|
||||
state.lastSectionX = sectionX;
|
||||
state.lastSectionY = sectionY;
|
||||
state.lastSectionZ = sectionZ;
|
||||
Scope scope = new VanillaScope(renderer, accessor, state, minecraft.getBlockEntityRenderDispatcher());
|
||||
accessor.antarchy$setViewArea(state.area);
|
||||
accessor.antarchy$setSectionOcclusionGraph(state.graph);
|
||||
accessor.antarchy$setVisibleSections(state.visibleSections);
|
||||
accessor.antarchy$setGlobalBlockEntities(state.globalBlockEntities);
|
||||
accessor.antarchy$setLastCameraSectionX(sectionX);
|
||||
accessor.antarchy$setLastCameraSectionY(sectionY);
|
||||
accessor.antarchy$setLastCameraSectionZ(sectionZ);
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static boolean routeSectionCompiled(SectionRenderDispatcher.RenderSection section) {
|
||||
ViewState state = SECTION_OWNERS.get(section);
|
||||
if (state == null) {
|
||||
return ((PortalViewSectionMarker) section).antarchy$isPortalViewSection();
|
||||
}
|
||||
state.graph.onSectionCompiled(section);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Vec3 cameraForSection(SectionRenderDispatcher.RenderSection section, Vec3 fallback) {
|
||||
ViewState state = SECTION_OWNERS.get(section);
|
||||
return state == null || state.cameraPos == null ? fallback : state.cameraPos;
|
||||
}
|
||||
|
||||
public static boolean updateGlobalBlockEntities(SectionRenderDispatcher.RenderSection section, Iterable<BlockEntity> removed, Iterable<BlockEntity> added) {
|
||||
ViewState state = SECTION_OWNERS.get(section);
|
||||
if (state == null) {
|
||||
return ((PortalViewSectionMarker) section).antarchy$isPortalViewSection();
|
||||
}
|
||||
synchronized (state.globalBlockEntities) {
|
||||
for (BlockEntity blockEntity : removed) {
|
||||
state.globalBlockEntities.remove(blockEntity);
|
||||
}
|
||||
for (BlockEntity blockEntity : added) {
|
||||
state.globalBlockEntities.add(blockEntity);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void onSectionDirty(int sectionX, int sectionY, int sectionZ, boolean playerChanged) {
|
||||
for (ViewState state : VIEW_AREAS.values()) {
|
||||
int sectionRange = state.area.getViewDistance() + 1;
|
||||
if (Math.abs((long) sectionX - state.lastSectionX) > sectionRange
|
||||
|| Math.abs((long) sectionZ - state.lastSectionZ) > sectionRange
|
||||
|| sectionY < ownerLevel.getMinSection()
|
||||
|| sectionY > ownerLevel.getMaxSection()) {
|
||||
continue;
|
||||
}
|
||||
state.area.setDirty(sectionX, sectionY, sectionZ, playerChanged);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onChunkLoaded(net.minecraft.world.level.ChunkPos pos) {
|
||||
for (ViewState state : VIEW_AREAS.values()) {
|
||||
state.graph.onChunkLoaded(pos);
|
||||
markChunkDirty(state, pos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onChunkDropped(net.minecraft.world.level.ChunkPos pos) {
|
||||
for (ViewState state : VIEW_AREAS.values()) {
|
||||
markChunkDirty(state, pos);
|
||||
state.graph.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private static void markChunkDirty(ViewState state, net.minecraft.world.level.ChunkPos pos) {
|
||||
int sectionRange = state.area.getViewDistance() + 1;
|
||||
if (Math.abs((long) pos.x - state.lastSectionX) <= sectionRange
|
||||
&& Math.abs((long) pos.z - state.lastSectionZ) <= sectionRange) {
|
||||
for (int sectionY = ownerLevel.getMinSection(); sectionY <= ownerLevel.getMaxSection(); sectionY++) {
|
||||
state.area.setDirty(pos.x, sectionY, pos.z, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
SodiumCompat.clear();
|
||||
for (ViewState state : VIEW_AREAS.values()) {
|
||||
state.graph.waitAndReset(state.area);
|
||||
}
|
||||
VIEW_AREAS.clear();
|
||||
SECTION_OWNERS.clear();
|
||||
ownerLevel = null;
|
||||
ownerViewDistance = -1;
|
||||
}
|
||||
|
||||
public static void releaseRenderer(LevelRenderer renderer) {
|
||||
Iterator<Map.Entry<ViewKey, ViewState>> iterator = VIEW_AREAS.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<ViewKey, ViewState> entry = iterator.next();
|
||||
if (entry.getKey().renderer() == renderer) {
|
||||
ViewState state = entry.getValue();
|
||||
state.graph.waitAndReset(state.area);
|
||||
removeOwners(state);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void trimOldViews() {
|
||||
Iterator<Map.Entry<ViewKey, ViewState>> iterator = VIEW_AREAS.entrySet().iterator();
|
||||
while (VIEW_AREAS.size() > MAX_VIEW_AREAS && iterator.hasNext()) {
|
||||
ViewState state = iterator.next().getValue();
|
||||
iterator.remove();
|
||||
state.graph.waitAndReset(state.area);
|
||||
removeOwners(state);
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeOwners(ViewState state) {
|
||||
for (SectionRenderDispatcher.RenderSection section : state.area.sections) {
|
||||
SECTION_OWNERS.remove(section);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ViewState {
|
||||
private final ViewArea area;
|
||||
private final SectionOcclusionGraph graph;
|
||||
private final ObjectArrayList<SectionRenderDispatcher.RenderSection> visibleSections;
|
||||
private final Set<BlockEntity> globalBlockEntities;
|
||||
private VertexBuffer cloudBuffer;
|
||||
private boolean generateClouds = true;
|
||||
private int prevCloudX = Integer.MIN_VALUE;
|
||||
private int prevCloudY = Integer.MIN_VALUE;
|
||||
private int prevCloudZ = Integer.MIN_VALUE;
|
||||
private Vec3 prevCloudColor = Vec3.ZERO;
|
||||
private CloudStatus prevCloudsType;
|
||||
private int lastSectionX;
|
||||
private int lastSectionY;
|
||||
private int lastSectionZ;
|
||||
private volatile Vec3 cameraPos;
|
||||
private double transparentSortX = Double.NaN;
|
||||
private double transparentSortY = Double.NaN;
|
||||
private double transparentSortZ = Double.NaN;
|
||||
private double prevCamX = Double.NaN;
|
||||
private double prevCamY = Double.NaN;
|
||||
private double prevCamZ = Double.NaN;
|
||||
private double prevCamRotX = Double.NaN;
|
||||
private double prevCamRotY = Double.NaN;
|
||||
|
||||
private ViewState(ViewArea area, SectionOcclusionGraph graph, ObjectArrayList<SectionRenderDispatcher.RenderSection> visibleSections, Set<BlockEntity> globalBlockEntities) {
|
||||
this.area = area;
|
||||
this.graph = graph;
|
||||
this.visibleSections = visibleSections;
|
||||
this.globalBlockEntities = globalBlockEntities;
|
||||
}
|
||||
}
|
||||
|
||||
private record ViewKey(LevelRenderer renderer, UUID destinationId) {
|
||||
}
|
||||
|
||||
public interface Scope extends AutoCloseable {
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
|
||||
private static final class SodiumScope implements Scope {
|
||||
private final SodiumCompat.TerrainScope terrainScope;
|
||||
|
||||
private SodiumScope(SodiumCompat.TerrainScope terrainScope) {
|
||||
this.terrainScope = terrainScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
terrainScope.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class VanillaScope implements Scope {
|
||||
private final LevelRendererPortalViewAreaAccessor accessor;
|
||||
private final ViewArea previousArea;
|
||||
private final SectionOcclusionGraph previousGraph;
|
||||
private final ObjectArrayList<SectionRenderDispatcher.RenderSection> previousVisibleSections;
|
||||
private final Set<BlockEntity> previousGlobalBlockEntities;
|
||||
private final VertexBuffer previousCloudBuffer;
|
||||
private final boolean previousGenerateClouds;
|
||||
private final int previousCloudX;
|
||||
private final int previousCloudY;
|
||||
private final int previousCloudZ;
|
||||
private final Vec3 previousCloudColor;
|
||||
private final CloudStatus previousCloudsType;
|
||||
private final int previousRainSoundTime;
|
||||
private final int previousSectionX;
|
||||
private final int previousSectionY;
|
||||
private final int previousSectionZ;
|
||||
private final double previousPrevCamX;
|
||||
private final double previousPrevCamY;
|
||||
private final double previousPrevCamZ;
|
||||
private final double previousPrevCamRotX;
|
||||
private final double previousPrevCamRotY;
|
||||
private final double previousTransparentSortX;
|
||||
private final double previousTransparentSortY;
|
||||
private final double previousTransparentSortZ;
|
||||
private final Vec3 previousDispatcherCamera;
|
||||
private final SectionRenderDispatcher dispatcher;
|
||||
private final BlockEntityRenderDispatcher blockEntityDispatcher;
|
||||
private final Level previousBlockEntityLevel;
|
||||
private final net.minecraft.client.Camera previousBlockEntityCamera;
|
||||
private final HitResult previousBlockEntityHitResult;
|
||||
private final ViewState state;
|
||||
private boolean closed;
|
||||
|
||||
private VanillaScope(LevelRenderer renderer, LevelRendererPortalViewAreaAccessor accessor, ViewState state, BlockEntityRenderDispatcher blockEntityDispatcher) {
|
||||
this.accessor = accessor;
|
||||
this.state = state;
|
||||
this.blockEntityDispatcher = blockEntityDispatcher;
|
||||
this.previousBlockEntityLevel = blockEntityDispatcher.level;
|
||||
this.previousBlockEntityCamera = blockEntityDispatcher.camera;
|
||||
this.previousBlockEntityHitResult = blockEntityDispatcher.cameraHitResult;
|
||||
this.previousArea = accessor.antarchy$getViewArea();
|
||||
this.previousGraph = accessor.antarchy$getSectionOcclusionGraph();
|
||||
this.previousVisibleSections = accessor.antarchy$getVisibleSections();
|
||||
this.previousGlobalBlockEntities = accessor.antarchy$getGlobalBlockEntities();
|
||||
this.previousCloudBuffer = accessor.antarchy$getCloudBuffer();
|
||||
this.previousGenerateClouds = accessor.antarchy$getGenerateClouds();
|
||||
this.previousCloudX = accessor.antarchy$getPrevCloudX();
|
||||
this.previousCloudY = accessor.antarchy$getPrevCloudY();
|
||||
this.previousCloudZ = accessor.antarchy$getPrevCloudZ();
|
||||
this.previousCloudColor = accessor.antarchy$getPrevCloudColor();
|
||||
this.previousCloudsType = accessor.antarchy$getPrevCloudsType();
|
||||
this.previousRainSoundTime = accessor.antarchy$getRainSoundTime();
|
||||
this.previousSectionX = accessor.antarchy$getLastCameraSectionX();
|
||||
this.previousSectionY = accessor.antarchy$getLastCameraSectionY();
|
||||
this.previousSectionZ = accessor.antarchy$getLastCameraSectionZ();
|
||||
this.previousPrevCamX = accessor.antarchy$getPrevCamX();
|
||||
this.previousPrevCamY = accessor.antarchy$getPrevCamY();
|
||||
this.previousPrevCamZ = accessor.antarchy$getPrevCamZ();
|
||||
this.previousPrevCamRotX = accessor.antarchy$getPrevCamRotX();
|
||||
this.previousPrevCamRotY = accessor.antarchy$getPrevCamRotY();
|
||||
this.previousTransparentSortX = accessor.antarchy$getTransparentSortX();
|
||||
this.previousTransparentSortY = accessor.antarchy$getTransparentSortY();
|
||||
this.previousTransparentSortZ = accessor.antarchy$getTransparentSortZ();
|
||||
this.dispatcher = renderer.getSectionRenderDispatcher();
|
||||
this.previousDispatcherCamera = dispatcher.getCameraPosition();
|
||||
accessor.antarchy$setLastCameraSectionX(state.lastSectionX);
|
||||
accessor.antarchy$setLastCameraSectionY(state.lastSectionY);
|
||||
accessor.antarchy$setLastCameraSectionZ(state.lastSectionZ);
|
||||
accessor.antarchy$setPrevCamX(state.prevCamX);
|
||||
accessor.antarchy$setPrevCamY(state.prevCamY);
|
||||
accessor.antarchy$setPrevCamZ(state.prevCamZ);
|
||||
accessor.antarchy$setPrevCamRotX(state.prevCamRotX);
|
||||
accessor.antarchy$setPrevCamRotY(state.prevCamRotY);
|
||||
accessor.antarchy$setTransparentSortX(state.transparentSortX);
|
||||
accessor.antarchy$setTransparentSortY(state.transparentSortY);
|
||||
accessor.antarchy$setTransparentSortZ(state.transparentSortZ);
|
||||
accessor.antarchy$setCloudBuffer(state.cloudBuffer);
|
||||
accessor.antarchy$setGenerateClouds(state.generateClouds);
|
||||
accessor.antarchy$setPrevCloudX(state.prevCloudX);
|
||||
accessor.antarchy$setPrevCloudY(state.prevCloudY);
|
||||
accessor.antarchy$setPrevCloudZ(state.prevCloudZ);
|
||||
accessor.antarchy$setPrevCloudColor(state.prevCloudColor);
|
||||
accessor.antarchy$setPrevCloudsType(state.prevCloudsType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (closed) {
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
state.lastSectionX = accessor.antarchy$getLastCameraSectionX();
|
||||
state.lastSectionY = accessor.antarchy$getLastCameraSectionY();
|
||||
state.lastSectionZ = accessor.antarchy$getLastCameraSectionZ();
|
||||
state.prevCamX = accessor.antarchy$getPrevCamX();
|
||||
state.prevCamY = accessor.antarchy$getPrevCamY();
|
||||
state.prevCamZ = accessor.antarchy$getPrevCamZ();
|
||||
state.prevCamRotX = accessor.antarchy$getPrevCamRotX();
|
||||
state.prevCamRotY = accessor.antarchy$getPrevCamRotY();
|
||||
state.transparentSortX = accessor.antarchy$getTransparentSortX();
|
||||
state.transparentSortY = accessor.antarchy$getTransparentSortY();
|
||||
state.transparentSortZ = accessor.antarchy$getTransparentSortZ();
|
||||
state.cloudBuffer = accessor.antarchy$getCloudBuffer();
|
||||
state.generateClouds = accessor.antarchy$getGenerateClouds();
|
||||
state.prevCloudX = accessor.antarchy$getPrevCloudX();
|
||||
state.prevCloudY = accessor.antarchy$getPrevCloudY();
|
||||
state.prevCloudZ = accessor.antarchy$getPrevCloudZ();
|
||||
state.prevCloudColor = accessor.antarchy$getPrevCloudColor();
|
||||
state.prevCloudsType = accessor.antarchy$getPrevCloudsType();
|
||||
accessor.antarchy$setViewArea(previousArea);
|
||||
accessor.antarchy$setSectionOcclusionGraph(previousGraph);
|
||||
accessor.antarchy$setVisibleSections(previousVisibleSections);
|
||||
accessor.antarchy$setGlobalBlockEntities(previousGlobalBlockEntities);
|
||||
accessor.antarchy$setCloudBuffer(previousCloudBuffer);
|
||||
accessor.antarchy$setGenerateClouds(previousGenerateClouds);
|
||||
accessor.antarchy$setPrevCloudX(previousCloudX);
|
||||
accessor.antarchy$setPrevCloudY(previousCloudY);
|
||||
accessor.antarchy$setPrevCloudZ(previousCloudZ);
|
||||
accessor.antarchy$setPrevCloudColor(previousCloudColor);
|
||||
accessor.antarchy$setPrevCloudsType(previousCloudsType);
|
||||
accessor.antarchy$setRainSoundTime(previousRainSoundTime);
|
||||
accessor.antarchy$setLastCameraSectionX(previousSectionX);
|
||||
accessor.antarchy$setLastCameraSectionY(previousSectionY);
|
||||
accessor.antarchy$setLastCameraSectionZ(previousSectionZ);
|
||||
accessor.antarchy$setPrevCamX(previousPrevCamX);
|
||||
accessor.antarchy$setPrevCamY(previousPrevCamY);
|
||||
accessor.antarchy$setPrevCamZ(previousPrevCamZ);
|
||||
accessor.antarchy$setPrevCamRotX(previousPrevCamRotX);
|
||||
accessor.antarchy$setPrevCamRotY(previousPrevCamRotY);
|
||||
accessor.antarchy$setTransparentSortX(previousTransparentSortX);
|
||||
accessor.antarchy$setTransparentSortY(previousTransparentSortY);
|
||||
accessor.antarchy$setTransparentSortZ(previousTransparentSortZ);
|
||||
dispatcher.setCamera(previousDispatcherCamera);
|
||||
blockEntityDispatcher.prepare(previousBlockEntityLevel, previousBlockEntityCamera, previousBlockEntityHitResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
+372
-909
File diff suppressed because it is too large.
Load diff
-246
@@ -1,246 +0,0 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
|
||||
import com.craisinlord.antarchy.mixins.client.LevelRendererPortalSceneInvoker;
|
||||
import com.craisinlord.antarchy.mixins.client.LevelRendererPortalViewAreaAccessor;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.platform.Lighting;
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.CloudStatus;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fStack;
|
||||
|
||||
public final class PortalGunProxySceneRenderer {
|
||||
private PortalGunProxySceneRenderer() {
|
||||
}
|
||||
|
||||
public static void render(Minecraft minecraft, LevelRenderer renderer, Camera camera, float partialTick, Matrix4f modelViewMatrix, Matrix4f projectionMatrix, Matrix4f cullProjectionMatrix, String tracePair) {
|
||||
Matrix4fStack outerModelViewStack = RenderSystem.getModelViewStack();
|
||||
float previousFogStart = RenderSystem.getShaderFogStart();
|
||||
float previousFogEnd = RenderSystem.getShaderFogEnd();
|
||||
float[] previousFogColor = RenderSystem.getShaderFogColor().clone();
|
||||
FogShape previousFogShape = RenderSystem.getShaderFogShape();
|
||||
outerModelViewStack.pushMatrix();
|
||||
outerModelViewStack.identity();
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
ObjectArrayList<SectionRenderDispatcher.RenderSection> originalVisibleSections = null;
|
||||
try {
|
||||
Vec3 cameraPosition = camera.getPosition();
|
||||
double cameraX = cameraPosition.x;
|
||||
double cameraY = cameraPosition.y;
|
||||
double cameraZ = cameraPosition.z;
|
||||
Frustum frustum = new Frustum(modelViewMatrix, cullProjectionMatrix);
|
||||
frustum.prepare(cameraX, cameraY, cameraZ);
|
||||
LevelRendererPortalSceneInvoker scene = (LevelRendererPortalSceneInvoker) renderer;
|
||||
float renderDistance = minecraft.gameRenderer.getRenderDistance();
|
||||
BlockPos cameraBlockPos = BlockPos.containing(cameraX, cameraY, cameraZ);
|
||||
boolean foggy = minecraft.level.effects().isFoggyAt(cameraBlockPos.getX(), cameraBlockPos.getY())
|
||||
|| minecraft.gui.getBossOverlay().shouldCreateWorldFog();
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "sky", "camera=" + cameraPosition)) {
|
||||
RenderSystem.setShaderGameTime(minecraft.level.getGameTime(), partialTick);
|
||||
minecraft.getBlockEntityRenderDispatcher().prepare(minecraft.level, camera, minecraft.hitResult);
|
||||
minecraft.getEntityRenderDispatcher().prepare(minecraft.level, camera, minecraft.crosshairPickEntity);
|
||||
FogRenderer.setupColor(camera, partialTick, minecraft.level, minecraft.options.getEffectiveRenderDistance(), minecraft.gameRenderer.getDarkenWorldAmount(partialTick));
|
||||
FogRenderer.levelFogColor();
|
||||
FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_SKY, renderDistance, foggy, partialTick);
|
||||
RenderSystem.setShader(net.minecraft.client.renderer.GameRenderer::getPositionShader);
|
||||
renderer.renderSky(modelViewMatrix, projectionMatrix, partialTick, camera, foggy,
|
||||
() -> FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_SKY, renderDistance, foggy, partialTick));
|
||||
}
|
||||
|
||||
boolean sodium = SodiumCompat.isLoaded();
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "frustum-and-visibility", "renderDistance=" + (sodium ? minecraft.options.getEffectiveRenderDistance() : rendererAccessDistance(renderer)))) {
|
||||
FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_TERRAIN, Math.max(renderDistance, 32.0F), foggy, partialTick);
|
||||
scene.antarchy$setupPortalScene(camera, frustum, false, minecraft.player != null && minecraft.player.isSpectator());
|
||||
}
|
||||
LevelRendererPortalViewAreaAccessor viewAreaAccessor = sodium ? null : (LevelRendererPortalViewAreaAccessor) renderer;
|
||||
int visibleSectionCount = 0;
|
||||
int candidateSectionCount = 0;
|
||||
if (viewAreaAccessor != null) {
|
||||
originalVisibleSections = viewAreaAccessor.antarchy$getVisibleSections();
|
||||
candidateSectionCount = originalVisibleSections.size();
|
||||
ObjectArrayList<SectionRenderDispatcher.RenderSection> apertureSections = new ObjectArrayList<>();
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "aperture-section-cull", "candidateSections=" + candidateSectionCount)) {
|
||||
for (SectionRenderDispatcher.RenderSection section : originalVisibleSections) {
|
||||
if (PortalGunPortalRenderState.shouldRenderBounds(section.getBoundingBox())) {
|
||||
apertureSections.add(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
viewAreaAccessor.antarchy$setVisibleSections(apertureSections);
|
||||
ObjectArrayList<SectionRenderDispatcher.RenderSection> fullVisibleSections = apertureSections;
|
||||
ObjectArrayList<SectionRenderDispatcher.RenderSection> budgetedVisibleSections = new ObjectArrayList<>();
|
||||
int scannedVisibleSections = 0;
|
||||
while (scannedVisibleSections < fullVisibleSections.size() && PortalGunPortalRendererPool.remainingSectionBudgetNanos() > 0L) {
|
||||
budgetedVisibleSections.add(fullVisibleSections.get(scannedVisibleSections++));
|
||||
}
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "compile-visible-sections", "visibleTotal=" + fullVisibleSections.size() + " visibleScanned=" + scannedVisibleSections + " rebuildBudgetNanos=" + PortalGunPortalRendererPool.remainingSectionBudgetNanos())) {
|
||||
viewAreaAccessor.antarchy$setVisibleSections(budgetedVisibleSections);
|
||||
try {
|
||||
scene.antarchy$compilePortalSections(camera);
|
||||
} finally {
|
||||
viewAreaAccessor.antarchy$setVisibleSections(fullVisibleSections);
|
||||
}
|
||||
}
|
||||
visibleSectionCount = fullVisibleSections.size();
|
||||
}
|
||||
PortalSceneRenderTrace.event(tracePair, "visible-sections-ready", "renderer=" + (sodium ? "sodium" : "vanilla")
|
||||
+ " count=" + visibleSectionCount + " candidates=" + candidateSectionCount
|
||||
+ " scheduledRebuilds=" + PortalGunPortalRendererPool.scheduledSectionRebuilds()
|
||||
+ " uploaded=" + PortalGunPortalRendererPool.uploadedThisFrame()
|
||||
+ " pendingUploads=" + (sodium ? "sodium-managed" : viewAreaAccessor.antarchy$getSectionRenderDispatcher().getToUpload()));
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "opaque-terrain-layers", "sections=" + visibleSectionCount)) {
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.depthMask(true);
|
||||
scene.antarchy$renderPortalSectionLayer(RenderType.solid(), cameraX, cameraY, cameraZ, modelViewMatrix, projectionMatrix);
|
||||
scene.antarchy$renderPortalSectionLayer(RenderType.cutoutMipped(), cameraX, cameraY, cameraZ, modelViewMatrix, projectionMatrix);
|
||||
scene.antarchy$renderPortalSectionLayer(RenderType.cutout(), cameraX, cameraY, cameraZ, modelViewMatrix, projectionMatrix);
|
||||
}
|
||||
|
||||
if (minecraft.level.effects().constantAmbientLight()) {
|
||||
Lighting.setupNetherLevel();
|
||||
} else {
|
||||
Lighting.setupLevel();
|
||||
}
|
||||
|
||||
Matrix4fStack modelViewStack = RenderSystem.getModelViewStack();
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "entity-scene-state", "enter-model-view")) {
|
||||
modelViewStack.pushMatrix();
|
||||
modelViewStack.mul(modelViewMatrix);
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
}
|
||||
PoseStack poseStack = new PoseStack();
|
||||
MultiBufferSource.BufferSource buffers = PortalGunPortalRendererPool.bufferSource();
|
||||
try {
|
||||
int entityCount = 0;
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "entities", "dispatch-start")) {
|
||||
for (Entity entity : minecraft.level.entitiesForRendering()) {
|
||||
if (!minecraft.getEntityRenderDispatcher().shouldRender(entity, frustum, cameraX, cameraY, cameraZ)
|
||||
&& !entity.hasIndirectPassenger(minecraft.player)) {
|
||||
continue;
|
||||
}
|
||||
if (entity == camera.getEntity() && !camera.isDetached()
|
||||
&& (!(entity instanceof LivingEntity living) || !living.isSleeping())) {
|
||||
continue;
|
||||
}
|
||||
if (entity instanceof Player player && player == minecraft.player && !player.isSpectator() && entity != camera.getEntity()) {
|
||||
continue;
|
||||
}
|
||||
scene.antarchy$renderPortalEntity(entity, cameraX, cameraY, cameraZ, partialTick, poseStack, buffers);
|
||||
entityCount++;
|
||||
}
|
||||
}
|
||||
buffers.endBatch();
|
||||
PortalSceneRenderTrace.event(tracePair, "entities-dispatched", "count=" + entityCount);
|
||||
|
||||
int blockEntityCount = 0;
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "block-entities", "visibleSections=" + visibleSectionCount)) {
|
||||
if (sodium) {
|
||||
int[] count = {0};
|
||||
SodiumCompat.forEachVisibleBlockEntity(blockEntity -> {
|
||||
renderBlockEntity(minecraft, blockEntity, cameraX, cameraY, cameraZ, partialTick, poseStack, buffers);
|
||||
count[0]++;
|
||||
});
|
||||
blockEntityCount = count[0];
|
||||
} else {
|
||||
for (var section : viewAreaAccessor.antarchy$getVisibleSections()) {
|
||||
for (BlockEntity blockEntity : section.getCompiled().getRenderableBlockEntities()) {
|
||||
renderBlockEntity(minecraft, blockEntity, cameraX, cameraY, cameraZ, partialTick, poseStack, buffers);
|
||||
blockEntityCount++;
|
||||
}
|
||||
}
|
||||
synchronized (viewAreaAccessor.antarchy$getGlobalBlockEntities()) {
|
||||
for (BlockEntity blockEntity : viewAreaAccessor.antarchy$getGlobalBlockEntities()) {
|
||||
if (frustum.isVisible(new AABB(blockEntity.getBlockPos()).inflate(1.0D))) {
|
||||
renderBlockEntity(minecraft, blockEntity, cameraX, cameraY, cameraZ, partialTick, poseStack, buffers);
|
||||
blockEntityCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
buffers.endBatch();
|
||||
PortalSceneRenderTrace.event(tracePair, "block-entities-dispatched", "count=" + blockEntityCount);
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "translucent-and-particles", "rendering")) {
|
||||
scene.antarchy$renderPortalSectionLayer(RenderType.translucent(), cameraX, cameraY, cameraZ, modelViewMatrix, projectionMatrix);
|
||||
buffers.endBatch(RenderType.lines());
|
||||
buffers.endBatch();
|
||||
scene.antarchy$renderPortalSectionLayer(RenderType.tripwire(), cameraX, cameraY, cameraZ, modelViewMatrix, projectionMatrix);
|
||||
minecraft.particleEngine.render(minecraft.gameRenderer.lightTexture(), camera, partialTick);
|
||||
}
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "clouds", minecraft.options.getCloudsType().toString())) {
|
||||
if (minecraft.options.getCloudsType() != CloudStatus.OFF) {
|
||||
renderer.renderClouds(poseStack, modelViewMatrix, projectionMatrix, partialTick, cameraX, cameraY, cameraZ);
|
||||
}
|
||||
}
|
||||
|
||||
try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "weather-and-border", "rendering")) {
|
||||
RenderSystem.depthMask(false);
|
||||
scene.antarchy$renderPortalWeather(minecraft.gameRenderer.lightTexture(), partialTick, cameraX, cameraY, cameraZ);
|
||||
scene.antarchy$renderPortalWorldBorder(camera);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
buffers.endBatch();
|
||||
} finally {
|
||||
modelViewStack.popMatrix();
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.enableCull();
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (originalVisibleSections != null) {
|
||||
((LevelRendererPortalViewAreaAccessor) renderer).antarchy$setVisibleSections(originalVisibleSections);
|
||||
}
|
||||
outerModelViewStack.popMatrix();
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
RenderSystem.setShaderFogStart(previousFogStart);
|
||||
RenderSystem.setShaderFogEnd(previousFogEnd);
|
||||
RenderSystem.setShaderFogColor(previousFogColor[0], previousFogColor[1], previousFogColor[2], previousFogColor[3]);
|
||||
RenderSystem.setShaderFogShape(previousFogShape);
|
||||
}
|
||||
}
|
||||
|
||||
private static int rendererAccessDistance(LevelRenderer renderer) {
|
||||
return ((LevelRendererPortalViewAreaAccessor) renderer).antarchy$getViewArea().getViewDistance();
|
||||
}
|
||||
|
||||
private static void renderBlockEntity(Minecraft minecraft, BlockEntity blockEntity, double cameraX, double cameraY, double cameraZ,
|
||||
float partialTick, PoseStack poseStack, MultiBufferSource.BufferSource buffers) {
|
||||
if (!blockEntity.hasLevel() || !blockEntity.getType().isValid(blockEntity.getBlockState())) {
|
||||
return;
|
||||
}
|
||||
BlockPos pos = blockEntity.getBlockPos();
|
||||
poseStack.pushPose();
|
||||
try {
|
||||
poseStack.translate(pos.getX() - cameraX, pos.getY() - cameraY, pos.getZ() - cameraZ);
|
||||
minecraft.getBlockEntityRenderDispatcher().render(blockEntity, partialTick, poseStack, buffers);
|
||||
} finally {
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
|
||||
final class PortalRenderWatchdog {
|
||||
private static final long STALL_NANOS = 5_000_000_000L;
|
||||
private static final long RECENT_PORTAL_NANOS = 10_000_000_000L;
|
||||
private static volatile Thread renderThread;
|
||||
private static volatile long lastFrameNanos;
|
||||
private static volatile long lastPortalViewNanos = Long.MIN_VALUE;
|
||||
private static volatile boolean reportedStall;
|
||||
private static Thread watcher;
|
||||
|
||||
private PortalRenderWatchdog() {
|
||||
}
|
||||
|
||||
static void frame() {
|
||||
lastFrameNanos = System.nanoTime();
|
||||
reportedStall = false;
|
||||
if (watcher == null) {
|
||||
renderThread = Thread.currentThread();
|
||||
watcher = new Thread(PortalRenderWatchdog::watch, "Antarchy portal render watchdog");
|
||||
watcher.setDaemon(true);
|
||||
watcher.start();
|
||||
}
|
||||
}
|
||||
|
||||
static void portalViewDrawn() {
|
||||
lastPortalViewNanos = System.nanoTime();
|
||||
}
|
||||
|
||||
private static void watch() {
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(1000L);
|
||||
} catch (InterruptedException exception) {
|
||||
return;
|
||||
}
|
||||
long now = System.nanoTime();
|
||||
long lastFrame = lastFrameNanos;
|
||||
long lastPortal = lastPortalViewNanos;
|
||||
Thread thread = renderThread;
|
||||
if (reportedStall || thread == null || lastPortal == Long.MIN_VALUE
|
||||
|| now - lastFrame < STALL_NANOS || lastFrame - lastPortal > RECENT_PORTAL_NANOS) {
|
||||
continue;
|
||||
}
|
||||
reportedStall = true;
|
||||
StringBuilder stack = new StringBuilder();
|
||||
for (StackTraceElement element : thread.getStackTrace()) {
|
||||
stack.append("\n\tat ").append(element);
|
||||
}
|
||||
Antarchy.LOGGER.warn("Render thread has not finished a frame for {} ms after portal views were drawn (state {}). Stack:{}",
|
||||
(now - lastFrame) / 1_000_000L, thread.getState(), stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
public interface PortalSectionGraphMarker {
|
||||
void antarchy$markPortalGraph();
|
||||
}
|
||||
+42
-167
@@ -7,15 +7,14 @@ import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
public final class PortalStencilTarget {
|
||||
private static final Map<RenderTarget, Attachment> ATTACHMENTS = Collections.synchronizedMap(new IdentityHashMap<>());
|
||||
private static final int GL_INCR = 7682;
|
||||
private static final int GL_DECR = 7683;
|
||||
private static final Map<RenderTarget, Attachment> MAIN_STENCIL_ATTACHMENTS = Collections.synchronizedMap(new IdentityHashMap<>());
|
||||
private static final Map<RenderTarget, Integer> UNSUPPORTED_MAIN_TARGETS = Collections.synchronizedMap(new IdentityHashMap<>());
|
||||
private static final Set<RenderTarget> DIRECT_TARGETS = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||
|
||||
private PortalStencilTarget() {
|
||||
}
|
||||
@@ -52,105 +51,67 @@ public final class PortalStencilTarget {
|
||||
return stencilBits() > 0;
|
||||
}
|
||||
|
||||
public static Scope beginDirect(RenderTarget target, Runnable drawApertureMask, Runnable clearApertureDepth, Runnable restoreApertureDepth) {
|
||||
target.bindWrite(true);
|
||||
if (stencilBits() <= 0) {
|
||||
throw new IllegalStateException("Main render target has no stencil attachment");
|
||||
}
|
||||
DIRECT_TARGETS.add(target);
|
||||
public static void beginFrame(RenderTarget target) {
|
||||
target.bindWrite(true);
|
||||
RenderSystem.disableScissor();
|
||||
RenderSystem.stencilMask(0xFF);
|
||||
RenderSystem.clearStencil(0);
|
||||
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
|
||||
RenderSystem.stencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.depthMask(false);
|
||||
RenderSystem.enableDepthTest();
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
try {
|
||||
Objects.requireNonNull(drawApertureMask).run();
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.stencilMask(0x00);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
Objects.requireNonNull(clearApertureDepth).run();
|
||||
} catch (RuntimeException | Error exception) {
|
||||
try {
|
||||
target.bindWrite(true);
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilMask(0x00);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.depthMask(true);
|
||||
restoreApertureDepth.run();
|
||||
} catch (RuntimeException | Error restoreFailure) {
|
||||
exception.addSuppressed(restoreFailure);
|
||||
} finally {
|
||||
DIRECT_TARGETS.remove(target);
|
||||
resetState();
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.stencilMask(0x00);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.enableDepthTest();
|
||||
return new Scope(target, restoreApertureDepth);
|
||||
drawInside(0);
|
||||
}
|
||||
|
||||
public static Scope begin(RenderTarget target, Runnable drawApertureMask) {
|
||||
ensureAttachment(target);
|
||||
target.bindWrite(true);
|
||||
RenderSystem.disableScissor();
|
||||
public static void endFrame() {
|
||||
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilMask(0xFF);
|
||||
RenderSystem.clearStencil(0);
|
||||
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
|
||||
RenderSystem.stencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.depthMask(false);
|
||||
RenderSystem.disableDepthTest();
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
try {
|
||||
Objects.requireNonNull(drawApertureMask).run();
|
||||
} catch (RuntimeException | Error exception) {
|
||||
resetState();
|
||||
throw exception;
|
||||
}
|
||||
RenderSystem.stencilFunc(GL11.GL_ALWAYS, 0, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.stencilMask(0x00);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
RenderSystem.enableDepthTest();
|
||||
return new Scope(target);
|
||||
}
|
||||
|
||||
public static void activate(RenderTarget target) {
|
||||
if (!ATTACHMENTS.containsKey(target) && !DIRECT_TARGETS.contains(target)) {
|
||||
return;
|
||||
}
|
||||
target.bindWrite(true);
|
||||
public static void pushAperture(int parentLevel, Runnable drawAperture) {
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilMask(0xFF);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, parentLevel, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL_INCR);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.depthMask(false);
|
||||
RenderSystem.enableDepthTest();
|
||||
try {
|
||||
drawAperture.run();
|
||||
} finally {
|
||||
drawInside(parentLevel + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void popAperture(int parentLevel, Runnable drawApertureDepth) {
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilMask(0xFF);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, parentLevel + 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL_DECR);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.enableDepthTest();
|
||||
try {
|
||||
drawApertureDepth.run();
|
||||
} finally {
|
||||
drawInside(parentLevel);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawInside(int level) {
|
||||
RenderSystem.stencilMask(0x00);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, level, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
public static void release(RenderTarget target) {
|
||||
DIRECT_TARGETS.remove(target);
|
||||
UNSUPPORTED_MAIN_TARGETS.remove(target);
|
||||
Attachment attachment = ATTACHMENTS.remove(target);
|
||||
if (attachment != null) {
|
||||
GL30.glDeleteRenderbuffers(attachment.renderbuffer());
|
||||
}
|
||||
Attachment mainAttachment = MAIN_STENCIL_ATTACHMENTS.remove(target);
|
||||
if (mainAttachment != null) {
|
||||
GL30.glDeleteRenderbuffers(mainAttachment.renderbuffer());
|
||||
@@ -158,16 +119,11 @@ public final class PortalStencilTarget {
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
for (Attachment attachment : ATTACHMENTS.values()) {
|
||||
GL30.glDeleteRenderbuffers(attachment.renderbuffer());
|
||||
}
|
||||
ATTACHMENTS.clear();
|
||||
for (Attachment attachment : MAIN_STENCIL_ATTACHMENTS.values()) {
|
||||
GL30.glDeleteRenderbuffers(attachment.renderbuffer());
|
||||
}
|
||||
MAIN_STENCIL_ATTACHMENTS.clear();
|
||||
UNSUPPORTED_MAIN_TARGETS.clear();
|
||||
DIRECT_TARGETS.clear();
|
||||
}
|
||||
|
||||
private static void ensureMainStencilAttachment(RenderTarget target) {
|
||||
@@ -203,47 +159,6 @@ public final class PortalStencilTarget {
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureAttachment(RenderTarget target) {
|
||||
Attachment attachment = ATTACHMENTS.get(target);
|
||||
if (attachment != null
|
||||
&& attachment.framebuffer() == target.frameBufferId
|
||||
&& attachment.width() == target.width
|
||||
&& attachment.height() == target.height) {
|
||||
return;
|
||||
}
|
||||
if (attachment != null) {
|
||||
GL30.glDeleteRenderbuffers(attachment.renderbuffer());
|
||||
}
|
||||
int previousFramebuffer = GL11.glGetInteger(GL30.GL_FRAMEBUFFER_BINDING);
|
||||
int previousRenderbuffer = GL11.glGetInteger(GL30.GL_RENDERBUFFER_BINDING);
|
||||
int renderbuffer = GL30.glGenRenderbuffers();
|
||||
try {
|
||||
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, target.frameBufferId);
|
||||
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, renderbuffer);
|
||||
GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH24_STENCIL8, target.width, target.height);
|
||||
GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, renderbuffer);
|
||||
int status = GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER);
|
||||
if (status != GL30.GL_FRAMEBUFFER_COMPLETE) {
|
||||
GL30.glDeleteRenderbuffers(renderbuffer);
|
||||
throw new IllegalStateException("Portal view framebuffer is incomplete with packed depth/stencil attachment: 0x" + Integer.toHexString(status));
|
||||
}
|
||||
ATTACHMENTS.put(target, new Attachment(target.frameBufferId, renderbuffer, target.width, target.height));
|
||||
} finally {
|
||||
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, previousRenderbuffer);
|
||||
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, previousFramebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void resetState() {
|
||||
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilMask(0xFF);
|
||||
RenderSystem.stencilFunc(GL11.GL_ALWAYS, 0, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
private static int stencilBits() {
|
||||
int type = GL30.glGetFramebufferAttachmentParameteri(GL30.GL_FRAMEBUFFER, GL30.GL_STENCIL_ATTACHMENT,
|
||||
GL30.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
|
||||
@@ -253,44 +168,4 @@ public final class PortalStencilTarget {
|
||||
|
||||
private record Attachment(int framebuffer, int renderbuffer, int width, int height) {
|
||||
}
|
||||
|
||||
public static final class Scope implements AutoCloseable {
|
||||
private boolean closed;
|
||||
private final RenderTarget target;
|
||||
private final Runnable restoreApertureDepth;
|
||||
|
||||
private Scope(RenderTarget target) {
|
||||
this(target, null);
|
||||
}
|
||||
|
||||
private Scope(RenderTarget target, Runnable restoreApertureDepth) {
|
||||
this.target = Objects.requireNonNull(target);
|
||||
this.restoreApertureDepth = restoreApertureDepth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (closed) {
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
try {
|
||||
if (this.restoreApertureDepth != null) {
|
||||
this.target.bindWrite(true);
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilMask(0x00);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.depthMask(true);
|
||||
this.restoreApertureDepth.run();
|
||||
}
|
||||
} finally {
|
||||
if (this.restoreApertureDepth != null) {
|
||||
DIRECT_TARGETS.remove(this.target);
|
||||
}
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
public interface PortalTerrain {
|
||||
static boolean canView(Minecraft minecraft, Vec3 exitCenter) {
|
||||
return SodiumCompat.isLoaded()
|
||||
? com.craisinlord.antarchy.content.client.renderer.sodium.SodiumPortalTerrain.canView(minecraft, exitCenter)
|
||||
: PortalGunPortalSectionViews.canView(minecraft, exitCenter);
|
||||
}
|
||||
|
||||
static PortalTerrain prepare(Minecraft minecraft, java.util.UUID exitId, Vec3 exitCenter, Vec3 exitNormal, Frustum frustum) {
|
||||
return SodiumCompat.isLoaded()
|
||||
? com.craisinlord.antarchy.content.client.renderer.sodium.SodiumPortalTerrain.prepare(minecraft, frustum)
|
||||
: VanillaPortalTerrain.prepare(minecraft, exitId, exitCenter, exitNormal, frustum);
|
||||
}
|
||||
|
||||
int sectionCount();
|
||||
|
||||
void begin(Minecraft minecraft);
|
||||
|
||||
void end(Minecraft minecraft);
|
||||
|
||||
void drawLayer(Minecraft minecraft, RenderType renderType, Vec3 cameraPosition, Matrix4f viewMatrix, Matrix4f projection);
|
||||
|
||||
void forEachBlockEntity(Minecraft minecraft, Frustum frustum, Consumer<BlockEntity> consumer);
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
public interface PortalViewSectionMarker {
|
||||
void antarchy$markPortalViewSection();
|
||||
|
||||
boolean antarchy$isPortalViewSection();
|
||||
}
|
||||
+8
-116
@@ -1,23 +1,20 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
public final class SodiumCompat {
|
||||
private static final String SODIUM_RENDERER_CLASS = "net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer";
|
||||
private static final ThreadLocal<RenderState> RENDER_STATE = ThreadLocal.withInitial(RenderState::new);
|
||||
private static boolean restoreWarningLogged;
|
||||
private static Boolean loaded;
|
||||
|
||||
private SodiumCompat() {
|
||||
}
|
||||
|
||||
public static boolean isLoaded() {
|
||||
if (loaded == null) {
|
||||
loaded = detect();
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
private static boolean detect() {
|
||||
String resource = SODIUM_RENDERER_CLASS.replace('.', '/') + ".class";
|
||||
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
|
||||
if (contextLoader != null && contextLoader.getResource(resource) != null) {
|
||||
@@ -26,109 +23,4 @@ public final class SodiumCompat {
|
||||
ClassLoader ownLoader = SodiumCompat.class.getClassLoader();
|
||||
return ownLoader != null && ownLoader.getResource(resource) != null;
|
||||
}
|
||||
|
||||
public static void captureTerrainSetup(Camera camera, Object viewport, boolean spectator, boolean updateChunks) {
|
||||
RENDER_STATE.get().activeSetup = new TerrainSetup(camera, viewport, spectator, updateChunks);
|
||||
}
|
||||
|
||||
public static TerrainScope beginPortalView() {
|
||||
RenderState state = RENDER_STATE.get();
|
||||
TerrainSetup previousSetup = state.activeSetup;
|
||||
state.previousSetups.push(new PreviousSetup(previousSetup));
|
||||
return () -> {
|
||||
PreviousSetup previous = state.previousSetups.pop();
|
||||
if (previous.setup() == null) {
|
||||
state.activeSetup = null;
|
||||
return;
|
||||
}
|
||||
restoreTerrainSetup(previous.setup(), state);
|
||||
};
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
RENDER_STATE.remove();
|
||||
}
|
||||
|
||||
public static void forEachVisibleBlockEntity(Consumer<BlockEntity> consumer) {
|
||||
try {
|
||||
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
|
||||
Class<?> rendererClass = Class.forName(SODIUM_RENDERER_CLASS, false,
|
||||
contextLoader == null ? SodiumCompat.class.getClassLoader() : contextLoader);
|
||||
Object renderer = rendererClass.getMethod("instanceNullable").invoke(null);
|
||||
if (renderer != null) {
|
||||
rendererClass.getMethod("iterateVisibleBlockEntities", Consumer.class).invoke(renderer, consumer);
|
||||
}
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | LinkageError exception) {
|
||||
logRestoreFailure("Could not iterate Sodium block entities for a portal view", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void restoreTerrainSetup(TerrainSetup setup, RenderState state) {
|
||||
try {
|
||||
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
|
||||
Class<?> rendererClass = Class.forName(SODIUM_RENDERER_CLASS, false,
|
||||
contextLoader == null ? SodiumCompat.class.getClassLoader() : contextLoader);
|
||||
Object renderer = rendererClass.getMethod("instanceNullable").invoke(null);
|
||||
if (renderer == null) {
|
||||
return;
|
||||
}
|
||||
Method terrainSetup = null;
|
||||
for (Method method : rendererClass.getMethods()) {
|
||||
Class<?>[] parameters = method.getParameterTypes();
|
||||
if (method.getName().equals("setupTerrain")
|
||||
&& parameters.length == 4
|
||||
&& parameters[0].isInstance(setup.camera())
|
||||
&& parameters[1].isInstance(setup.viewport())
|
||||
&& parameters[2] == boolean.class
|
||||
&& parameters[3] == boolean.class) {
|
||||
terrainSetup = method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (terrainSetup == null) {
|
||||
logRestoreFailure("Sodium terrain setup method was not found", null);
|
||||
state.activeSetup = setup;
|
||||
return;
|
||||
}
|
||||
Class<?> deviceClass = Class.forName("net.caffeinemc.mods.sodium.client.gl.device.RenderDevice", false,
|
||||
contextLoader == null ? SodiumCompat.class.getClassLoader() : contextLoader);
|
||||
deviceClass.getMethod("enterManagedCode").invoke(null);
|
||||
try {
|
||||
terrainSetup.invoke(renderer, setup.camera(), setup.viewport(), setup.spectator(), setup.updateChunks());
|
||||
} finally {
|
||||
deviceClass.getMethod("exitManagedCode").invoke(null);
|
||||
}
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | LinkageError exception) {
|
||||
logRestoreFailure("Could not restore Sodium terrain after a portal view", exception);
|
||||
state.activeSetup = setup;
|
||||
}
|
||||
}
|
||||
|
||||
private static void logRestoreFailure(String message, Throwable exception) {
|
||||
if (!restoreWarningLogged) {
|
||||
restoreWarningLogged = true;
|
||||
if (exception == null) {
|
||||
Antarchy.LOGGER.warn(message);
|
||||
} else {
|
||||
Antarchy.LOGGER.warn(message, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TerrainScope extends AutoCloseable {
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
|
||||
private static final class RenderState {
|
||||
private final Deque<PreviousSetup> previousSetups = new ArrayDeque<>();
|
||||
private TerrainSetup activeSetup;
|
||||
}
|
||||
|
||||
private record PreviousSetup(TerrainSetup setup) {
|
||||
}
|
||||
|
||||
private record TerrainSetup(Camera camera, Object viewport, boolean spectator, boolean updateChunks) {
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
|
||||
import com.craisinlord.antarchy.mixins.client.LevelRendererPortalViewAreaAccessor;
|
||||
import com.mojang.blaze3d.shaders.Uniform;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.VertexBuffer;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.client.renderer.chunk.RenderRegionCache;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
final class VanillaPortalTerrain implements PortalTerrain {
|
||||
private static final int MAX_REBUILDS_PER_SCENE = 32;
|
||||
|
||||
private final ObjectArrayList<SectionRenderDispatcher.RenderSection> sections;
|
||||
|
||||
private VanillaPortalTerrain(ObjectArrayList<SectionRenderDispatcher.RenderSection> sections) {
|
||||
this.sections = sections;
|
||||
}
|
||||
|
||||
static VanillaPortalTerrain prepare(Minecraft minecraft, UUID exitId, Vec3 exitCenter, Vec3 exitNormal, Frustum frustum) {
|
||||
PortalGunPortalSectionViews.View view = PortalGunPortalSectionViews.prepare(minecraft, exitId, exitCenter, exitNormal, frustum);
|
||||
view.visibleSections().removeIf(section -> !PortalGunPortalRenderState.shouldRenderBounds(section.getBoundingBox()));
|
||||
queueDirtySections(minecraft, view.visibleSections());
|
||||
return new VanillaPortalTerrain(view.visibleSections());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sectionCount() {
|
||||
return this.sections.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(Minecraft minecraft) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(Minecraft minecraft) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Minecraft minecraft, RenderType renderType, Vec3 cameraPosition, Matrix4f viewMatrix, Matrix4f projection) {
|
||||
renderType.setupRenderState();
|
||||
ShaderInstance shader = RenderSystem.getShader();
|
||||
if (shader == null) {
|
||||
renderType.clearRenderState();
|
||||
return;
|
||||
}
|
||||
shader.setDefaultUniforms(VertexFormat.Mode.QUADS, viewMatrix, projection, minecraft.getWindow());
|
||||
shader.apply();
|
||||
Uniform chunkOffset = shader.CHUNK_OFFSET;
|
||||
boolean frontToBack = renderType != RenderType.translucent();
|
||||
ObjectListIterator<SectionRenderDispatcher.RenderSection> iterator =
|
||||
this.sections.listIterator(frontToBack ? 0 : this.sections.size());
|
||||
try {
|
||||
while (frontToBack ? iterator.hasNext() : iterator.hasPrevious()) {
|
||||
SectionRenderDispatcher.RenderSection section = frontToBack ? iterator.next() : iterator.previous();
|
||||
if (section.getCompiled().isEmpty(renderType)) {
|
||||
continue;
|
||||
}
|
||||
VertexBuffer buffer = section.getBuffer(renderType);
|
||||
BlockPos origin = section.getOrigin();
|
||||
if (chunkOffset != null) {
|
||||
chunkOffset.set((float) (origin.getX() - cameraPosition.x), (float) (origin.getY() - cameraPosition.y),
|
||||
(float) (origin.getZ() - cameraPosition.z));
|
||||
chunkOffset.upload();
|
||||
}
|
||||
buffer.bind();
|
||||
buffer.draw();
|
||||
}
|
||||
} finally {
|
||||
if (chunkOffset != null) {
|
||||
chunkOffset.set(0.0F, 0.0F, 0.0F);
|
||||
}
|
||||
shader.clear();
|
||||
VertexBuffer.unbind();
|
||||
renderType.clearRenderState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachBlockEntity(Minecraft minecraft, Frustum frustum, Consumer<BlockEntity> consumer) {
|
||||
for (SectionRenderDispatcher.RenderSection section : this.sections) {
|
||||
for (BlockEntity blockEntity : section.getCompiled().getRenderableBlockEntities()) {
|
||||
consumer.accept(blockEntity);
|
||||
}
|
||||
}
|
||||
LevelRendererPortalViewAreaAccessor state = (LevelRendererPortalViewAreaAccessor) minecraft.levelRenderer;
|
||||
synchronized (state.antarchy$getGlobalBlockEntities()) {
|
||||
for (BlockEntity blockEntity : state.antarchy$getGlobalBlockEntities()) {
|
||||
if (frustum.isVisible(new AABB(blockEntity.getBlockPos()).inflate(1.0D))) {
|
||||
consumer.accept(blockEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void queueDirtySections(Minecraft minecraft, ObjectArrayList<SectionRenderDispatcher.RenderSection> sections) {
|
||||
SectionRenderDispatcher dispatcher = minecraft.levelRenderer.getSectionRenderDispatcher();
|
||||
if (dispatcher == null) {
|
||||
return;
|
||||
}
|
||||
RenderRegionCache cache = null;
|
||||
int queued = 0;
|
||||
for (SectionRenderDispatcher.RenderSection section : sections) {
|
||||
if (queued >= MAX_REBUILDS_PER_SCENE) {
|
||||
break;
|
||||
}
|
||||
if (!section.isDirty() || !minecraft.level.getLightEngine().lightOnInSection(SectionPos.of(section.getOrigin()))) {
|
||||
continue;
|
||||
}
|
||||
if (cache == null) {
|
||||
cache = new RenderRegionCache();
|
||||
}
|
||||
section.rebuildSectionAsync(dispatcher, cache);
|
||||
section.setNotDirty();
|
||||
queued++;
|
||||
}
|
||||
}
|
||||
}
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer.sodium;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalTerrain;
|
||||
import com.craisinlord.antarchy.mixins.compat.sodium.RenderSectionManagerAccessor;
|
||||
import com.craisinlord.antarchy.mixins.compat.sodium.SodiumWorldRendererAccessor;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import net.caffeinemc.mods.sodium.client.SodiumClientMod;
|
||||
import net.caffeinemc.mods.sodium.client.gl.device.RenderDevice;
|
||||
import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.TaskQueueType;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.lists.CoordinateSectionVisitor;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.lists.SortedRenderLists;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.lists.TreeSectionCollector;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass;
|
||||
import net.caffeinemc.mods.sodium.client.render.viewport.Viewport;
|
||||
import net.caffeinemc.mods.sodium.client.render.viewport.ViewportProvider;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
public final class SodiumPortalTerrain implements PortalTerrain {
|
||||
private static final int FIRST_PORTAL_FRAME = -1_000_000;
|
||||
private static final int MAX_PENDING_TASKS_PER_QUEUE = 256;
|
||||
private static final Map<TaskQueueType, ArrayDeque<RenderSection>> PENDING_TASKS = new EnumMap<>(TaskQueueType.class);
|
||||
private static int nextFrame = FIRST_PORTAL_FRAME;
|
||||
|
||||
private final SodiumWorldRenderer worldRenderer;
|
||||
private final RenderSectionManager sectionManager;
|
||||
private final SortedRenderLists renderLists;
|
||||
private final int sectionCount;
|
||||
private SortedRenderLists previousRenderLists;
|
||||
private boolean previousEntityCulling;
|
||||
|
||||
private SodiumPortalTerrain(SodiumWorldRenderer worldRenderer, RenderSectionManager sectionManager, SortedRenderLists renderLists, int sectionCount) {
|
||||
this.worldRenderer = worldRenderer;
|
||||
this.sectionManager = sectionManager;
|
||||
this.renderLists = renderLists;
|
||||
this.sectionCount = sectionCount;
|
||||
}
|
||||
|
||||
public static boolean canView(Minecraft minecraft, Vec3 exitCenter) {
|
||||
SodiumWorldRenderer worldRenderer = SodiumWorldRenderer.instanceNullable();
|
||||
if (worldRenderer == null || minecraft.player == null
|
||||
|| ((SodiumWorldRendererAccessor) worldRenderer).antarchy$getRenderSectionManager() == null) {
|
||||
return false;
|
||||
}
|
||||
int limit = minecraft.options.getEffectiveRenderDistance();
|
||||
return Math.abs(SectionPos.posToSectionCoord(exitCenter.x) - minecraft.player.chunkPosition().x) <= limit
|
||||
&& Math.abs(SectionPos.posToSectionCoord(exitCenter.z) - minecraft.player.chunkPosition().z) <= limit;
|
||||
}
|
||||
|
||||
public static PortalTerrain prepare(Minecraft minecraft, Frustum frustum) {
|
||||
SodiumWorldRenderer worldRenderer = SodiumWorldRenderer.instanceNullable();
|
||||
RenderSectionManager sectionManager = worldRenderer == null ? null
|
||||
: ((SodiumWorldRendererAccessor) worldRenderer).antarchy$getRenderSectionManager();
|
||||
if (sectionManager == null) {
|
||||
return EmptyTerrain.INSTANCE;
|
||||
}
|
||||
RenderSectionManagerAccessor manager = (RenderSectionManagerAccessor) sectionManager;
|
||||
int frame = nextFrame--;
|
||||
if (nextFrame > FIRST_PORTAL_FRAME) {
|
||||
nextFrame = FIRST_PORTAL_FRAME;
|
||||
}
|
||||
Viewport viewport = ((ViewportProvider) frustum).sodium$createViewport();
|
||||
TreeSectionCollector collector = new TreeSectionCollector(frame,
|
||||
SodiumClientMod.options().performance.chunkBuildDeferMode.getImportantRebuildQueueType(),
|
||||
manager.antarchy$getSortBehavior().getDeferMode().getImportantRebuildQueueType(),
|
||||
manager.antarchy$getSectionByPosition());
|
||||
int[] visited = {0};
|
||||
CoordinateSectionVisitor apertureFilter = (x, y, z) -> {
|
||||
int minX = SectionPos.sectionToBlockCoord(x);
|
||||
int minY = SectionPos.sectionToBlockCoord(y);
|
||||
int minZ = SectionPos.sectionToBlockCoord(z);
|
||||
if (PortalGunPortalRenderState.shouldRenderBounds(new AABB(minX, minY, minZ, minX + 16, minY + 16, minZ + 16))) {
|
||||
collector.visit(x, y, z);
|
||||
visited[0]++;
|
||||
}
|
||||
};
|
||||
manager.antarchy$getRenderableSectionTree().prepareForTraversal();
|
||||
manager.antarchy$getRenderableSectionTree().traverse(apertureFilter, viewport, manager.antarchy$getSearchDistance());
|
||||
SortedRenderLists renderLists = collector.createRenderLists(viewport);
|
||||
stashPendingTasks(collector.getTaskLists());
|
||||
sectionManager.markGraphDirty();
|
||||
return new SodiumPortalTerrain(worldRenderer, sectionManager, renderLists, visited[0]);
|
||||
}
|
||||
|
||||
public static void drainPendingTasks(Map<TaskQueueType, ArrayDeque<RenderSection>> taskLists) {
|
||||
if (PENDING_TASKS.isEmpty() || taskLists == null) {
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<TaskQueueType, ArrayDeque<RenderSection>> entry : PENDING_TASKS.entrySet()) {
|
||||
ArrayDeque<RenderSection> queue = taskLists.get(entry.getKey());
|
||||
if (queue == null) {
|
||||
continue;
|
||||
}
|
||||
int limit = entry.getKey().queueSizeLimit();
|
||||
for (RenderSection section : entry.getValue()) {
|
||||
if (queue.size() >= limit) {
|
||||
break;
|
||||
}
|
||||
if (!section.isDisposed() && section.getPendingUpdate() != 0 && section.getRunningJob() == null) {
|
||||
queue.add(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
PENDING_TASKS.clear();
|
||||
}
|
||||
|
||||
private static void stashPendingTasks(Map<TaskQueueType, ArrayDeque<RenderSection>> taskLists) {
|
||||
for (Map.Entry<TaskQueueType, ArrayDeque<RenderSection>> entry : taskLists.entrySet()) {
|
||||
if (entry.getValue().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
ArrayDeque<RenderSection> pending = PENDING_TASKS.computeIfAbsent(entry.getKey(), type -> new ArrayDeque<>());
|
||||
for (RenderSection section : entry.getValue()) {
|
||||
if (pending.size() >= MAX_PENDING_TASKS_PER_QUEUE) {
|
||||
break;
|
||||
}
|
||||
pending.add(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sectionCount() {
|
||||
return this.sectionCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(Minecraft minecraft) {
|
||||
RenderSectionManagerAccessor manager = (RenderSectionManagerAccessor) this.sectionManager;
|
||||
SodiumWorldRendererAccessor renderer = (SodiumWorldRendererAccessor) this.worldRenderer;
|
||||
this.previousRenderLists = manager.antarchy$getRenderLists();
|
||||
this.previousEntityCulling = renderer.antarchy$getUseEntityCulling();
|
||||
manager.antarchy$setRenderLists(this.renderLists);
|
||||
renderer.antarchy$setUseEntityCulling(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(Minecraft minecraft) {
|
||||
((RenderSectionManagerAccessor) this.sectionManager).antarchy$setRenderLists(this.previousRenderLists);
|
||||
((SodiumWorldRendererAccessor) this.worldRenderer).antarchy$setUseEntityCulling(this.previousEntityCulling);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachBlockEntity(Minecraft minecraft, Frustum frustum, Consumer<BlockEntity> consumer) {
|
||||
this.worldRenderer.iterateVisibleBlockEntities(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Minecraft minecraft, RenderType renderType, Vec3 cameraPosition, Matrix4f viewMatrix, Matrix4f projection) {
|
||||
TerrainRenderPass[] passes;
|
||||
if (renderType == RenderType.solid()) {
|
||||
passes = new TerrainRenderPass[] {DefaultTerrainRenderPasses.SOLID, DefaultTerrainRenderPasses.CUTOUT};
|
||||
} else if (renderType == RenderType.translucent()) {
|
||||
passes = new TerrainRenderPass[] {DefaultTerrainRenderPasses.TRANSLUCENT};
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
ChunkRenderMatrices matrices = new ChunkRenderMatrices(projection, viewMatrix);
|
||||
RenderDevice.enterManagedCode();
|
||||
try {
|
||||
for (TerrainRenderPass pass : passes) {
|
||||
this.sectionManager.renderLayer(matrices, pass, cameraPosition.x, cameraPosition.y, cameraPosition.z);
|
||||
}
|
||||
} finally {
|
||||
RenderDevice.exitManagedCode();
|
||||
}
|
||||
}
|
||||
|
||||
private enum EmptyTerrain implements PortalTerrain {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int sectionCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(Minecraft minecraft) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(Minecraft minecraft) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Minecraft minecraft, RenderType renderType, Vec3 cameraPosition, Matrix4f viewMatrix, Matrix4f projection) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachBlockEntity(Minecraft minecraft, Frustum frustum, Consumer<BlockEntity> consumer) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -102,7 +102,7 @@ public class DrTrayaurusEntity extends AbstractVillager {
|
||||
protected void updateTrades() {
|
||||
MerchantOffers offers = this.getOffers();
|
||||
offers.clear();
|
||||
offers.addAll(DrTrayaurusTradeManager.createOffers());
|
||||
offers.addAll(DrTrayaurusTradeManager.createOffers(this.registryAccess()));
|
||||
this.overrideXp(1);
|
||||
this.tradesInitialized = true;
|
||||
}
|
||||
|
||||
+57
-17
@@ -6,7 +6,13 @@ import com.google.gson.JsonParseException;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.component.DataComponentPatch;
|
||||
import net.minecraft.core.component.DataComponentPredicate;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
@@ -20,8 +26,10 @@ import net.minecraft.world.item.trading.MerchantOffers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public final class DrTrayaurusTradeManager extends SimpleJsonResourceReloadListener {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Gson GSON = new Gson();
|
||||
private static final String DIRECTORY = "trayaurus_trades";
|
||||
private static final Codec<TradeFile> TRADE_FILE_CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
@@ -47,10 +55,10 @@ public final class DrTrayaurusTradeManager extends SimpleJsonResourceReloadListe
|
||||
loadedTrades = parsedTrades.isEmpty() ? defaultTrades() : List.copyOf(parsedTrades);
|
||||
}
|
||||
|
||||
public static MerchantOffers createOffers() {
|
||||
public static MerchantOffers createOffers(HolderLookup.Provider registries) {
|
||||
MerchantOffers offers = new MerchantOffers();
|
||||
for (TradeEntry trade : loadedTrades) {
|
||||
trade.toOffer().ifPresent(offers::add);
|
||||
trade.toOffer(registries).ifPresent(offers::add);
|
||||
}
|
||||
return offers;
|
||||
}
|
||||
@@ -78,18 +86,18 @@ public final class DrTrayaurusTradeManager extends SimpleJsonResourceReloadListe
|
||||
Codec.FLOAT.optionalFieldOf("price_multiplier", 0.05F).forGetter(TradeEntry::priceMultiplier)
|
||||
).apply(instance, TradeEntry::new));
|
||||
|
||||
private Optional<MerchantOffer> toOffer() {
|
||||
private Optional<MerchantOffer> toOffer(HolderLookup.Provider registries) {
|
||||
if (this.maxUses < 1 || this.villagerXp < 1 || this.villagerXp > 99) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<ItemCost> buyCost = this.buy.toCost();
|
||||
Optional<ItemCost> buyCost = this.buy.toCost(registries);
|
||||
if (buyCost.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<ItemCost> secondBuyCost = this.secondBuy.flatMap(StackEntry::toCost);
|
||||
ItemStack sellStack = this.sell.toStack();
|
||||
Optional<ItemCost> secondBuyCost = this.secondBuy.flatMap(entry -> entry.toCost(registries));
|
||||
ItemStack sellStack = this.sell.toStack(registries);
|
||||
if (sellStack.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -105,28 +113,60 @@ public final class DrTrayaurusTradeManager extends SimpleJsonResourceReloadListe
|
||||
}
|
||||
}
|
||||
|
||||
private record StackEntry(ResourceLocation itemId, int count) {
|
||||
/**
|
||||
* One side of a trade. {@code components} is optional: on {@code sell} it is a data component
|
||||
* patch applied to the result (enchantments, custom name, ...); on {@code buy}/{@code second_buy}
|
||||
* it is a component predicate the offered stack must match exactly for each listed component.
|
||||
* It is kept as raw JSON and parsed per offer because components such as enchantments need
|
||||
* registry access, which the reload listener does not have.
|
||||
*/
|
||||
private record StackEntry(ResourceLocation itemId, int count, Optional<JsonElement> components) {
|
||||
private static final Codec<StackEntry> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
ResourceLocation.CODEC.fieldOf("item").forGetter(StackEntry::itemId),
|
||||
Codec.INT.optionalFieldOf("count", 1).forGetter(StackEntry::count)
|
||||
Codec.INT.optionalFieldOf("count", 1).forGetter(StackEntry::count),
|
||||
ExtraCodecs.JSON.optionalFieldOf("components").forGetter(StackEntry::components)
|
||||
).apply(instance, StackEntry::new));
|
||||
|
||||
private StackEntry(ResourceLocation itemId, int count) {
|
||||
this(itemId, count, Optional.empty());
|
||||
}
|
||||
|
||||
private Optional<Item> item() {
|
||||
return BuiltInRegistries.ITEM.getOptional(this.itemId)
|
||||
.filter(item -> item != net.minecraft.world.item.Items.AIR);
|
||||
}
|
||||
|
||||
private ItemStack toStack() {
|
||||
return this.item()
|
||||
.filter(item -> this.count > 0)
|
||||
.map(item -> new ItemStack(item, this.count))
|
||||
.orElse(ItemStack.EMPTY);
|
||||
private ItemStack toStack(HolderLookup.Provider registries) {
|
||||
Optional<Item> item = this.item().filter(found -> this.count > 0);
|
||||
if (item.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack stack = new ItemStack(item.get(), this.count);
|
||||
if (this.components.isPresent()) {
|
||||
Optional<DataComponentPatch> patch = DataComponentPatch.CODEC
|
||||
.parse(RegistryOps.create(JsonOps.INSTANCE, registries), this.components.get())
|
||||
.resultOrPartial(message -> LOGGER.error("Dr. Trayaurus trade {}: bad components: {}", this.itemId, message));
|
||||
if (patch.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
stack.applyComponents(patch.get());
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
private Optional<ItemCost> toCost() {
|
||||
return this.item()
|
||||
.filter(item -> this.count > 0)
|
||||
.map(item -> new ItemCost(item, this.count));
|
||||
private Optional<ItemCost> toCost(HolderLookup.Provider registries) {
|
||||
Optional<Item> item = this.item().filter(found -> this.count > 0);
|
||||
if (item.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (this.components.isEmpty()) {
|
||||
return Optional.of(new ItemCost(item.get(), this.count));
|
||||
}
|
||||
// A predicate that fails to parse drops the trade rather than accepting any stack.
|
||||
return DataComponentPredicate.CODEC
|
||||
.parse(RegistryOps.create(JsonOps.INSTANCE, registries), this.components.get())
|
||||
.resultOrPartial(message -> LOGGER.error("Dr. Trayaurus trade {}: bad components: {}", this.itemId, message))
|
||||
.map(predicate -> new ItemCost(item.get().builtInRegistryHolder(), this.count, predicate));
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
-11
@@ -357,28 +357,27 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
public PortalCrossing resolveCrossing(Entity entity, AABB previousBox, AABB currentBox) {
|
||||
Vec3 previousProbe = this.teleportProbePosition(entity, previousBox);
|
||||
Vec3 currentProbe = this.teleportProbePosition(entity, currentBox);
|
||||
Vec3 normal = this.getNormalVec().normalize();
|
||||
if (entity instanceof Player && Math.abs(normal.y) < 0.5D) {
|
||||
if (entity instanceof Player) {
|
||||
PortalGunWorldPortalShape shape = this.getWorldPortalShape();
|
||||
double previousDepth = shape.localCoords(previousProbe).depth();
|
||||
double currentDepth = shape.localCoords(currentProbe).depth();
|
||||
double halfBodyDepth = entity.getBbWidth() * 0.5D;
|
||||
if (previousDepth <= 0.0D || currentDepth >= previousDepth - 1.0E-6D
|
||||
|| currentDepth - halfBodyDepth > 0.02D || currentDepth < -shape.halfDepth()) {
|
||||
return null;
|
||||
}
|
||||
Vec3 center = currentBox.getCenter();
|
||||
PortalGunWorldPortalShape.PortalLocalCoords localCenter = shape.localCoords(center);
|
||||
double previousDepth = shape.localCoords(previousBox.getCenter()).depth();
|
||||
double currentDepth = localCenter.depth();
|
||||
double halfX = (currentBox.maxX - currentBox.minX) * 0.5D;
|
||||
double halfY = (currentBox.maxY - currentBox.minY) * 0.5D;
|
||||
double halfZ = (currentBox.maxZ - currentBox.minZ) * 0.5D;
|
||||
double depthExtent = halfX * Math.abs(shape.normal().x) + halfY * Math.abs(shape.normal().y) + halfZ * Math.abs(shape.normal().z);
|
||||
if (previousDepth <= 0.0D || currentDepth >= previousDepth - 1.0E-6D
|
||||
|| currentDepth - depthExtent > 0.02D || currentDepth < -shape.halfDepth()) {
|
||||
return null;
|
||||
}
|
||||
double widthExtent = halfX * Math.abs(shape.right().x) + halfY * Math.abs(shape.right().y) + halfZ * Math.abs(shape.right().z);
|
||||
double heightExtent = halfX * Math.abs(shape.up().x) + halfY * Math.abs(shape.up().y) + halfZ * Math.abs(shape.up().z);
|
||||
if (Math.abs(localCenter.horizontal()) + widthExtent > shape.halfWidth() + 1.0E-3D
|
||||
|| Math.abs(localCenter.vertical()) + heightExtent > shape.halfHeight() + 1.0E-3D) {
|
||||
return null;
|
||||
}
|
||||
return new PortalCrossing(currentProbe, Math.max(0.05D, currentDepth + 0.05D));
|
||||
return new PortalCrossing(currentProbe, Math.max(0.05D, shape.localCoords(currentProbe).depth() + 0.05D));
|
||||
}
|
||||
return this.crossesPortal(previousProbe, currentProbe) ? new PortalCrossing(currentProbe, 0.0D) : null;
|
||||
}
|
||||
@@ -403,10 +402,20 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
}
|
||||
|
||||
public static void teleportEntityAfterMovement(Entity entity, AABB previousBox, Vec3 resolvedMovement) {
|
||||
if (entity instanceof ServerPlayer) {
|
||||
return;
|
||||
}
|
||||
teleportAfterMovement(entity, previousBox, entity.getBoundingBox(), resolvedMovement);
|
||||
}
|
||||
|
||||
public static void teleportPlayerAfterMovementPacket(ServerPlayer player, AABB previousBox, Vec3 claimedMovement) {
|
||||
teleportAfterMovement(player, previousBox, previousBox.move(claimedMovement), claimedMovement);
|
||||
}
|
||||
|
||||
private static void teleportAfterMovement(Entity entity, AABB previousBox, AABB currentBox, Vec3 resolvedMovement) {
|
||||
if (entity.level().isClientSide || !entity.isAlive() || entity.isPassenger() || entity instanceof PortalGunPortalEntity) {
|
||||
return;
|
||||
}
|
||||
AABB currentBox = entity.getBoundingBox();
|
||||
if (previousBox.getCenter().distanceToSqr(currentBox.getCenter()) <= 1.0E-10D) {
|
||||
return;
|
||||
}
|
||||
|
||||
+7
-7
@@ -6,13 +6,15 @@ import org.joml.Vector4f;
|
||||
|
||||
/** Applies the destination portal plane as the near plane of a camera projection. */
|
||||
public final class PortalGunProjectionUtil {
|
||||
public static final double MIN_EYE_PLANE_DISTANCE = 0.01D;
|
||||
|
||||
private PortalGunProjectionUtil() {
|
||||
}
|
||||
|
||||
public static Matrix4f clipAtExit(Matrix4f projection, Vec3 eye, Vec3 look, Vec3 up,
|
||||
Vec3 planePoint, Vec3 planeNormal) {
|
||||
Vector4f clipPlane = planeInCameraSpace(eye, look, up, planePoint, planeNormal);
|
||||
if (clipPlane.lengthSquared() <= 1.0E-6F) {
|
||||
if (clipPlane.w() > -MIN_EYE_PLANE_DISTANCE) {
|
||||
return projection;
|
||||
}
|
||||
Vector4f q = new Vector4f(signNonZero(clipPlane.x()), signNonZero(clipPlane.y()), 1.0F, 1.0F)
|
||||
@@ -42,15 +44,13 @@ public final class PortalGunProjectionUtil {
|
||||
(float) -relativePoint.dot(forward),
|
||||
1.0F
|
||||
);
|
||||
Vec3 unitNormal = planeNormal.normalize();
|
||||
Vector4f normal = new Vector4f(
|
||||
(float) planeNormal.dot(right),
|
||||
(float) planeNormal.dot(correctedUp),
|
||||
(float) -planeNormal.dot(forward),
|
||||
(float) unitNormal.dot(right),
|
||||
(float) unitNormal.dot(correctedUp),
|
||||
(float) -unitNormal.dot(forward),
|
||||
0.0F
|
||||
);
|
||||
if (normal.z() > 0.0F) {
|
||||
normal.mul(-1.0F);
|
||||
}
|
||||
return new Vector4f(normal.x(), normal.y(), normal.z(), -normal.dot(point));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.SodiumCompat;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
@@ -29,18 +28,6 @@ public final class AntarchyMixinPlugin implements IMixinConfigPlugin {
|
||||
if (!classPresent(targetClassName)) {
|
||||
return false;
|
||||
}
|
||||
if (SodiumCompat.isLoaded()
|
||||
&& (mixinClassName.endsWith(".LevelRendererPortalViewAreaAccessor")
|
||||
|| mixinClassName.endsWith(".LevelRendererPortalViewAreaMixin")
|
||||
|| mixinClassName.endsWith(".LevelRendererPortalChunkBudgetMixin")
|
||||
|| mixinClassName.endsWith(".SectionRenderDispatcherPortalUploadsAccessor")
|
||||
|| mixinClassName.endsWith(".PortalViewChunkCacheMixin")
|
||||
|| mixinClassName.endsWith(".PortalViewSectionSortingMixin"))) {
|
||||
return false;
|
||||
}
|
||||
if (mixinClassName.endsWith(".SodiumWorldRendererMixin")) {
|
||||
return SodiumCompat.isLoaded();
|
||||
}
|
||||
if (mixinClassName.startsWith("com.craisinlord.antarchy.mixins.compat.scguns.")) {
|
||||
return classPresent("top.ribs.scguns.entity.projectile.ProjectileEntity");
|
||||
}
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
|
||||
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerGamePacketListenerImpl.class)
|
||||
public abstract class PortalGunPlayerMovePacketMixin {
|
||||
@Unique
|
||||
private static final double MAX_CLAIMED_MOVEMENT_SQR = 100.0D;
|
||||
@Unique
|
||||
private AABB antarchy$portalGunMoveStartBox;
|
||||
@Unique
|
||||
private Vec3 antarchy$portalGunMoveStartPosition;
|
||||
|
||||
@Inject(method = "handleMovePlayer", at = @At("HEAD"))
|
||||
private void antarchy$capturePortalGunMoveStart(ServerboundMovePlayerPacket packet, CallbackInfo ci) {
|
||||
ServerPlayer player = ((ServerGamePacketListenerImpl) (Object) this).player;
|
||||
if (player.getServer() == null || !player.getServer().isSameThread()) {
|
||||
return;
|
||||
}
|
||||
this.antarchy$portalGunMoveStartBox = null;
|
||||
this.antarchy$portalGunMoveStartPosition = null;
|
||||
if (!packet.hasPosition() || ((ServerGamePacketListenerTeleportAccessor) this).antarchy$getAwaitingPositionFromClient() != null) {
|
||||
return;
|
||||
}
|
||||
this.antarchy$portalGunMoveStartBox = player.getBoundingBox();
|
||||
this.antarchy$portalGunMoveStartPosition = player.position();
|
||||
}
|
||||
|
||||
@Inject(method = "handleMovePlayer", at = @At("RETURN"))
|
||||
private void antarchy$teleportPlayerOnPortalCrossing(ServerboundMovePlayerPacket packet, CallbackInfo ci) {
|
||||
AABB startBox = this.antarchy$portalGunMoveStartBox;
|
||||
Vec3 startPosition = this.antarchy$portalGunMoveStartPosition;
|
||||
this.antarchy$portalGunMoveStartBox = null;
|
||||
this.antarchy$portalGunMoveStartPosition = null;
|
||||
if (startBox == null || startPosition == null) {
|
||||
return;
|
||||
}
|
||||
ServerPlayer player = ((ServerGamePacketListenerImpl) (Object) this).player;
|
||||
Vec3 claimedMovement = new Vec3(packet.getX(startPosition.x), packet.getY(startPosition.y), packet.getZ(startPosition.z))
|
||||
.subtract(startPosition);
|
||||
double lengthSqr = claimedMovement.lengthSqr();
|
||||
if (lengthSqr > 1.0E-10D && lengthSqr < MAX_CLAIMED_MOVEMENT_SQR) {
|
||||
PortalGunPortalEntity.teleportPlayerAfterMovementPacket(player, startBox, claimedMovement);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(ServerGamePacketListenerImpl.class)
|
||||
public interface ServerGamePacketListenerTeleportAccessor {
|
||||
@Accessor("awaitingPositionFromClient")
|
||||
Vec3 antarchy$getAwaitingPositionFromClient();
|
||||
}
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalRendererPool;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.chunk.RenderRegionCache;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public abstract class LevelRendererPortalChunkBudgetMixin {
|
||||
@Redirect(
|
||||
method = "compileSections",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher;uploadAllPendingUploads()V")
|
||||
)
|
||||
private void antarchy$budgetPortalUploads(SectionRenderDispatcher dispatcher) {
|
||||
PortalGunPortalRendererPool.uploadPending((LevelRenderer) (Object) this, dispatcher);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "renderLevel",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;pollLightUpdates()V")
|
||||
)
|
||||
private void antarchy$skipProxyLightQueuePoll(ClientLevel level) {
|
||||
if (!PortalGunPortalRendererPool.isProxy((LevelRenderer) (Object) this)) {
|
||||
level.pollLightUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "renderLevel",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I")
|
||||
)
|
||||
private int antarchy$skipProxyLightQueueDrain(LevelLightEngine lightEngine) {
|
||||
return PortalGunPortalRendererPool.isProxy((LevelRenderer) (Object) this) ? 0 : lightEngine.runLightUpdates();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "compileSections",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher;rebuildSectionSync(Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher$RenderSection;Lnet/minecraft/client/renderer/chunk/RenderRegionCache;)V"
|
||||
)
|
||||
)
|
||||
private void antarchy$queuePortalSyncRebuilds(SectionRenderDispatcher dispatcher, SectionRenderDispatcher.RenderSection section, RenderRegionCache cache) {
|
||||
PortalGunPortalRendererPool.rebuildSection((LevelRenderer) (Object) this, dispatcher, section, cache);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "compileSections",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher$RenderSection;rebuildSectionAsync(Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher;Lnet/minecraft/client/renderer/chunk/RenderRegionCache;)V"
|
||||
)
|
||||
)
|
||||
private void antarchy$budgetPortalAsyncRebuilds(SectionRenderDispatcher.RenderSection section, SectionRenderDispatcher dispatcher, RenderRegionCache cache) {
|
||||
PortalGunPortalRendererPool.rebuildSectionAsync((LevelRenderer) (Object) this, dispatcher, section, cache);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "compileSections",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher$RenderSection;setNotDirty()V"
|
||||
)
|
||||
)
|
||||
private void antarchy$keepUnscheduledPortalSectionsDirty(SectionRenderDispatcher.RenderSection section) {
|
||||
PortalGunPortalRendererPool.setNotDirty(section);
|
||||
}
|
||||
}
|
||||
+4
-24
@@ -1,10 +1,6 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewAreaManager;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalRendererPool;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalVisibilityQueries;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalStencilTarget;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
@@ -18,40 +14,24 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
public abstract class LevelRendererPortalLifecycleMixin {
|
||||
@Inject(method = "renderLevel", at = @At("HEAD"))
|
||||
private void antarchy$preparePortalStencil(CallbackInfo ci) {
|
||||
if (PortalGunPortalViewRenderer.isEnabled() && !PortalGunPortalRendererPool.isProxy((LevelRenderer) (Object) this)) {
|
||||
if (PortalGunPortalViewRenderer.isEnabled()) {
|
||||
PortalStencilTarget.prepareMainTarget(Minecraft.getInstance().getMainRenderTarget());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "setLevel", at = @At("HEAD"))
|
||||
private void antarchy$clearPortalViewsOnLevelChange(ClientLevel level, CallbackInfo ci) {
|
||||
if (PortalGunPortalRendererPool.isProxy((LevelRenderer) (Object) this)) {
|
||||
return;
|
||||
}
|
||||
PortalGunPortalRendererPool.clear();
|
||||
PortalGunPortalViewAreaManager.clear();
|
||||
PortalGunPortalVisibilityQueries.clear();
|
||||
PortalGunPortalViewRenderer.releaseTargets();
|
||||
}
|
||||
|
||||
@Inject(method = "close", at = @At("HEAD"))
|
||||
private void antarchy$clearPortalViewsOnClose(CallbackInfo ci) {
|
||||
if (PortalGunPortalRendererPool.isProxy((LevelRenderer) (Object) this)) {
|
||||
return;
|
||||
}
|
||||
PortalGunPortalRendererPool.clear();
|
||||
PortalGunPortalViewAreaManager.clear();
|
||||
PortalGunPortalViewRenderer.releaseTargets();
|
||||
PortalStencilTarget.clear();
|
||||
}
|
||||
|
||||
@Inject(method = "allChanged", at = @At("TAIL"))
|
||||
private void antarchy$clearPortalViewsOnRendererRebuild(CallbackInfo ci) {
|
||||
if (PortalGunPortalRendererPool.isProxy((LevelRenderer) (Object) this)) {
|
||||
return;
|
||||
}
|
||||
if (PortalGunPortalRenderState.getContext() == null) {
|
||||
PortalGunPortalRendererPool.clear();
|
||||
PortalGunPortalViewAreaManager.clear();
|
||||
PortalGunPortalViewRenderer.releaseTargets();
|
||||
}
|
||||
PortalGunPortalViewRenderer.releaseTargets();
|
||||
}
|
||||
}
|
||||
-12
@@ -2,27 +2,15 @@ package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.joml.Matrix4f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public interface LevelRendererPortalSceneInvoker {
|
||||
@Invoker("setupRender")
|
||||
void antarchy$setupPortalScene(Camera camera, Frustum frustum, boolean capturedFrustum, boolean spectator);
|
||||
|
||||
@Invoker("compileSections")
|
||||
void antarchy$compilePortalSections(Camera camera);
|
||||
|
||||
@Invoker("renderSectionLayer")
|
||||
void antarchy$renderPortalSectionLayer(RenderType renderType, double cameraX, double cameraY, double cameraZ, Matrix4f modelViewMatrix, Matrix4f projectionMatrix);
|
||||
|
||||
@Invoker("renderEntity")
|
||||
void antarchy$renderPortalEntity(Entity entity, double cameraX, double cameraY, double cameraZ, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource);
|
||||
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.PostChain;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public interface LevelRendererPortalTargetsAccessor {
|
||||
@Accessor("entityEffect")
|
||||
PostChain antarchy$getEntityEffect();
|
||||
|
||||
@Accessor("transparencyChain")
|
||||
PostChain antarchy$getTransparencyChain();
|
||||
}
|
||||
+5
-32
@@ -1,8 +1,7 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewAreaManager;
|
||||
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalSectionViews;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
@@ -25,39 +24,13 @@ public abstract class LevelRendererPortalViewAreaMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyExpressionValue(method = "setupRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;getX()D"), require = 0)
|
||||
private double antarchy$usePortalCameraX(double original) {
|
||||
PortalGunPortalRenderState.PortalRenderContext context = PortalGunPortalRenderState.getContext();
|
||||
return context == null ? original : context.cameraPos().x;
|
||||
}
|
||||
|
||||
@ModifyExpressionValue(method = "setupRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;getY()D"), require = 0)
|
||||
private double antarchy$usePortalCameraY(double original) {
|
||||
PortalGunPortalRenderState.PortalRenderContext context = PortalGunPortalRenderState.getContext();
|
||||
return context == null ? original : context.cameraPos().y;
|
||||
}
|
||||
|
||||
@ModifyExpressionValue(method = "setupRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;getZ()D"), require = 0)
|
||||
private double antarchy$usePortalCameraZ(double original) {
|
||||
PortalGunPortalRenderState.PortalRenderContext context = PortalGunPortalRenderState.getContext();
|
||||
return context == null ? original : context.cameraPos().z;
|
||||
}
|
||||
|
||||
@Inject(method = "addRecentlyCompiledSection", at = @At("HEAD"), cancellable = true)
|
||||
private void antarchy$routePortalSectionCompile(SectionRenderDispatcher.RenderSection section, CallbackInfo ci) {
|
||||
if (PortalGunPortalViewAreaManager.routeSectionCompiled(section)) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "setSectionDirty(IIIZ)V", at = @At("TAIL"))
|
||||
private void antarchy$dirtyPortalSection(int sectionX, int sectionY, int sectionZ, boolean playerChanged, CallbackInfo ci) {
|
||||
PortalGunPortalViewAreaManager.onSectionDirty(sectionX, sectionY, sectionZ, playerChanged);
|
||||
@Inject(method = "addRecentlyCompiledSection", at = @At("TAIL"))
|
||||
private void antarchy$notifyPortalGraphs(SectionRenderDispatcher.RenderSection section, CallbackInfo ci) {
|
||||
PortalGunPortalSectionViews.onSectionCompiled(section);
|
||||
}
|
||||
|
||||
@Inject(method = "onChunkLoaded", at = @At("TAIL"))
|
||||
private void antarchy$updatePortalChunkGraph(ChunkPos pos, CallbackInfo ci) {
|
||||
PortalGunPortalViewAreaManager.onChunkLoaded(pos);
|
||||
PortalGunPortalSectionViews.onChunkLoaded(pos);
|
||||
}
|
||||
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalSceneRenderer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
public abstract class MinecraftPortalTransparencyMixin {
|
||||
@Inject(method = "useShaderTransparency", at = @At("HEAD"), cancellable = true)
|
||||
private static void antarchy$disableShaderTransparencyInPortalScenes(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (PortalGunPortalSceneRenderer.isRenderingScene()) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewAreaManager;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalSectionViews;
|
||||
import net.minecraft.client.multiplayer.ClientChunkCache;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -12,6 +12,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
public abstract class PortalViewChunkCacheMixin {
|
||||
@Inject(method = "drop", at = @At("TAIL"))
|
||||
private void antarchy$invalidatePortalChunk(ChunkPos pos, CallbackInfo ci) {
|
||||
PortalGunPortalViewAreaManager.onChunkDropped(pos);
|
||||
PortalGunPortalSectionViews.onChunkDropped(pos);
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewAreaManager;
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalViewSectionMarker;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import java.util.Collection;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(SectionRenderDispatcher.RenderSection.class)
|
||||
public abstract class PortalViewSectionSortingMixin implements PortalViewSectionMarker {
|
||||
@Unique
|
||||
private boolean antarchy$portalViewSection;
|
||||
|
||||
@Override
|
||||
public void antarchy$markPortalViewSection() {
|
||||
this.antarchy$portalViewSection = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean antarchy$isPortalViewSection() {
|
||||
return this.antarchy$portalViewSection;
|
||||
}
|
||||
|
||||
@ModifyExpressionValue(method = "createVertexSorting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher;getCameraPosition()Lnet/minecraft/world/phys/Vec3;"))
|
||||
private Vec3 antarchy$sortPortalGeometryFromVirtualCamera(Vec3 original) {
|
||||
return PortalGunPortalViewAreaManager.cameraForSection((SectionRenderDispatcher.RenderSection) (Object) this, original);
|
||||
}
|
||||
|
||||
@Redirect(method = "updateGlobalBlockEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;updateGlobalBlockEntities(Ljava/util/Collection;Ljava/util/Collection;)V"))
|
||||
private void antarchy$routePortalGlobalBlockEntities(LevelRenderer renderer, Collection<BlockEntity> removed, Collection<BlockEntity> added) {
|
||||
if (!PortalGunPortalViewAreaManager.updateGlobalBlockEntities((SectionRenderDispatcher.RenderSection) (Object) this, removed, added)) {
|
||||
renderer.updateGlobalBlockEntities(removed, added);
|
||||
}
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||
import net.minecraft.client.renderer.PostChain;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(PostChain.class)
|
||||
public interface PostChainTargetAccessor {
|
||||
@Accessor("screenTarget")
|
||||
RenderTarget antarchy$getScreenTarget();
|
||||
|
||||
@Mutable
|
||||
@Accessor("screenTarget")
|
||||
void antarchy$setScreenTarget(RenderTarget renderTarget);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.PortalSectionGraphMarker;
|
||||
import net.minecraft.client.renderer.SectionOcclusionGraph;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(SectionOcclusionGraph.class)
|
||||
public abstract class SectionOcclusionGraphPortalMixin implements PortalSectionGraphMarker {
|
||||
@Unique
|
||||
private volatile boolean antarchy$portalGraph;
|
||||
|
||||
@Override
|
||||
public void antarchy$markPortalGraph() {
|
||||
this.antarchy$portalGraph = true;
|
||||
}
|
||||
|
||||
@Inject(method = "getRelativeFrom", at = @At("RETURN"), cancellable = true)
|
||||
private void antarchy$rejectWrappedPortalSections(BlockPos cameraSectionPos, SectionRenderDispatcher.RenderSection section,
|
||||
Direction direction, CallbackInfoReturnable<SectionRenderDispatcher.RenderSection> cir) {
|
||||
if (!this.antarchy$portalGraph) {
|
||||
return;
|
||||
}
|
||||
SectionRenderDispatcher.RenderSection relative = cir.getReturnValue();
|
||||
if (relative != null && !relative.getOrigin().equals(section.getRelativeOrigin(direction))) {
|
||||
cir.setReturnValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import java.util.Queue;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(SectionRenderDispatcher.class)
|
||||
public interface SectionRenderDispatcherPortalUploadsAccessor {
|
||||
@Accessor("toUpload")
|
||||
Queue<Runnable> antarchy$getToUpload();
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.SodiumCompat;
|
||||
import net.minecraft.client.Camera;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Coerce;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Pseudo
|
||||
@Mixin(targets = "net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer", remap = false)
|
||||
public abstract class SodiumWorldRendererMixin {
|
||||
@Inject(method = "setupTerrain", at = @At("HEAD"), remap = false)
|
||||
private void antarchy$captureTerrainSetup(Camera camera, @Coerce Object viewport, boolean spectator, boolean updateChunks, CallbackInfo ci) {
|
||||
SodiumCompat.captureTerrainSetup(camera, viewport, spectator, updateChunks);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.craisinlord.antarchy.mixins.compat.sodium;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.lists.SortedRenderLists;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.SortBehavior;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.tree.RemovableMultiForest;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(value = RenderSectionManager.class, remap = false)
|
||||
public interface RenderSectionManagerAccessor {
|
||||
@Accessor(value = "renderLists", remap = false)
|
||||
SortedRenderLists antarchy$getRenderLists();
|
||||
|
||||
@Accessor(value = "renderLists", remap = false)
|
||||
void antarchy$setRenderLists(SortedRenderLists renderLists);
|
||||
|
||||
@Accessor(value = "renderableSectionTree", remap = false)
|
||||
RemovableMultiForest antarchy$getRenderableSectionTree();
|
||||
|
||||
@Accessor(value = "sectionByPosition", remap = false)
|
||||
Long2ReferenceMap<RenderSection> antarchy$getSectionByPosition();
|
||||
|
||||
@Accessor(value = "sortBehavior", remap = false)
|
||||
SortBehavior antarchy$getSortBehavior();
|
||||
|
||||
@Invoker(value = "getSearchDistance", remap = false)
|
||||
float antarchy$getSearchDistance();
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.craisinlord.antarchy.mixins.compat.sodium;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.renderer.sodium.SodiumPortalTerrain;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Map;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.TaskQueueType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(value = RenderSectionManager.class, remap = false)
|
||||
public abstract class RenderSectionManagerPortalTasksMixin {
|
||||
@Shadow(remap = false)
|
||||
private Map<TaskQueueType, ArrayDeque<RenderSection>> taskLists;
|
||||
|
||||
@Inject(method = "update", at = @At("TAIL"), remap = false)
|
||||
private void antarchy$addPortalViewTasks(CallbackInfo ci) {
|
||||
SodiumPortalTerrain.drainPendingTasks(this.taskLists);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.craisinlord.antarchy.mixins.compat.sodium;
|
||||
|
||||
import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(value = SodiumWorldRenderer.class, remap = false)
|
||||
public interface SodiumWorldRendererAccessor {
|
||||
@Accessor(value = "renderSectionManager", remap = false)
|
||||
RenderSectionManager antarchy$getRenderSectionManager();
|
||||
|
||||
@Accessor(value = "useEntityCulling", remap = false)
|
||||
boolean antarchy$getUseEntityCulling();
|
||||
|
||||
@Accessor(value = "useEntityCulling", remap = false)
|
||||
void antarchy$setUseEntityCulling(boolean useEntityCulling);
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
"AbstractMinecartMixin",
|
||||
"AbstractArrowAccessor",
|
||||
"PortalGunEntityCollisionMixin",
|
||||
"PortalGunPlayerMovePacketMixin",
|
||||
"ServerGamePacketListenerTeleportAccessor",
|
||||
"PortalGunZombieMixin",
|
||||
"FallingBlockEntityAccessor",
|
||||
"AccessorFireBlock",
|
||||
@@ -142,15 +144,14 @@
|
||||
"client.CameraBasisAccessor",
|
||||
"client.LevelRendererPortalViewAreaAccessor",
|
||||
"client.LevelRendererPortalViewAreaMixin",
|
||||
"client.LevelRendererPortalChunkBudgetMixin",
|
||||
"client.SectionRenderDispatcherPortalUploadsAccessor",
|
||||
"client.LevelRendererPortalLifecycleMixin",
|
||||
"client.PortalViewChunkCacheMixin",
|
||||
"client.PortalViewSectionSortingMixin",
|
||||
"client.LevelRendererPortalTargetsAccessor",
|
||||
"client.LevelRendererPortalSceneInvoker",
|
||||
"client.SectionOcclusionGraphPortalMixin",
|
||||
"client.MinecraftPortalTransparencyMixin",
|
||||
"client.EntityRenderDispatcherPortalMixin",
|
||||
"client.BlockEntityRenderDispatcherPortalMixin",
|
||||
"client.MinecraftMainRenderTargetAccessor",
|
||||
"client.PostChainTargetAccessor",
|
||||
"client.AbstractMinecartRendererMixin",
|
||||
"client.EntityLightProbeMixin",
|
||||
"client.CustomBossBarMixin",
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
"plugin": "com.craisinlord.antarchy.mixins.AntarchyMixinPlugin",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"client": [
|
||||
"client.SodiumWorldRendererMixin"
|
||||
"compat.sodium.SodiumWorldRendererAccessor",
|
||||
"compat.sodium.RenderSectionManagerAccessor",
|
||||
"compat.sodium.RenderSectionManagerPortalTasksMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 341 B |
@@ -43,6 +43,11 @@ dependencies {
|
||||
if (providers.gradleProperty('antarchySodiumCompatTest').orNull == 'true') {
|
||||
modLocalRuntime(files("$rootDir/infinite_dimensions_jars/sodium-fabric-0.8.13+mc1.21.1.jar"))
|
||||
}
|
||||
// Sodium — compile-only, for portal live views drawn through Sodium's renderer. Compiled
|
||||
// against the NeoForge build (official Mojang mappings, matching this module's compile
|
||||
// space; Sodium's own classes are identical across loaders). Never bundled.
|
||||
compileOnly(files(zipTree("$rootDir/infinite_dimensions_jars/sodium-neoforge-0.8.13+mc1.21.1.jar")
|
||||
.matching { include "META-INF/jarjar/net.caffeinemc.sodium-neoforge-*-mod.jar" }))
|
||||
modCompileOnly("curse.maven:intapi-${intapi_curseforge_id}:${intapi_curseforge_file_id_fabric}")
|
||||
modLocalRuntime("curse.maven:intapi-${intapi_curseforge_id}:${intapi_curseforge_file_id_fabric}")
|
||||
modLocalRuntime("dev.architectury:architectury-fabric:${architectury_api_version}")
|
||||
|
||||
-2
@@ -5,7 +5,6 @@ import com.craisinlord.antarchy.fabric.registry.AntarchyFabricItems;
|
||||
import com.craisinlord.antarchy.fabric.registry.AntarchyFabricMisc;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.client.PortalGunCrosshairRenderer;
|
||||
import com.craisinlord.antarchy.content.client.CameraShakeClientState;
|
||||
import com.craisinlord.antarchy.content.client.AntarchyArchivePreviews;
|
||||
import com.craisinlord.antarchy.content.client.HerculesBeetleImpactShakeClientState;
|
||||
@@ -626,7 +625,6 @@ public final class AntarchyFabricClientBootstrap {
|
||||
DorrieJumpHudRenderer.render(guiGraphics);
|
||||
HerculesBeetleChargeHudRenderer.render(guiGraphics);
|
||||
com.craisinlord.antarchy.content.client.KingJudgmentFlashHudRenderer.render(guiGraphics);
|
||||
PortalGunCrosshairRenderer.render(guiGraphics);
|
||||
});
|
||||
|
||||
WorldRenderEvents.LAST.register(context -> {
|
||||
|
||||
@@ -49,6 +49,11 @@ dependencies {
|
||||
if (providers.gradleProperty('antarchySodiumCompatTest').orNull == 'true') {
|
||||
runtimeOnly(files(rootProject.file("infinite_dimensions_jars/sodium-neoforge-0.8.13+mc1.21.1.jar")))
|
||||
}
|
||||
// Sodium — compile-only, for portal live views drawn through Sodium's renderer
|
||||
// (content/client/renderer/sodium, mixins/compat/sodium). Never bundled; that code only
|
||||
// loads when Sodium is installed. The published jar nests the mod jar, so compile against it.
|
||||
compileOnly(files(zipTree(rootProject.file("infinite_dimensions_jars/sodium-neoforge-0.8.13+mc1.21.1.jar"))
|
||||
.matching { include "META-INF/jarjar/net.caffeinemc.sodium-neoforge-*-mod.jar" }))
|
||||
compileOnly(files(rootProject.file("infinite_dimensions_jars/antos-neoforge-1.21.1-${antos_version}.jar")))
|
||||
runtimeOnly(files(rootProject.file("infinite_dimensions_jars/antos-neoforge-1.21.1-${antos_version}.jar")))
|
||||
compileOnly("curse.maven:intapi-${intapi_curseforge_id}:${intapi_curseforge_file_id_neoforge}")
|
||||
|
||||
-6
@@ -2,7 +2,6 @@ package com.craisinlord.antarchy.neoforge.client;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.client.GoopedHudRenderer;
|
||||
import com.craisinlord.antarchy.content.client.PortalGunCrosshairRenderer;
|
||||
import com.craisinlord.antarchy.content.client.AntarchyArchivePreviews;
|
||||
import com.craisinlord.antarchy.content.client.game.AntarchyComputerGames;
|
||||
import com.craisinlord.antarchy.content.client.HordeHudRenderer;
|
||||
@@ -385,11 +384,6 @@ public final class AntarchyNeoForgeClient {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerGuiLayers(RegisterGuiLayersEvent event) {
|
||||
event.registerAbove(
|
||||
VanillaGuiLayers.CROSSHAIR,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "portal_gun_crosshair"),
|
||||
(guiGraphics, partialTick) -> PortalGunCrosshairRenderer.render(guiGraphics)
|
||||
);
|
||||
event.registerAboveAll(
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dread_darkness"),
|
||||
(guiGraphics, partialTick) -> DreadHudRenderer.render(guiGraphics)
|
||||
|
||||
Reference in new issue
Block a user