all mapped out, Part I

- fixed a minor oversight in ProperWaterloggedBlock
- changed tracks material color to metal
- added the ability to add station markers to maps, working similar to banners
This commit is contained in:
zelophed 2022-05-31 15:06:40 +02:00
parent 1b39fd3241
commit e26f47baff
7 changed files with 298 additions and 36 deletions

View file

@ -1443,7 +1443,7 @@ public class AllBlocks {
public static final BlockEntry<TrackBlock> TRACK = REGISTRATE.block("track", TrackBlock::new)
.initialProperties(Material.STONE)
.properties(p -> p.color(MaterialColor.NONE)
.properties(p -> p.color(MaterialColor.METAL)
.strength(0.8F)
.sound(SoundType.METAL)
.noOcclusion())

View file

@ -20,6 +20,8 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.MapItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
@ -31,6 +33,7 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
@ -64,7 +67,7 @@ public class StationBlock extends Block implements ITE<StationTileEntity>, IWren
updateWater(pLevel, pState, pCurrentPos);
return pState;
}
@Override
public FluidState getFluidState(BlockState pState) {
return fluidState(pState);
@ -108,6 +111,25 @@ public class StationBlock extends Block implements ITE<StationTileEntity>, IWren
if (AllItems.WRENCH.isIn(itemInHand))
return InteractionResult.PASS;
if (itemInHand.getItem() == Items.FILLED_MAP) {
return onTileEntityUse(pLevel, pPos, station -> {
if (pLevel.isClientSide)
return InteractionResult.SUCCESS;
if (station.getStation() == null || station.getStation().getId() == null)
return InteractionResult.FAIL;
MapItemSavedData savedData = MapItem.getSavedData(itemInHand, pLevel);
if (!(savedData instanceof StationMapData stationMapData))
return InteractionResult.FAIL;
if (!stationMapData.toggleStation(pLevel, pPos, station))
return InteractionResult.FAIL;
return InteractionResult.SUCCESS;
});
}
InteractionResult result = onTileEntityUse(pLevel, pPos, station -> {
ItemStack autoSchedule = station.getAutoSchedule();
if (autoSchedule.isEmpty())

View file

@ -0,0 +1,12 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelAccessor;
public interface StationMapData {
boolean toggleStation(LevelAccessor level, BlockPos pos, StationTileEntity stationTileEntity);
void loadStationMarker(StationMarker marker);
}

View file

@ -0,0 +1,84 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.util.Objects;
import java.util.Optional;
import com.simibubi.create.AllTileEntities;
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.world.level.BlockGetter;
import net.minecraft.world.level.saveddata.maps.MapDecoration;
public class StationMarker {
private final BlockPos pos;
private final Component name;
public StationMarker(BlockPos pos, Component name) {
this.pos = pos;
this.name = name;
}
public static StationMarker load(CompoundTag tag) {
BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("pos"));
Component name = Component.Serializer.fromJson(tag.getString("name"));
if (name == null) name = TextComponent.EMPTY;
return new StationMarker(pos, name);
}
public static StationMarker fromWorld(BlockGetter level, BlockPos pos) {
Optional<StationTileEntity> stationOption = AllTileEntities.TRACK_STATION.get(level, pos);
if (stationOption.isEmpty() || stationOption.get().getStation() == null)
return null;
String name = stationOption.get().getStation().name;
return new StationMarker(pos, new TextComponent(name));
}
public CompoundTag save() {
CompoundTag tag = new CompoundTag();
tag.put("pos", NbtUtils.writeBlockPos(this.pos));
tag.putString("name", Component.Serializer.toJson(this.name));
return tag;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StationMarker that = (StationMarker) o;
if (!pos.equals(that.pos)) return false;
return name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(this.pos, this.name);
}
public BlockPos getPos() {
return this.pos;
}
public Component getName() {
return name;
}
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();
}
}

View file

@ -20,7 +20,7 @@ import net.minecraft.world.level.material.Fluids;
*/
public interface ProperWaterloggedBlock extends SimpleWaterloggedBlock {
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
default FluidState fluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState();
@ -35,14 +35,13 @@ public interface ProperWaterloggedBlock extends SimpleWaterloggedBlock {
return withWater(ctx.getLevel(), placementState, ctx.getClickedPos());
}
public static BlockState withWater(LevelAccessor level, BlockState placementState, BlockPos pos) {
static BlockState withWater(LevelAccessor level, BlockState placementState, BlockPos pos) {
if (placementState == null)
return null;
if (!(placementState.getBlock() instanceof SimpleWaterloggedBlock))
return null;
return placementState;
FluidState ifluidstate = level.getFluidState(pos);
return placementState.setValue(BlockStateProperties.WATERLOGGED,
Boolean.valueOf(ifluidstate.getType() == Fluids.WATER));
return placementState.setValue(BlockStateProperties.WATERLOGGED, ifluidstate.getType() == Fluids.WATER);
}
}

View file

@ -0,0 +1,144 @@
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;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.google.common.collect.Maps;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationMapData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationMarker;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity;
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;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
@Mixin(MapItemSavedData.class)
public class MapItemSavedDataMixin implements StationMapData {
@Final
@Shadow
public int x;
@Final
@Shadow
public int z;
@Final
@Shadow
public byte scale;
private final Map<String, StationMarker> stationMarkers = Maps.newHashMap();
@Inject(
method = "save(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;",
at = @At("RETURN")
)
public void save(CompoundTag compound, CallbackInfoReturnable<CompoundTag> cir) {
ListTag listTag = new ListTag();
for (StationMarker stationMarker : this.stationMarkers.values()) {
listTag.add(stationMarker.save());
}
cir.getReturnValue().put("create:stations", listTag);
}
@Inject(
method = "load(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/level/saveddata/maps/MapItemSavedData;",
at = @At("RETURN")
)
private static void load(CompoundTag compound, CallbackInfoReturnable<MapItemSavedData> cir) {
MapItemSavedData mapData = cir.getReturnValue();
StationMapData stationMapData = (StationMapData) mapData;
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);
}
}
@Override
public void loadStationMarker(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();
}
@Shadow
private void removeDecoration(String pIdentifier) {
throw new AssertionError();
}
@Shadow
public boolean isTrackedCountOverLimit(int pTrackedCount) {
throw new AssertionError();
}
@Override
public boolean toggleStation(LevelAccessor level, BlockPos pos, StationTileEntity stationTileEntity) {
double xCenter = pos.getX() + 0.5D;
double zCenter = pos.getZ() + 0.5D;
int scaleMultiplier = 1 << this.scale;
double localX = (xCenter - (double) this.x) / (double) scaleMultiplier;
double localZ = (zCenter - (double) this.z) / (double) scaleMultiplier;
if (localX < -63.0D || localX > 63.0D || localZ < -63.0D || localZ > 63.0D)
return false;
StationMarker marker = StationMarker.fromWorld(level, pos);
if (marker == null)
return false;
if (this.stationMarkers.remove(marker.getId(), marker)) {
this.removeDecoration(marker.getId());
return true;
}
if (!this.isTrackedCountOverLimit(256)) {
this.stationMarkers.put(marker.getId(), marker);
this.addDecoration(marker.getType(), level, marker.getId(), xCenter, zCenter, 180.0D, marker.getName());
}
return false;
}
@Inject(
method = "checkBanners(Lnet/minecraft/world/level/BlockGetter;II)V",
at = @At("RETURN")
)
public void checkBanners(BlockGetter pReader, int pX, int pZ, CallbackInfo ci) {
Iterator<StationMarker> 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.equals(other)) {
iterator.remove();
this.removeDecoration(marker.getId());
}
}
}
}
}

View file

@ -1,31 +1,32 @@
{
"required": true,
"priority": 1100,
"package": "com.simibubi.create.foundation.mixin",
"compatibilityLevel": "JAVA_16",
"refmap": "create.refmap.json",
"mixins": [
"CustomItemUseEffectsMixin",
"accessor.AbstractProjectileDispenseBehaviorAccessor",
"accessor.DispenserBlockAccessor",
"accessor.FallingBlockEntityAccessor",
"accessor.ServerLevelAccessor",
"accessor.LivingEntityAccessor"
],
"client": [
"DestroyProgressMixin",
"EntityContraptionInteractionMixin",
"FixNormalScalingMixin",
"HeavyBootsOnPlayerMixin",
"ModelDataRefreshMixin",
"WindowResizeMixin",
"GameRendererMixin",
"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",
"ModelDataRefreshMixin",
"WindowResizeMixin",
"accessor.AgeableListModelAccessor",
"accessor.GameRendererAccessor",
"accessor.ParticleEngineAccessor"
],
"injectors": {
"defaultRequire": 1
},
"minVersion": "0.8"
}