blob: e676ce7641c80b65aee959c3c2538af9c4c53ce0 [file] [log] [blame] [raw]
package net.glowstone.map;
import net.glowstone.GlowServer;
import net.glowstone.ServerProvider;
import net.glowstone.block.GlowBlock;
import net.glowstone.block.MaterialValueManager.ValueCollection;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.map.MapCanvas;
import org.bukkit.map.MapRenderer;
import org.bukkit.map.MapView;
import static net.glowstone.map.GlowMapCanvas.MAP_SIZE;
/**
* Glowstone's built-in map renderer.
*/
public final class GlowMapRenderer extends MapRenderer {
private static final int MAP_SIGHT_DISTANCE_SQUARED = 64 * 64;
private final GlowMapView map;
public GlowMapRenderer(GlowMapView map) {
super(false);
this.map = map;
}
@Override
public void render(MapView map, MapCanvas canvas, Player player) {
World world = map.getWorld();
int scaleShift = map.getScale().getValue();
Location playerLoc = player.getLocation();
int playerX = playerLoc.getBlockX();
int playerZ = playerLoc.getBlockZ();
int cornerX = map.getCenterX() - ((MAP_SIZE / 2) << scaleShift);
int cornerZ = map.getCenterZ() - ((MAP_SIZE / 2) << scaleShift);
for (int pixelX = 0; pixelX < MAP_SIZE; pixelX++) {
for (int pixelY = 0; pixelY < MAP_SIZE; pixelY++) {
int worldX = cornerX + (pixelX << scaleShift);
int worldZ = cornerZ + (pixelY << scaleShift);
if (((worldX - playerX) * (worldX - playerX)
+ (worldZ - playerZ) * (worldZ - playerZ)) < MAP_SIGHT_DISTANCE_SQUARED) {
// TODO: Should the highest block be skipped over if it's e.g. a flower or a
// technical block?
byte blockColor =
colorFor(world.getHighestBlockAt(worldX, worldZ), worldX, worldZ);
canvas.setPixel(pixelX, pixelY, blockColor);
}
}
}
}
/**
* Based on https://minecraft.gamepedia.com/Slime#.22Slime_chunks.22 but simplified (doesn't
* instantiate a Random, and doesn't vary with the world seed. Designed to be reproducible, so
* that updating a map doesn't change the color unless the map contents have changed.
*/
private static byte pseudoRandomShade(int worldX, int worldZ) {
return (byte) ((
((worldX * worldX * 0x4c1906) + (worldX * 0x5ac0db) + ((worldZ * worldZ) * 0x4307a7)
+ (worldZ * 0x5f24f))) % 4);
}
private static byte colorFor(Block block, int worldX, int worldZ) {
// TODO: Some blocks vary in map color based on block states (e.g. wood species)
ValueCollection materialValues;
materialValues = block instanceof GlowBlock ? ((GlowBlock) block).getMaterialValues()
: ((GlowServer) ServerProvider.getServer()).getMaterialValueManager()
.getValues(block.getType());
byte baseColor = materialValues.getBaseMapColor();
return (byte) (baseColor | pseudoRandomShade(worldX, worldZ));
}
}