Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public static void init() {
LOG.info("Debug Logging Enabled: {}", LOG.isDebugEnabled());
LOG.debug("If you can see this while the system property torchmaster.enableDebugLogging is not set to 1, report this on github!");
ModRegistry.initialize();
Services.PLATFORM.getNetwork().registerPayloads();
}

public static Optional<IBlockingLightManager> getRegistryForLevel(Level level)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,46 @@
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.xalcon.torchmaster.Torchmaster;
import net.xalcon.torchmaster.client.MegaTorchScreenOpener;

public class EntityBlockingLightBlock extends Block
{
public static final BooleanProperty OVERLAY_VISIBLE = BooleanProperty.create("overlay_visible");

private final LightType lightType;

public EntityBlockingLightBlock(Properties properties, LightType lightType)
{
super(properties);
this.lightType = lightType;
this.registerDefaultState(this.stateDefinition.any().setValue(OVERLAY_VISIBLE, false));
}

public LightType getLightType()
{
return this.lightType;
}

@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder)
{
super.createBlockStateDefinition(builder);
builder.add(OVERLAY_VISIBLE);
}

@Override
Expand All @@ -36,6 +60,34 @@ public void animateTick(BlockState state, Level level, BlockPos pos, RandomSourc
level.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0f, 0.0f, 0.0f);
}

@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit)
{
if (this.lightType != LightType.MegaTorch)
return InteractionResult.PASS;

if (level.isClientSide)
{
MegaTorchScreenOpener.open(pos);
return InteractionResult.SUCCESS;
}
return InteractionResult.CONSUME;
}

@Override
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit)
{
if (this.lightType != LightType.MegaTorch || player.isShiftKeyDown())
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;

if (level.isClientSide)
{
MegaTorchScreenOpener.open(pos);
return ItemInteractionResult.SUCCESS;
}
return ItemInteractionResult.CONSUME;
}

