Skip to content

Commit 70c8098

Browse files
committed
Limit the size of a single hires-tile to a reasonable amount
1 parent 216f60a commit 70c8098

File tree

3 files changed

+101
-56
lines changed

3 files changed

+101
-56
lines changed

core/src/main/java/de/bluecolored/bluemap/core/map/hires/ArrayTileModel.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
public class ArrayTileModel implements TileModel {
3434
private static final double GROW_MULTIPLIER = 1.5;
35+
private static final int MAX_CAPACITY = 1000000;
3536

3637
private static final InstancePool<ArrayTileModel> INSTANCE_POOL = new InstancePool<>(
3738
() -> new ArrayTileModel(100),
@@ -373,6 +374,9 @@ private void ensureCapacity(int count) {
373374
int[] _materialIndex = materialIndex;
374375

375376
int newCapacity = (int) (capacity * GROW_MULTIPLIER) + count;
377+
if (newCapacity > MAX_CAPACITY) newCapacity = MAX_CAPACITY;
378+
if (size + count > newCapacity)
379+
throw new MaxCapacityReachedException("Capacity out of range: " + (size + count));
376380
setCapacity(newCapacity);
377381

378382
System.arraycopy(_position, 0, position, 0, size * FI_POSITION);
@@ -387,6 +391,9 @@ private void ensureCapacity(int count) {
387391
}
388392

389393
private void setCapacity(int capacity) {
394+
if (capacity > MAX_CAPACITY)
395+
throw new MaxCapacityReachedException("Capacity out of range: " + capacity);
396+
390397
this.capacity = capacity;
391398

392399
// attributes capacity * per-vertex * per-face

core/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import com.flowpowered.math.vector.Vector3d;
2828
import com.flowpowered.math.vector.Vector3i;
29+
import de.bluecolored.bluemap.core.logger.Logger;
2930
import de.bluecolored.bluemap.core.map.TextureGallery;
3031
import de.bluecolored.bluemap.core.map.TileMetaConsumer;
3132
import de.bluecolored.bluemap.core.map.hires.block.BlockStateModelRenderer;
@@ -58,80 +59,84 @@ public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel
5859
}
5960

6061
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel tileModel, TileMetaConsumer tileMetaConsumer) {
61-
Vector3i min = modelMin.max(renderSettings.getMinPos());
62-
Vector3i max = modelMax.min(renderSettings.getMaxPos());
63-
Vector3i modelAnchor = new Vector3i(modelMin.getX(), 0, modelMin.getZ());
62+
try {
63+
Vector3i min = modelMin.max(renderSettings.getMinPos());
64+
Vector3i max = modelMax.min(renderSettings.getMaxPos());
65+
Vector3i modelAnchor = new Vector3i(modelMin.getX(), 0, modelMin.getZ());
6466

65-
// render blocks
66-
BlockStateModelRenderer blockRenderer = threadLocalBlockRenderer.get();
67-
EntityModelRenderer entityRenderer = threadLocalEntityRenderer.get();
67+
// render blocks
68+
BlockStateModelRenderer blockRenderer = threadLocalBlockRenderer.get();
69+
EntityModelRenderer entityRenderer = threadLocalEntityRenderer.get();
6870

69-
int maxHeight, minY, maxY;
70-
double topBlockLight;
71-
Color columnColor = new Color(), blockColor = new Color();
72-
BlockNeighborhood block = new BlockNeighborhood(new Block(world, 0, 0, 0), resourcePack, renderSettings, world.getDimensionType());
73-
TileModelView tileModelView = new TileModelView(tileModel);
71+
int maxHeight, minY, maxY;
72+
double topBlockLight;
73+
Color columnColor = new Color(), blockColor = new Color();
74+
BlockNeighborhood block = new BlockNeighborhood(new Block(world, 0, 0, 0), resourcePack, renderSettings, world.getDimensionType());
75+
TileModelView tileModelView = new TileModelView(tileModel);
7476

75-
int x, y, z;
76-
for (x = modelMin.getX(); x <= modelMax.getX(); x++){
77-
for (z = modelMin.getZ(); z <= modelMax.getZ(); z++){
77+
int x, y, z;
78+
for (x = modelMin.getX(); x <= modelMax.getX(); x++) {
79+
for (z = modelMin.getZ(); z <= modelMax.getZ(); z++) {
7880

79-
maxHeight = Integer.MIN_VALUE;
80-
topBlockLight = 0;
81+
maxHeight = Integer.MIN_VALUE;
82+
topBlockLight = 0;
8183

82-
columnColor.set(0, 0, 0, 0, true);
84+
columnColor.set(0, 0, 0, 0, true);
8385

84-
if (renderSettings.isInsideRenderBoundaries(x, z)) {
85-
Chunk chunk = world.getChunkAtBlock(x, z);
86-
minY = Math.max(min.getY(), chunk.getMinY(x, z));
87-
maxY = Math.min(max.getY(), chunk.getMaxY(x, z));
86+
if (renderSettings.isInsideRenderBoundaries(x, z)) {
87+
Chunk chunk = world.getChunkAtBlock(x, z);
88+
minY = Math.max(min.getY(), chunk.getMinY(x, z));
89+
maxY = Math.min(max.getY(), chunk.getMaxY(x, z));
8890

89-
for (y = maxY; y >= minY; y--) {
90-
if (x == -1743 && y == 64 && z == 1393)
91-
System.out.println();
91+
for (y = maxY; y >= minY; y--) {
92+
if (x == -1743 && y == 64 && z == 1393)
93+
System.out.println();
9294

93-
block.set(x, y, z);
94-
if (!block.isInsideRenderBounds()) continue;
95+
block.set(x, y, z);
96+
if (!block.isInsideRenderBounds()) continue;
9597

96-
tileModelView.initialize();
98+
tileModelView.initialize();
9799

98-
blockRenderer.render(block, tileModelView, blockColor);
100+
blockRenderer.render(block, tileModelView, blockColor);
99101

100-
//update topBlockLight
101-
topBlockLight = Math.max(topBlockLight, block.getBlockLightLevel() * (1 - columnColor.a));
102+
//update topBlockLight
103+
topBlockLight = Math.max(topBlockLight, block.getBlockLightLevel() * (1 - columnColor.a));
102104

103-
// move block-model to correct position
104-
tileModelView.translate(x - modelAnchor.getX(), y - modelAnchor.getY(), z - modelAnchor.getZ());
105+
// move block-model to correct position
106+
tileModelView.translate(x - modelAnchor.getX(), y - modelAnchor.getY(), z - modelAnchor.getZ());
105107

106-
//update color and height (only if not 100% translucent)
107-
if (blockColor.a > 0) {
108-
if (maxHeight < y) maxHeight = y;
109-
columnColor.underlay(blockColor.premultiplied());
110-
}
108+
//update color and height (only if not 100% translucent)
109+
if (blockColor.a > 0) {
110+
if (maxHeight < y) maxHeight = y;
111+
columnColor.underlay(blockColor.premultiplied());
112+
}
111113

112-
if (renderSettings.isRenderTopOnly() && blockColor.a > 0.999 && block.getProperties().isCulling())
113-
break;
114+
if (renderSettings.isRenderTopOnly() && blockColor.a > 0.999 && block.getProperties().isCulling())
115+
break;
116+
}
114117
}
115-
}
116118

117-
if (maxHeight == Integer.MIN_VALUE)
118-
maxHeight = 0;
119+
if (maxHeight == Integer.MIN_VALUE)
120+
maxHeight = 0;
119121

120-
tileMetaConsumer.set(x, z, columnColor, maxHeight, (int) topBlockLight);
122+
tileMetaConsumer.set(x, z, columnColor, maxHeight, (int) topBlockLight);
123+
}
121124
}
122-
}
123-
124-
// render entities
125-
world.iterateEntities(min.getX(), min.getZ(), max.getX(), max.getZ(), entity -> {
126-
Vector3d pos = entity.getPos();
127-
block.set(pos.getFloorX(), pos.getFloorY(), pos.getFloorZ());
128-
entityRenderer.render(entity, block, tileModelView.initialize());
129-
tileModelView.translate(
130-
(float) pos.getX() - modelAnchor.getX(),
131-
(float) pos.getY() - modelAnchor.getY(),
132-
(float) pos.getZ() - modelAnchor.getZ()
133-
);
134-
});
135125

126+
// render entities
127+
world.iterateEntities(min.getX(), min.getZ(), max.getX(), max.getZ(), entity -> {
128+
Vector3d pos = entity.getPos();
129+
block.set(pos.getFloorX(), pos.getFloorY(), pos.getFloorZ());
130+
entityRenderer.render(entity, block, tileModelView.initialize());
131+
tileModelView.translate(
132+
(float) pos.getX() - modelAnchor.getX(),
133+
(float) pos.getY() - modelAnchor.getY(),
134+
(float) pos.getZ() - modelAnchor.getZ()
135+
);
136+
});
137+
} catch (MaxCapacityReachedException ex) {
138+
Logger.global.noFloodWarning("max-capacity-reached",
139+
"One or more map-tiles are too complex to be completed: " + ex);
140+
}
136141
}
137142
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* This file is part of BlueMap, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package de.bluecolored.bluemap.core.map.hires;
26+
27+
public class MaxCapacityReachedException extends RuntimeException {
28+
29+
public MaxCapacityReachedException(String message) {
30+
super(message);
31+
}
32+
33+
}

0 commit comments

Comments
 (0)