diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMapData.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMapData.java index db92d8248..a440b8135 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMapData.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMapData.java @@ -7,6 +7,6 @@ public interface StationMapData { boolean toggleStation(LevelAccessor level, BlockPos pos, StationTileEntity stationTileEntity); - void loadStationMarker(StationMarker marker); + void addStationMarker(StationMarker marker); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMarker.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMarker.java index 19537e096..fb50df799 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMarker.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMarker.java @@ -3,32 +3,47 @@ package com.simibubi.create.content.logistics.trains.management.edgePoint.statio import java.util.Objects; import java.util.Optional; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix4f; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextComponent; +import net.minecraft.util.Mth; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.saveddata.maps.MapDecoration; +import net.minecraft.world.level.saveddata.maps.MapItemSavedData; public class StationMarker { - private final BlockPos pos; + private final BlockPos source; + private final BlockPos target; private final Component name; - public StationMarker(BlockPos pos, Component name) { - this.pos = pos; + public StationMarker(BlockPos source, BlockPos target, Component name) { + this.source = source; + this.target = target; this.name = name; } public static StationMarker load(CompoundTag tag) { - BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("pos")); + BlockPos source = NbtUtils.readBlockPos(tag.getCompound("source")); + BlockPos target = NbtUtils.readBlockPos(tag.getCompound("target")); Component name = Component.Serializer.fromJson(tag.getString("name")); if (name == null) name = TextComponent.EMPTY; - return new StationMarker(pos, name); + return new StationMarker(source, target, name); } public static StationMarker fromWorld(BlockGetter level, BlockPos pos) { @@ -38,12 +53,13 @@ public class StationMarker { return null; String name = stationOption.get().getStation().name; - return new StationMarker(pos, new TextComponent(name)); + return new StationMarker(pos, TileEntityBehaviour.get(stationOption.get(), TrackTargetingBehaviour.TYPE).getGlobalPosition(), new TextComponent(name)); } public CompoundTag save() { CompoundTag tag = new CompoundTag(); - tag.put("pos", NbtUtils.writeBlockPos(this.pos)); + tag.put("source", NbtUtils.writeBlockPos(this.source)); + tag.put("target", NbtUtils.writeBlockPos(this.target)); tag.putString("name", Component.Serializer.toJson(this.name)); return tag; @@ -56,17 +72,21 @@ public class StationMarker { StationMarker that = (StationMarker) o; - if (!pos.equals(that.pos)) return false; + if (!target.equals(that.target)) return false; return name.equals(that.name); } @Override public int hashCode() { - return Objects.hash(this.pos, this.name); + return Objects.hash(this.target, this.name); } - public BlockPos getPos() { - return this.pos; + public BlockPos getTarget() { + return this.target; + } + + public BlockPos getSource() { + return this.source; } public Component getName() { @@ -74,11 +94,71 @@ public class StationMarker { } public MapDecoration.Type getType() { - //todo replace with own type return MapDecoration.Type.MANSION; } public String getId() { - return "create:station-" + this.pos.getX() + "," + this.pos.getY() + "," + this.pos.getZ(); + return "create:station-" + this.target.getX() + "," + this.target.getY() + "," + this.target.getZ(); + } + + public static class Decoration extends MapDecoration { + + public Decoration(byte pX, byte pY, Component pName) { + super(Type.MANSION, pX, pY, (byte) 0, pName); + } + + @Override + public boolean renderOnFrame() { + return true; + } + + @Override + public boolean render(int index) { + return true; + } + + public boolean render(PoseStack ms, MultiBufferSource bufferSource, int mapId, MapItemSavedData mapData, boolean active, int packedLight, int index) { + ms.pushPose(); + + ms.translate(getX() / 2D + 64.0, getY() / 2D + 64.0, -0.02D); + + ms.pushPose(); + + ms.translate(0.5f, 0f, 0); + ms.scale(4.5F, 4.5F, 3.0F); + + VertexConsumer buffer = bufferSource.getBuffer(RenderType.text(Create.asResource("textures/gui/station_map_icon.png"))); + + float zOffset = -0.001f; + float alpha = 1f; + + Matrix4f mat = ms.last().pose(); + buffer.vertex(mat, -1, -1, zOffset * index).color(1f, 1f, 1f, alpha).uv(0.0f , 0.0f ).uv2(packedLight).endVertex(); + buffer.vertex(mat, -1, 1, zOffset * index).color(1f, 1f, 1f, alpha).uv(0.0f , 0.0f + 1.0f).uv2(packedLight).endVertex(); + buffer.vertex(mat, 1, 1, zOffset * index).color(1f, 1f, 1f, alpha).uv(0.0f + 1.0f, 0.0f + 1.0f).uv2(packedLight).endVertex(); + buffer.vertex(mat, 1, -1, zOffset * index).color(1f, 1f, 1f, alpha).uv(0.0f + 1.0f, 0.0f ).uv2(packedLight).endVertex(); + + ms.popPose(); + + if (getName() != null) { + Font font = Minecraft.getInstance().font; + Component component = getName(); + float f6 = (float)font.width(component); + float f7 = Mth.clamp(25.0F / f6, 0.0F, 6.0F / 9.0F); + ms.pushPose(); + //ms.translate((double)(0.0F + (float)getX() / 2.0F + 64.0F / 2.0F), (double)(0.0F + (float)getY() / 2.0F + 64.0F + 4.0F), (double)-0.025F); + ms.translate(0, 6.0D, -0.005F); + + ms.scale(0.8f, 0.8f, 1.0F); + ms.translate(-f6 / 2f, 0, 0); + //ms.scale(f7, f7, 1.0F); + font.drawInBatch(component, 0.0F, 0.0F, -1, false, ms.last().pose(), bufferSource, false, Integer.MIN_VALUE, 15728880); + ms.popPose(); + } + + ms.popPose(); + + return false; + } } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/MapItemSavedDataMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/MapItemSavedDataMixin.java index 5ebacee3d..ae842bd6b 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/MapItemSavedDataMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/MapItemSavedDataMixin.java @@ -3,8 +3,6 @@ package com.simibubi.create.foundation.mixin; import java.util.Iterator; import java.util.Map; -import javax.annotation.Nullable; - import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -21,7 +19,6 @@ import com.simibubi.create.content.logistics.trains.management.edgePoint.station import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -import net.minecraft.network.chat.Component; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.saveddata.maps.MapDecoration; @@ -42,7 +39,11 @@ public class MapItemSavedDataMixin implements StationMapData { @Shadow public byte scale; - private final Map stationMarkers = Maps.newHashMap(); + @Final + @Shadow + Map decorations; + + private final Map stationMarkers = Maps.newLinkedHashMap(); @Inject( method = "save(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;", @@ -69,19 +70,27 @@ public class MapItemSavedDataMixin implements StationMapData { ListTag listTag = compound.getList("create:stations", 10); for (int k = 0; k < listTag.size(); ++k) { StationMarker stationMarker = StationMarker.load(listTag.getCompound(k)); - stationMapData.loadStationMarker(stationMarker); + stationMapData.addStationMarker(stationMarker); } } @Override - public void loadStationMarker(StationMarker marker) { + public void addStationMarker(StationMarker marker) { stationMarkers.put(marker.getId(), marker); - addDecoration(marker.getType(), null, marker.getId(), marker.getPos().getX(), marker.getPos().getZ(), 180.0D, marker.getName()); - } - @Shadow - private void addDecoration(MapDecoration.Type pType, @Nullable LevelAccessor pLevel, String pDecorationName, double pLevelX, double pLevelZ, double pRotation, @Nullable Component pName) { - throw new AssertionError(); + int scaleMultiplier = 1 << this.scale; + + double localX = ((double) marker.getTarget().getX() - (double) this.x) / (double) scaleMultiplier; + double localZ = ((double) marker.getTarget().getZ() - (double) this.z) / (double) scaleMultiplier; + + if (localX < -63.0D || localX > 63.0D || localZ < -63.0D || localZ > 63.0D) + return; + + byte localXByte = (byte) (int) (localX * 2.0F + 0.5D); + byte localZByte = (byte) (int) (localZ * 2.0F + 0.5D); + + MapDecoration decoration = new StationMarker.Decoration(localXByte, localZByte, marker.getName()); + this.decorations.put(marker.getId(), decoration); } @Shadow @@ -116,8 +125,7 @@ public class MapItemSavedDataMixin implements StationMapData { } if (!this.isTrackedCountOverLimit(256)) { - this.stationMarkers.put(marker.getId(), marker); - this.addDecoration(marker.getType(), level, marker.getId(), xCenter, zCenter, 180.0D, marker.getName()); + addStationMarker(marker); } return false; @@ -128,15 +136,23 @@ public class MapItemSavedDataMixin implements StationMapData { at = @At("RETURN") ) public void checkBanners(BlockGetter pReader, int pX, int pZ, CallbackInfo ci) { + checkStations(pReader, pX, pZ); + } + + private void checkStations(BlockGetter pReader, int pX, int pZ) { Iterator iterator = this.stationMarkers.values().iterator(); while (iterator.hasNext()) { StationMarker marker = iterator.next(); - if (marker.getPos().getX() == pX && marker.getPos().getZ() == pZ) { - StationMarker other = StationMarker.fromWorld(pReader, marker.getPos()); + if (marker.getTarget().getX() == pX && marker.getTarget().getZ() == pZ) { + StationMarker other = StationMarker.fromWorld(pReader, marker.getSource()); if (!marker.equals(other)) { iterator.remove(); this.removeDecoration(marker.getId()); + + if (other != null && marker.getTarget().equals(other.getTarget())) { + addStationMarker(other); + } } } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/MapRendererMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/MapRendererMixin.java new file mode 100644 index 000000000..acf8efad2 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/MapRendererMixin.java @@ -0,0 +1,40 @@ +package com.simibubi.create.foundation.mixin; + +import java.util.Collection; + +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.CallbackInfo; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationMarker; + +import net.minecraft.client.gui.MapRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.level.saveddata.maps.MapDecoration; +import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + +@Mixin(MapRenderer.class) +public class MapRendererMixin { + + @Inject( + method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/level/saveddata/maps/MapItemSavedData;ZI)V", + at = @At("TAIL") + ) + public void render(PoseStack ms, MultiBufferSource buffer, int mapId, MapItemSavedData mapData, boolean active, int packedLight, CallbackInfo ci) { + Iterable decorations = mapData.getDecorations(); + int index = 32; + if (decorations instanceof Collection) { + index = ((Collection) decorations).size(); + } + + for (MapDecoration deco : decorations) { + if (!(deco instanceof StationMarker.Decoration stationDeco)) + continue; + + stationDeco.render(ms, buffer, mapId, mapData, active, packedLight, index++); + } + } + +} diff --git a/src/main/resources/assets/create/textures/gui/station_map_icon.png b/src/main/resources/assets/create/textures/gui/station_map_icon.png new file mode 100644 index 000000000..4ccbcf986 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/station_map_icon.png differ diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 7a3d95863..d362e164e 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -1,32 +1,33 @@ { - "required": true, - "priority": 1100, - "package": "com.simibubi.create.foundation.mixin", - "compatibilityLevel": "JAVA_16", - "refmap": "create.refmap.json", - "mixins": [ - "CustomItemUseEffectsMixin", - "MapItemSavedDataMixin", - "accessor.AbstractProjectileDispenseBehaviorAccessor", - "accessor.DispenserBlockAccessor", - "accessor.FallingBlockEntityAccessor", - "accessor.LivingEntityAccessor", - "accessor.ServerLevelAccessor" - ], - "client": [ - "DestroyProgressMixin", - "EntityContraptionInteractionMixin", - "FixNormalScalingMixin", - "GameRendererMixin", - "HeavyBootsOnPlayerMixin", - "ModelDataRefreshMixin", - "WindowResizeMixin", - "accessor.AgeableListModelAccessor", - "accessor.GameRendererAccessor", - "accessor.ParticleEngineAccessor" - ], - "injectors": { - "defaultRequire": 1 - }, - "minVersion": "0.8" + "required": true, + "priority": 1100, + "package": "com.simibubi.create.foundation.mixin", + "compatibilityLevel": "JAVA_16", + "refmap": "create.refmap.json", + "mixins": [ + "CustomItemUseEffectsMixin", + "MapItemSavedDataMixin", + "accessor.AbstractProjectileDispenseBehaviorAccessor", + "accessor.DispenserBlockAccessor", + "accessor.FallingBlockEntityAccessor", + "accessor.LivingEntityAccessor", + "accessor.ServerLevelAccessor" + ], + "client": [ + "DestroyProgressMixin", + "EntityContraptionInteractionMixin", + "FixNormalScalingMixin", + "GameRendererMixin", + "HeavyBootsOnPlayerMixin", + "MapRendererMixin", + "ModelDataRefreshMixin", + "WindowResizeMixin", + "accessor.AgeableListModelAccessor", + "accessor.GameRendererAccessor", + "accessor.ParticleEngineAccessor" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" }