@Override
public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean moving) {
super.onPlace(state, level, pos, oldState, moving);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package net.xalcon.torchmaster.client;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;

import java.util.ArrayList;
import java.util.List;

public final class MegaTorchOverlayRenderer
{
private static final int OVERLAY_COLOR_ARGB = 0x60_00C800;
private static final double MAX_RENDER_DISTANCE_SQR = 256.0D * 256.0D;
private static final int MAX_OVERLAYS_PER_FRAME = 32;

private MegaTorchOverlayRenderer() {}

public static void render(PoseStack poseStack, Camera camera, Frustum frustum, ClientLevel level, int radius)
{
if (level == null || radius <= 0) return;

Vec3 camPos = camera.getPosition();
List<Candidate> candidates = new ArrayList<>();

OverlayCache.forEach(level.dimension(), (long packed) ->
{
int x = BlockPos.getX(packed);
int y = BlockPos.getY(packed);
int z = BlockPos.getZ(packed);

double minX = x - radius;
double minY = y - radius;
double minZ = z - radius;
double maxX = x + radius + 1;
double maxY = y + radius + 1;
double maxZ = z + radius + 1;

double centerX = (minX + maxX) * 0.5;
double centerY = (minY + maxY) * 0.5;
double centerZ = (minZ + maxZ) * 0.5;

double dx = centerX - camPos.x;
double dy = centerY - camPos.y;
double dz = centerZ - camPos.z;
double distSqr = dx * dx + dy * dy + dz * dz;
if (distSqr > MAX_RENDER_DISTANCE_SQR) return;

AABB aabb = new AABB(minX, minY, minZ, maxX, maxY, maxZ);
if (!frustum.isVisible(aabb)) return;

candidates.add(new Candidate(minX, minY, minZ, maxX, maxY, maxZ, distSqr));
});

if (candidates.isEmpty()) return;

candidates.sort((a, b) -> Double.compare(a.distSqr, b.distSqr));
int limit = Math.min(candidates.size(), MAX_OVERLAYS_PER_FRAME);

MultiBufferSource.BufferSource bufferSource = Minecraft.getInstance().renderBuffers().bufferSource();
VertexConsumer consumer = bufferSource.getBuffer(RangeBoxRenderType.INSTANCE);

poseStack.pushPose();
poseStack.translate(-camPos.x, -camPos.y, -camPos.z);
Matrix4f pose = poseStack.last().pose();

for (int i = 0; i < limit; i++)
{
Candidate c = candidates.get(i);
drawBox(consumer, pose,
(float) c.minX, (float) c.minY, (float) c.minZ,
(float) c.maxX, (float) c.maxY, (float) c.maxZ,
OVERLAY_COLOR_ARGB);
}

poseStack.popPose();
bufferSource.endBatch(RangeBoxRenderType.INSTANCE);
}

private static void drawBox(VertexConsumer c, Matrix4f m,
float x0, float y0, float z0,
float x1, float y1, float z1,
int argb)
{
// Bottom (y = y0)
c.addVertex(m, x0, y0, z0).setColor(argb);
c.addVertex(m, x1, y0, z0).setColor(argb);
c.addVertex(m, x1, y0, z1).setColor(argb);
c.addVertex(m, x0, y0, z1).setColor(argb);

// Top (y = y1)
c.addVertex(m, x0, y1, z0).setColor(argb);
c.addVertex(m, x0, y1, z1).setColor(argb);
c.addVertex(m, x1, y1, z1).setColor(argb);
c.addVertex(m, x1, y1, z0).setColor(argb);

// North (z = z0)
c.addVertex(m, x0, y0, z0).setColor(argb);
c.addVertex(m, x0, y1, z0).setColor(argb);
c.addVertex(m, x1, y1, z0).setColor(argb);
c.addVertex(m, x1, y0, z0).setColor(argb);

// South (z = z1)
c.addVertex(m, x0, y0, z1).setColor(argb);
c.addVertex(m, x1, y0, z1).setColor(argb);
c.addVertex(m, x1, y1, z1).setColor(argb);
c.addVertex(m, x0, y1, z1).setColor(argb);

// West (x = x0)
c.addVertex(m, x0, y0, z0).setColor(argb);
c.addVertex(m, x0, y0, z1).setColor(argb);
c.addVertex(m, x0, y1, z1).setColor(argb);
c.addVertex(m, x0, y1, z0).setColor(argb);

// East (x = x1)
c.addVertex(m, x1, y0, z0).setColor(argb);
c.addVertex(m, x1, y1, z0).setColor(argb);
c.addVertex(m, x1, y1, z1).setColor(argb);
c.addVertex(m, x1, y0, z1).setColor(argb);
}

private record Candidate(double minX, double minY, double minZ,
double maxX, double maxY, double maxZ,
double distSqr) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package net.xalcon.torchmaster.client;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.block.state.BlockState;
import net.xalcon.torchmaster.ModRegistry;
import net.xalcon.torchmaster.blocks.EntityBlockingLightBlock;
import net.xalcon.torchmaster.platform.Services;

public class MegaTorchScreen extends net.minecraft.client.gui.screens.Screen
{
private static final int BUTTON_WIDTH = 200;
private static final int BUTTON_HEIGHT = 20;
private static final int PANEL_WIDTH = 220;
private static final int PANEL_HEIGHT = 130;

private final BlockPos torchPos;
private boolean overlayOn;
private int radius;
private Button toggleButton;

public MegaTorchScreen(BlockPos torchPos)
{
super(Component.translatable("screen.torchmaster.megatorch.title"));
this.torchPos = torchPos.immutable();
}

@Override
protected void init()
{
super.init();

this.radius = Services.PLATFORM.getConfig().getMegaTorchRadius();
this.overlayOn = readCurrentOverlayState();

int centerX = this.width / 2;
int panelTop = (this.height - PANEL_HEIGHT) / 2;

this.toggleButton = Button.builder(toggleLabel(), b -> onToggle())
.bounds(centerX - BUTTON_WIDTH / 2, panelTop + 60, BUTTON_WIDTH, BUTTON_HEIGHT)
.build();
this.addRenderableWidget(this.toggleButton);

this.addRenderableWidget(Button.builder(CommonComponents.GUI_DONE, b -> this.onClose())
.bounds(centerX - BUTTON_WIDTH / 2, panelTop + PANEL_HEIGHT - 28, BUTTON_WIDTH, BUTTON_HEIGHT)
.build());
}

private boolean readCurrentOverlayState()
{
ClientLevel level = Minecraft.getInstance().level;
if (level == null) return false;
BlockState state = level.getBlockState(this.torchPos);
if (!state.is(ModRegistry.blockMegaTorch.get())) return false;
return state.getValue(EntityBlockingLightBlock.OVERLAY_VISIBLE);
}

private void onToggle()
{
ClientLevel level = Minecraft.getInstance().level;
if (level == null) return;

Services.PLATFORM.getNetwork().sendToggleOverlayToServer(this.torchPos);
this.overlayOn = !this.overlayOn;
OverlayCache.toggle(level.dimension(), this.torchPos);
this.toggleButton.setMessage(toggleLabel());
}

private Component toggleLabel()
{
return this.overlayOn
? Component.translatable("screen.torchmaster.megatorch.toggle_on")
: Component.translatable("screen.torchmaster.megatorch.toggle_off");
}

@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick)
{
this.renderBackground(graphics, mouseX, mouseY, partialTick);
super.render(graphics, mouseX, mouseY, partialTick);

int centerX = this.width / 2;
int panelTop = (this.height - PANEL_HEIGHT) / 2;

graphics.drawCenteredString(this.font, this.title, centerX, panelTop + 10, 0xFFFFFFFF);
graphics.drawCenteredString(this.font,
Component.translatable("screen.torchmaster.megatorch.radius", this.radius),
centerX, panelTop + 35, 0xFFCCCCCC);
}

@Override
public boolean isPauseScreen()
{
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package net.xalcon.torchmaster.client;

import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;

public final class MegaTorchScreenOpener
{
private MegaTorchScreenOpener() {}

public static void open(BlockPos pos)
{
Minecraft.getInstance().setScreen(new MegaTorchScreen(pos));
}
}
Loading