Skip to content
Merged
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
12 changes: 10 additions & 2 deletions src/main/java/dev/xpple/seedmapper/SeedMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import dev.xpple.seedmapper.command.commands.DiscordCommand;
import dev.xpple.seedmapper.command.commands.HighlightCommand;
import dev.xpple.seedmapper.command.commands.LocateCommand;
import dev.xpple.seedmapper.command.commands.MinimapCommand;
import dev.xpple.seedmapper.command.commands.SampleCommand;
import dev.xpple.seedmapper.command.commands.SeedMapCommand;
import dev.xpple.seedmapper.command.commands.SourceCommand;
Expand All @@ -22,6 +23,7 @@
import dev.xpple.seedmapper.config.SeedResolutionAdapter;
import dev.xpple.seedmapper.render.RenderManager;
import dev.xpple.seedmapper.seedmap.MapFeature;
import dev.xpple.seedmapper.seedmap.MinimapManager;
import dev.xpple.seedmapper.util.SeedDatabaseHelper;
import dev.xpple.seedmapper.util.SeedIdentifier;
import dev.xpple.simplewaypoints.api.SimpleWaypointsAPI;
Expand Down Expand Up @@ -80,15 +82,20 @@ public void onInitializeClient() {

SeedDatabaseHelper.fetchSeeds();

KeyMapping keyMapping = KeyBindingHelper.registerKeyBinding(new KeyMapping("key.seedMap", InputConstants.KEY_M, KeyMapping.Category.GAMEPLAY));
KeyMapping seedMapKeyMapping = KeyBindingHelper.registerKeyBinding(new KeyMapping("key.seedMap", InputConstants.KEY_M, KeyMapping.Category.GAMEPLAY));
KeyMapping minimapKeyMapping = KeyBindingHelper.registerKeyBinding(new KeyMapping("key.minimap", InputConstants.KEY_COMMA, KeyMapping.Category.GAMEPLAY));
ClientTickEvents.END_CLIENT_TICK.register(minecraft -> {
while (keyMapping.consumeClick()) {
while (seedMapKeyMapping.consumeClick()) {
minecraft.player.connection.sendCommand("sm:seedmap");
}
while (minimapKeyMapping.consumeClick()) {
minecraft.player.connection.sendCommand("sm:minimap");
}
});

ClientCommandRegistrationCallback.EVENT.register(SeedMapper::registerCommands);
RenderManager.registerEvents();
MinimapManager.registerHudElement();
}

private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext context) {
Expand All @@ -102,5 +109,6 @@ private static void registerCommands(CommandDispatcher<FabricClientCommandSource
SeedMapCommand.register(dispatcher);
DiscordCommand.register(dispatcher);
SampleCommand.register(dispatcher);
MinimapCommand.register(dispatcher);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import net.minecraft.network.chat.Component;
import net.minecraft.server.permissions.PermissionSet;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import org.jspecify.annotations.Nullable;
Expand Down Expand Up @@ -155,11 +156,7 @@ public int getDimension() throws CommandSyntaxException {
return DimensionArgument.dimension().parse(new StringReader(this.getWorld().dimension().identifier().getPath()));
} catch (CommandSyntaxException _) {
}
return switch (this.getWorld().dimensionType().skybox()) {
case NONE -> Cubiomes.DIM_NETHER();
case OVERWORLD -> Cubiomes.DIM_OVERWORLD();
case END -> Cubiomes.DIM_END();
};
return inferDimension(this.getWorld().dimensionType());
}

public int getVersion() throws CommandSyntaxException {
Expand All @@ -180,4 +177,12 @@ public int getGeneratorFlags() throws CommandSyntaxException {
}
return this.getSeed().getSecond().generatorFlags();
}

public static int inferDimension(DimensionType dimensionType) {
return switch (dimensionType.skybox()) {
case NONE -> Cubiomes.DIM_NETHER();
case OVERWORLD -> Cubiomes.DIM_OVERWORLD();
case END -> Cubiomes.DIM_END();
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.xpple.seedmapper.command.commands;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import dev.xpple.seedmapper.command.CustomClientCommandSource;
import dev.xpple.seedmapper.seedmap.MinimapManager;
import dev.xpple.seedmapper.util.SeedIdentifier;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;

import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*;

public class MinimapCommand {

public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register(literal("sm:minimap")
.executes(ctx -> toggle(CustomClientCommandSource.of(ctx.getSource())))
.then(literal("show")
.executes(ctx -> toggle(CustomClientCommandSource.of(ctx.getSource()), true)))
.then(literal("hide")
.executes(ctx -> toggle(CustomClientCommandSource.of(ctx.getSource()), false))));
}

private static int toggle(CustomClientCommandSource source) throws CommandSyntaxException {
return toggle(source, !MinimapManager.isVisible());
}

private static int toggle(CustomClientCommandSource source, boolean show) throws CommandSyntaxException {
if (show) {
SeedIdentifier seed = source.getSeed().getSecond();
int dimension = source.getDimension();
int version = source.getVersion();
int generatorFlags = source.getGeneratorFlags();
MinimapManager.show(seed.seed(), dimension, version, generatorFlags);
return 1;
} else {
MinimapManager.hide();
return 0;
}
}
}
31 changes: 31 additions & 0 deletions src/main/java/dev/xpple/seedmapper/config/Configs.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,37 @@ private static void setPixelsPerBiome(int pixelsPerBiome) {
PixelsPerBiome = Math.clamp(pixelsPerBiome, SeedMapScreen.MIN_PIXELS_PER_BIOME, SeedMapScreen.MAX_PIXELS_PER_BIOME);
}

@Config(setter = @Config.Setter("setMinimapOffsetX"))
public static int MinimapOffsetX = 4;

private static void setMinimapOffsetX(int offsetX) {
MinimapOffsetX = Math.max(0, offsetX);
}

@Config(setter = @Config.Setter("setMinimapOffsetY"))
public static int MinimapOffsetY = 4;

private static void setMinimapOffsetY(int offsetY) {
MinimapOffsetY = Math.max(0, offsetY);
}

@Config(setter = @Config.Setter("setMinimapWidth"))
public static int MinimapWidth = 205;

private static void setMinimapWidth(int width) {
MinimapWidth = Math.clamp(width, 64, 512);
}

@Config(setter = @Config.Setter("setMinimapHeight"))
public static int MinimapHeight = 205;

private static void setMinimapHeight(int height) {
MinimapHeight = Math.clamp(height, 64, 512);
}

@Config
public static boolean RotateMinimap = true;

@Config(chatRepresentation = "listToggledFeatures")
public static EnumSet<MapFeature> ToggledFeatures = Util.make(() -> {
EnumSet<MapFeature> toggledFeatures = EnumSet.allOf(MapFeature.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dev.xpple.seedmapper.mixin;

import dev.xpple.seedmapper.command.CustomClientCommandSource;
import dev.xpple.seedmapper.render.RenderManager;
import dev.xpple.seedmapper.seedmap.MinimapManager;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
Expand All @@ -11,13 +13,16 @@

@Mixin(ClientPacketListener.class)
public class ClientPacketListenerMixin {
@Inject(method = "handleLogin", at = @At("HEAD"))
@Inject(method = "handleLogin", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V", shift = At.Shift.AFTER))
private void onHandleLogin(ClientboundLoginPacket packet, CallbackInfo ci) {
RenderManager.clear();
}

@Inject(method = "handleRespawn", at = @At("HEAD"))
@Inject(method = "handleRespawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V", shift = At.Shift.AFTER))
private void onHandleRespawn(ClientboundRespawnPacket packet, CallbackInfo ci) {
RenderManager.clear();

int dimension = CustomClientCommandSource.inferDimension(packet.commonPlayerSpawnInfo().dimensionType().value());
MinimapManager.updateDimension(dimension);
}
}
59 changes: 59 additions & 0 deletions src/main/java/dev/xpple/seedmapper/seedmap/MinimapManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package dev.xpple.seedmapper.seedmap;

import dev.xpple.seedmapper.SeedMapper;
import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.resources.Identifier;
import org.jetbrains.annotations.Nullable;

public final class MinimapManager {
private MinimapManager() {
}

private static @Nullable MinimapScreen minimapScreen;

public static void registerHudElement() {
HudElementRegistry.addLast(Identifier.fromNamespaceAndPath(SeedMapper.MOD_ID, "minimap"), MinimapManager::render);
}

public static boolean isVisible() {
return minimapScreen != null;
}

public static void show(long seed, int dimension, int version, int generatorFlags) {
hide();
minimapScreen = new MinimapScreen(seed, dimension, version, generatorFlags);
}

public static void hide() {
if (minimapScreen != null) {
if (minimapScreen.isInitialized()) {
minimapScreen.onClose();
}
minimapScreen = null;
}
}

public static void updateDimension(int dimension) {
if (minimapScreen == null) {
return;
}
if (minimapScreen.getDimension() == dimension) {
return;
}
show(minimapScreen.getSeed(), dimension, minimapScreen.getVersion(), minimapScreen.getGeneratorFlags());
}

private static void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) {
if (minimapScreen == null) {
return;
}
Minecraft minecraft = Minecraft.getInstance();
LocalPlayer player = minecraft.player;
minimapScreen.update(player.position(), player.getRotationVector());
minimapScreen.renderToHud(guiGraphics, deltaTracker.getGameTimeDeltaTicks());
}
}
111 changes: 111 additions & 0 deletions src/main/java/dev/xpple/seedmapper/seedmap/MinimapScreen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package dev.xpple.seedmapper.seedmap;

import dev.xpple.seedmapper.config.Configs;
import dev.xpple.seedmapper.util.QuartPos2f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;

// TODO refactor so that the minimap is not a `Screen`; it has no reason to be one
public class MinimapScreen extends SeedMapScreen {

private boolean initialized = false;
private int lastWidth = -1;
private int lastHeight = -1;

public MinimapScreen(long seed, int dimension, int version, int generatorFlags) {
super(seed, dimension, version, generatorFlags, Minecraft.getInstance().player.blockPosition(), Minecraft.getInstance().player.getRotationVector());
}

public void initForOverlay(int width, int height) {
if (this.initialized && width == this.lastWidth && height == this.lastHeight) {
return;
}
this.init(width, height);
this.initialized = true;
this.lastWidth = width;
this.lastHeight = height;
}

public void renderToHud(GuiGraphics guiGraphics, float partialTick) {
boolean rotateMinimap = Configs.RotateMinimap;
int contentWidth = Configs.MinimapWidth;
int contentHeight = Configs.MinimapHeight;
int renderContentWidth = contentWidth;
int renderContentHeight = contentHeight;
if (rotateMinimap) {
int diagonal = Mth.ceil(Math.sqrt(contentWidth * contentWidth + contentHeight * contentHeight));
renderContentWidth = diagonal;
renderContentHeight = diagonal;
}
// ensures super.seedMapWidth == renderContentWidth
int renderWidth = renderContentWidth + 2 * this.horizontalPadding();
// ensures super.seedMapHeight == renderContentHeight
int renderHeight = renderContentHeight + 2 * this.verticalPadding();

this.initForOverlay(renderWidth, renderHeight);

guiGraphics.enableScissor(this.horizontalPadding(), this.verticalPadding(), this.horizontalPadding() + contentWidth, this.verticalPadding() + contentHeight);

var pose = guiGraphics.pose();
pose.pushMatrix();
if (rotateMinimap) {
pose.translate(-this.centerX + (float) (this.horizontalPadding() + contentWidth / 2), -this.centerY + (float) (this.verticalPadding() + contentHeight / 2));
pose.translate(this.centerX, this.centerY);
pose.rotate((float) (-Math.toRadians(this.getPlayerRotation().y) + Math.PI));
pose.translate(-this.centerX, -this.centerY);
}
this.renderBiomes(guiGraphics, Integer.MIN_VALUE, Integer.MIN_VALUE, partialTick);

this.renderFeatures(guiGraphics, Integer.MIN_VALUE, Integer.MIN_VALUE, partialTick);
pose.popMatrix();

if (Configs.RotateMinimap) {
this.drawCenterCross(guiGraphics, this.horizontalPadding() + contentWidth / 2, this.verticalPadding() + contentHeight / 2);
}

guiGraphics.disableScissor();
}

private void drawCenterCross(GuiGraphics guiGraphics, int centerX, int centerY) {
int crossHalf = 3;
int color = 0xFF_FFFFFF;
guiGraphics.fill(centerX - crossHalf, centerY, centerX + crossHalf + 1, centerY + 1, color);
guiGraphics.fill(centerX, centerY - crossHalf, centerX + 1, centerY + crossHalf + 1, color);
}

public void update(Vec3 pos, Vec2 playerRotation) {
this.updatePlayerPosition(BlockPos.containing(pos));
this.updatePlayerRotation(playerRotation);
this.moveCenter(QuartPos2f.fromVec3(pos));
}

public boolean isInitialized() {
return this.initialized;
}

@Override
protected void drawPlayerIndicator(GuiGraphics guiGraphics) {
if (!Configs.RotateMinimap) {
this.drawDirectionArrow(guiGraphics, this.centerX - 10, this.centerY - 10);
}
}

@Override
protected boolean isMinimap() {
return true;
}

@Override
protected int horizontalPadding() {
return Configs.MinimapOffsetX;
}

@Override
protected int verticalPadding() {
return Configs.MinimapOffsetY;
}
}
Loading