Skip to content

Commit a822f0c

Browse files
Pr0metheanMomothereal
authored andcommitted
Implement GlowMapRenderer.render() (#608)
Related to #572
1 parent 7cb4894 commit a822f0c

File tree

5 files changed

+99
-5
lines changed

5 files changed

+99
-5
lines changed

src/main/java/net/glowstone/block/BuiltinMaterialValueManager.java

+5
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,10 @@ public int getFireResistance() {
8989
public double getSlipperiness() {
9090
return 0.6;
9191
}
92+
93+
@Override
94+
public byte getBaseMapColor() {
95+
return ((Number) get("baseMapColor")).byteValue();
96+
}
9297
}
9398
}

src/main/java/net/glowstone/block/MaterialValueManager.java

+8
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,13 @@ interface ValueCollection {
5858
* @return the slipperiness
5959
*/
6060
double getSlipperiness();
61+
62+
/**
63+
* Returns the base map color for this value. Map pixels with this as the highest block can
64+
* be this value plus 0 to 3.
65+
*
66+
* @return the base map color for this material
67+
*/
68+
byte getBaseMapColor();
6169
}
6270
}

src/main/java/net/glowstone/map/GlowMapCanvas.java

+26-4
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,36 @@ public final class GlowMapCanvas implements MapCanvas {
2020
private MapCursorCollection cursors = new MapCursorCollection();
2121
private byte[] base;
2222

23+
/**
24+
* Creates a new GlowMapCanvas for the given {@link MapView} and applies all updates seen by the
25+
* given player.
26+
*
27+
* @param mapView The {@link MapView} to associate with this canvas and render
28+
* @param player The player to pass to {@link MapRenderer#render(MapView, MapCanvas, Player)}
29+
* @return a new, rendered {@link GlowMapCanvas}
30+
*/
2331
public static GlowMapCanvas createAndRender(MapView mapView, Player player) {
2432
GlowMapCanvas out = new GlowMapCanvas(mapView);
25-
for (MapRenderer renderer : mapView.getRenderers()) {
26-
renderer.initialize(mapView);
27-
renderer.render(mapView, out, player);
28-
}
33+
out.update(player);
2934
return out;
3035
}
3136

3237
protected GlowMapCanvas(MapView mapView) {
3338
this.mapView = mapView;
3439
}
3540

41+
/**
42+
* Applies all updates seen by the given player according to the {@link MapView}'s renderers.
43+
*
44+
* @param player The player to pass to {@link MapRenderer#render(MapView, MapCanvas, Player)}
45+
*/
46+
public void update(Player player) {
47+
for (MapRenderer renderer : mapView.getRenderers()) {
48+
renderer.initialize(mapView);
49+
renderer.render(mapView, this, player);
50+
}
51+
}
52+
3653
@Override
3754
public MapView getMapView() {
3855
return mapView;
@@ -93,6 +110,11 @@ public void drawText(int x, int y, MapFont font, String text) {
93110
throw new UnsupportedOperationException("Not supported yet.");
94111
}
95112

113+
/**
114+
* Converts a snapshot of this canvas to a {@link Section} for transmission to the client.
115+
*
116+
* @return a {@link Section} holding a copy of this canvas's contents
117+
*/
96118
public Section toSection() {
97119
return new Section(MAP_SIZE, MAP_SIZE, mapView.getCenterX(), mapView.getCenterZ(), buffer.clone());
98120
}

src/main/java/net/glowstone/map/GlowMapRenderer.java

+51-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
package net.glowstone.map;
22

3+
import static net.glowstone.map.GlowMapCanvas.MAP_SIZE;
4+
5+
import net.glowstone.GlowServer;
6+
import net.glowstone.block.GlowBlock;
7+
import net.glowstone.block.MaterialValueManager.ValueCollection;
8+
import org.bukkit.Bukkit;
9+
import org.bukkit.Location;
10+
import org.bukkit.World;
11+
import org.bukkit.block.Block;
312
import org.bukkit.entity.Player;
413
import org.bukkit.map.MapCanvas;
514
import org.bukkit.map.MapRenderer;
@@ -10,6 +19,7 @@
1019
*/
1120
public final class GlowMapRenderer extends MapRenderer {
1221

22+
private static final int MAP_SIGHT_DISTANCE_SQUARED = 64 * 64;
1323
private final GlowMapView map;
1424

1525
public GlowMapRenderer(GlowMapView map) {
@@ -19,7 +29,47 @@ public GlowMapRenderer(GlowMapView map) {
1929

2030
@Override
2131
public void render(MapView map, MapCanvas canvas, Player player) {
22-
// todo
32+
World world = map.getWorld();
33+
int scaleShift = map.getScale().getValue();
34+
Location playerLoc = player.getLocation();
35+
int playerX = playerLoc.getBlockX();
36+
int playerZ = playerLoc.getBlockZ();
37+
int cornerX = map.getCenterX() - ((MAP_SIZE / 2) << scaleShift);
38+
int cornerZ = map.getCenterZ() - ((MAP_SIZE / 2) << scaleShift);
39+
for (int pixelX = 0; pixelX < MAP_SIZE; pixelX++) {
40+
for (int pixelY = 0; pixelY < MAP_SIZE; pixelY++) {
41+
int worldX = cornerX + (pixelX << scaleShift);
42+
int worldZ = cornerZ + (pixelY << scaleShift);
43+
if (((worldX - playerX) * (worldX - playerX)
44+
+ (worldZ - playerZ) * (worldZ - playerZ)) < MAP_SIGHT_DISTANCE_SQUARED) {
45+
// TODO: Should the highest block be skipped over if it's e.g. a flower or a
46+
// technical block?
47+
byte blockColor =
48+
colorFor(world.getHighestBlockAt(worldX, worldZ), worldX, worldZ);
49+
canvas.setPixel(pixelX, pixelY, blockColor);
50+
}
51+
}
52+
}
53+
}
54+
55+
/**
56+
* Based on https://minecraft.gamepedia.com/Slime#.22Slime_chunks.22 but simplified (doesn't
57+
* instantiate a Random, and doesn't vary with the world seed. Designed to be reproducible, so
58+
* that updating a map doesn't change the color unless the map contents have changed.
59+
*/
60+
private static byte pseudoRandomShade(int worldX, int worldZ) {
61+
return (byte) ((
62+
((worldX * worldX * 0x4c1906) + (worldX * 0x5ac0db) + ((worldZ * worldZ) * 0x4307a7)
63+
+ (worldZ * 0x5f24f))) % 4);
2364
}
2465

66+
private static byte colorFor(Block block, int worldX, int worldZ) {
67+
// TODO: Some blocks vary in map color based on block states (e.g. wood species)
68+
ValueCollection materialValues;
69+
materialValues = block instanceof GlowBlock ? ((GlowBlock) block).getMaterialValues()
70+
: ((GlowServer) Bukkit.getServer()).getMaterialValueManager()
71+
.getValues(block.getType());
72+
byte base_color = materialValues.getBaseMapColor();
73+
return (byte) (base_color | pseudoRandomShade(worldX, worldZ));
74+
}
2575
}

src/main/resources/builtin/materialValues.yml

+9
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,29 @@ default:
44
lightOpacity: 255
55
flameResistance: -1
66
fireResistance: -1
7+
baseMapColor: 44
78
values:
9+
# Incomplete:
10+
# hardness, blastResistance, lightOpacity, flameResistance, fireResistance, baseMapColor
811
AIR:
912
lightOpacity: 0
13+
baseMapColor: 0
1014
STONE:
1115
blastResistance: 30
1216
hardness: 1.5
17+
baseMapColor: 44
1318
GRASS:
1419
blastResistance: 3
1520
hardness: 0.6
21+
baseMapColor: 4
1622
DIRT:
1723
blastResistance: 2.5
1824
hardness: 0.5
25+
baseMapColor: 40
1926
COBBLESTONE:
2027
blastResistance: 30
2128
hardness: 2
29+
baseMapColor: 44
2230
WOOD:
2331
flameResistance: 5
2432
fireResistance: 20
@@ -34,6 +42,7 @@ values:
3442
lightOpacity: 3
3543
hardness: 100
3644
blastResistance: 500
45+
baseMapColor: 48
3746
STATIONARY_WATER:
3847
lightOpacity: 3
3948
hardness: 100

0 commit comments

Comments
 (0)