Code/net/minecraft/world/item/MapItem.java

339 lines
17 KiB
Java

package net.minecraft.world.item;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Multisets;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.SectionPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BiomeTags;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.component.MapPostProcessing;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
public class MapItem extends Item {
public static final int IMAGE_WIDTH = 128;
public static final int IMAGE_HEIGHT = 128;
public MapItem(Item.Properties p_42847_) {
super(p_42847_);
}
public static ItemStack create(ServerLevel p_398211_, int p_42888_, int p_42889_, byte p_42890_, boolean p_42891_, boolean p_42892_) {
ItemStack itemstack = new ItemStack(Items.FILLED_MAP);
MapId mapid = createNewSavedData(p_398211_, p_42888_, p_42889_, p_42890_, p_42891_, p_42892_, p_398211_.dimension());
itemstack.set(DataComponents.MAP_ID, mapid);
return itemstack;
}
@Nullable
public static MapItemSavedData getSavedData(@Nullable MapId p_332257_, Level p_151130_) {
return p_332257_ == null ? null : p_151130_.getMapData(p_332257_);
}
@Nullable
public static MapItemSavedData getSavedData(ItemStack p_42854_, Level p_42855_) {
MapId mapid = p_42854_.get(DataComponents.MAP_ID);
return getSavedData(mapid, p_42855_);
}
private static MapId createNewSavedData(
ServerLevel p_398225_, int p_151122_, int p_151123_, int p_151124_, boolean p_151125_, boolean p_151126_, ResourceKey<Level> p_151127_
) {
MapItemSavedData mapitemsaveddata = MapItemSavedData.createFresh(p_151122_, p_151123_, (byte)p_151124_, p_151125_, p_151126_, p_151127_);
MapId mapid = p_398225_.getFreeMapId();
p_398225_.setMapData(mapid, mapitemsaveddata);
return mapid;
}
public void update(Level p_42894_, Entity p_42895_, MapItemSavedData p_42896_) {
if (p_42894_.dimension() == p_42896_.dimension && p_42895_ instanceof Player) {
int i = 1 << p_42896_.scale;
int j = p_42896_.centerX;
int k = p_42896_.centerZ;
int l = Mth.floor(p_42895_.getX() - j) / i + 64;
int i1 = Mth.floor(p_42895_.getZ() - k) / i + 64;
int j1 = 128 / i;
if (p_42894_.dimensionType().hasCeiling()) {
j1 /= 2;
}
MapItemSavedData.HoldingPlayer mapitemsaveddata$holdingplayer = p_42896_.getHoldingPlayer((Player)p_42895_);
mapitemsaveddata$holdingplayer.step++;
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
BlockPos.MutableBlockPos blockpos$mutableblockpos1 = new BlockPos.MutableBlockPos();
boolean flag = false;
for (int k1 = l - j1 + 1; k1 < l + j1; k1++) {
if ((k1 & 15) == (mapitemsaveddata$holdingplayer.step & 15) || flag) {
flag = false;
double d0 = 0.0;
for (int l1 = i1 - j1 - 1; l1 < i1 + j1; l1++) {
if (k1 >= 0 && l1 >= -1 && k1 < 128 && l1 < 128) {
int i2 = Mth.square(k1 - l) + Mth.square(l1 - i1);
boolean flag1 = i2 > (j1 - 2) * (j1 - 2);
int j2 = (j / i + k1 - 64) * i;
int k2 = (k / i + l1 - 64) * i;
Multiset<MapColor> multiset = LinkedHashMultiset.create();
LevelChunk levelchunk = p_42894_.getChunk(SectionPos.blockToSectionCoord(j2), SectionPos.blockToSectionCoord(k2));
if (!levelchunk.isEmpty()) {
int l2 = 0;
double d1 = 0.0;
if (p_42894_.dimensionType().hasCeiling()) {
int i3 = j2 + k2 * 231871;
i3 = i3 * i3 * 31287121 + i3 * 11;
if ((i3 >> 20 & 1) == 0) {
multiset.add(Blocks.DIRT.defaultBlockState().getMapColor(p_42894_, BlockPos.ZERO), 10);
} else {
multiset.add(Blocks.STONE.defaultBlockState().getMapColor(p_42894_, BlockPos.ZERO), 100);
}
d1 = 100.0;
} else {
for (int i4 = 0; i4 < i; i4++) {
for (int j3 = 0; j3 < i; j3++) {
blockpos$mutableblockpos.set(j2 + i4, 0, k2 + j3);
int k3 = levelchunk.getHeight(
Heightmap.Types.WORLD_SURFACE, blockpos$mutableblockpos.getX(), blockpos$mutableblockpos.getZ()
)
+ 1;
BlockState blockstate;
if (k3 <= p_42894_.getMinY()) {
blockstate = Blocks.BEDROCK.defaultBlockState();
} else {
do {
blockpos$mutableblockpos.setY(--k3);
blockstate = levelchunk.getBlockState(blockpos$mutableblockpos);
} while (
blockstate.getMapColor(p_42894_, blockpos$mutableblockpos) == MapColor.NONE && k3 > p_42894_.getMinY()
);
if (k3 > p_42894_.getMinY() && !blockstate.getFluidState().isEmpty()) {
int l3 = k3 - 1;
blockpos$mutableblockpos1.set(blockpos$mutableblockpos);
BlockState blockstate1;
do {
blockpos$mutableblockpos1.setY(l3--);
blockstate1 = levelchunk.getBlockState(blockpos$mutableblockpos1);
l2++;
} while (l3 > p_42894_.getMinY() && !blockstate1.getFluidState().isEmpty());
blockstate = this.getCorrectStateForFluidBlock(p_42894_, blockstate, blockpos$mutableblockpos);
}
}
p_42896_.checkBanners(p_42894_, blockpos$mutableblockpos.getX(), blockpos$mutableblockpos.getZ());
d1 += (double)k3 / (i * i);
multiset.add(blockstate.getMapColor(p_42894_, blockpos$mutableblockpos));
}
}
}
l2 /= i * i;
MapColor mapcolor = Iterables.getFirst(Multisets.copyHighestCountFirst(multiset), MapColor.NONE);
MapColor.Brightness mapcolor$brightness;
if (mapcolor == MapColor.WATER) {
double d2 = l2 * 0.1 + (k1 + l1 & 1) * 0.2;
if (d2 < 0.5) {
mapcolor$brightness = MapColor.Brightness.HIGH;
} else if (d2 > 0.9) {
mapcolor$brightness = MapColor.Brightness.LOW;
} else {
mapcolor$brightness = MapColor.Brightness.NORMAL;
}
} else {
double d3 = (d1 - d0) * 4.0 / (i + 4) + ((k1 + l1 & 1) - 0.5) * 0.4;
if (d3 > 0.6) {
mapcolor$brightness = MapColor.Brightness.HIGH;
} else if (d3 < -0.6) {
mapcolor$brightness = MapColor.Brightness.LOW;
} else {
mapcolor$brightness = MapColor.Brightness.NORMAL;
}
}
d0 = d1;
if (l1 >= 0 && i2 < j1 * j1 && (!flag1 || (k1 + l1 & 1) != 0)) {
flag |= p_42896_.updateColor(k1, l1, mapcolor.getPackedId(mapcolor$brightness));
}
}
}
}
}
}
}
}
private BlockState getCorrectStateForFluidBlock(Level p_42901_, BlockState p_42902_, BlockPos p_42903_) {
FluidState fluidstate = p_42902_.getFluidState();
return !fluidstate.isEmpty() && !p_42902_.isFaceSturdy(p_42901_, p_42903_, Direction.UP) ? fluidstate.createLegacyBlock() : p_42902_;
}
private static boolean isBiomeWatery(boolean[] p_212252_, int p_212253_, int p_212254_) {
return p_212252_[p_212254_ * 128 + p_212253_];
}
public static void renderBiomePreviewMap(ServerLevel p_42851_, ItemStack p_42852_) {
MapItemSavedData mapitemsaveddata = getSavedData(p_42852_, p_42851_);
if (mapitemsaveddata != null) {
if (p_42851_.dimension() == mapitemsaveddata.dimension) {
int i = 1 << mapitemsaveddata.scale;
int j = mapitemsaveddata.centerX;
int k = mapitemsaveddata.centerZ;
boolean[] aboolean = new boolean[16384];
int l = j / i - 64;
int i1 = k / i - 64;
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
for (int j1 = 0; j1 < 128; j1++) {
for (int k1 = 0; k1 < 128; k1++) {
Holder<Biome> holder = p_42851_.getBiome(blockpos$mutableblockpos.set((l + k1) * i, 0, (i1 + j1) * i));
aboolean[j1 * 128 + k1] = holder.is(BiomeTags.WATER_ON_MAP_OUTLINES);
}
}
for (int j2 = 1; j2 < 127; j2++) {
for (int k2 = 1; k2 < 127; k2++) {
int l2 = 0;
for (int l1 = -1; l1 < 2; l1++) {
for (int i2 = -1; i2 < 2; i2++) {
if ((l1 != 0 || i2 != 0) && isBiomeWatery(aboolean, j2 + l1, k2 + i2)) {
l2++;
}
}
}
MapColor.Brightness mapcolor$brightness = MapColor.Brightness.LOWEST;
MapColor mapcolor = MapColor.NONE;
if (isBiomeWatery(aboolean, j2, k2)) {
mapcolor = MapColor.COLOR_ORANGE;
if (l2 > 7 && k2 % 2 == 0) {
switch ((j2 + (int)(Mth.sin(k2 + 0.0F) * 7.0F)) / 8 % 5) {
case 0:
case 4:
mapcolor$brightness = MapColor.Brightness.LOW;
break;
case 1:
case 3:
mapcolor$brightness = MapColor.Brightness.NORMAL;
break;
case 2:
mapcolor$brightness = MapColor.Brightness.HIGH;
}
} else if (l2 > 7) {
mapcolor = MapColor.NONE;
} else if (l2 > 5) {
mapcolor$brightness = MapColor.Brightness.NORMAL;
} else if (l2 > 3) {
mapcolor$brightness = MapColor.Brightness.LOW;
} else if (l2 > 1) {
mapcolor$brightness = MapColor.Brightness.LOW;
}
} else if (l2 > 0) {
mapcolor = MapColor.COLOR_BROWN;
if (l2 > 3) {
mapcolor$brightness = MapColor.Brightness.NORMAL;
} else {
mapcolor$brightness = MapColor.Brightness.LOWEST;
}
}
if (mapcolor != MapColor.NONE) {
mapitemsaveddata.setColor(j2, k2, mapcolor.getPackedId(mapcolor$brightness));
}
}
}
}
}
}
@Override
public void inventoryTick(ItemStack p_42870_, ServerLevel p_395390_, Entity p_42872_, @Nullable EquipmentSlot p_393433_) {
MapItemSavedData mapitemsaveddata = getSavedData(p_42870_, p_395390_);
if (mapitemsaveddata != null) {
if (p_42872_ instanceof Player player) {
mapitemsaveddata.tickCarriedBy(player, p_42870_);
}
if (!mapitemsaveddata.locked && p_393433_ != null && p_393433_.getType() == EquipmentSlot.Type.HAND) {
this.update(p_395390_, p_42872_, mapitemsaveddata);
}
}
}
@Override
public void onCraftedPostProcess(ItemStack p_42913_, Level p_42914_) {
MapPostProcessing mappostprocessing = p_42913_.remove(DataComponents.MAP_POST_PROCESSING);
if (mappostprocessing != null) {
if (p_42914_ instanceof ServerLevel serverlevel) {
switch (mappostprocessing) {
case LOCK:
lockMap(p_42913_, serverlevel);
break;
case SCALE:
scaleMap(p_42913_, serverlevel);
}
}
}
}
private static void scaleMap(ItemStack p_42857_, ServerLevel p_398209_) {
MapItemSavedData mapitemsaveddata = getSavedData(p_42857_, p_398209_);
if (mapitemsaveddata != null) {
MapId mapid = p_398209_.getFreeMapId();
p_398209_.setMapData(mapid, mapitemsaveddata.scaled());
p_42857_.set(DataComponents.MAP_ID, mapid);
}
}
private static void lockMap(ItemStack p_42899_, ServerLevel p_398218_) {
MapItemSavedData mapitemsaveddata = getSavedData(p_42899_, p_398218_);
if (mapitemsaveddata != null) {
MapId mapid = p_398218_.getFreeMapId();
MapItemSavedData mapitemsaveddata1 = mapitemsaveddata.locked();
p_398218_.setMapData(mapid, mapitemsaveddata1);
p_42899_.set(DataComponents.MAP_ID, mapid);
}
}
@Override
public InteractionResult useOn(UseOnContext p_42885_) {
BlockState blockstate = p_42885_.getLevel().getBlockState(p_42885_.getClickedPos());
if (blockstate.is(BlockTags.BANNERS)) {
if (!p_42885_.getLevel().isClientSide) {
MapItemSavedData mapitemsaveddata = getSavedData(p_42885_.getItemInHand(), p_42885_.getLevel());
if (mapitemsaveddata != null && !mapitemsaveddata.toggleBanner(p_42885_.getLevel(), p_42885_.getClickedPos())) {
return InteractionResult.FAIL;
}
}
return InteractionResult.SUCCESS;
} else {
return super.useOn(p_42885_);
}
}
}