Rollback immediate placement, make custom terrain regions actually work
This commit is contained in:
parent
566751b77b
commit
79e606f609
@ -221,10 +221,9 @@ data class DungeonDefinition(
|
|||||||
terrainSurfaceSpaceExtends: Int = 0,
|
terrainSurfaceSpaceExtends: Int = 0,
|
||||||
commit: Boolean = true,
|
commit: Boolean = true,
|
||||||
scope: CoroutineScope = Starbound.GLOBAL_SCOPE,
|
scope: CoroutineScope = Starbound.GLOBAL_SCOPE,
|
||||||
immediate: Boolean = false,
|
|
||||||
): CompletableFuture<DungeonWorld> {
|
): CompletableFuture<DungeonWorld> {
|
||||||
require(dungeonID in 0 .. NO_DUNGEON_ID) { "Dungeon ID out of range: $dungeonID" }
|
require(dungeonID in 0 .. NO_DUNGEON_ID) { "Dungeon ID out of range: $dungeonID" }
|
||||||
val dungeonWorld = DungeonWorld(world, random, if (markSurfaceAndTerrain) y else null, terrainSurfaceSpaceExtends, expectedSize = expectedSize, immediate = immediate)
|
val dungeonWorld = DungeonWorld(world, random, if (markSurfaceAndTerrain) y else null, terrainSurfaceSpaceExtends, expectedSize = expectedSize)
|
||||||
|
|
||||||
val validAnchors = anchorParts.filter { world.template.threatLevel in it.minimumThreatLevel .. it.maximumThreatLevel }
|
val validAnchors = anchorParts.filter { world.template.threatLevel in it.minimumThreatLevel .. it.maximumThreatLevel }
|
||||||
|
|
||||||
@ -259,10 +258,9 @@ data class DungeonDefinition(
|
|||||||
terrainSurfaceSpaceExtends: Int = 0,
|
terrainSurfaceSpaceExtends: Int = 0,
|
||||||
commit: Boolean = true,
|
commit: Boolean = true,
|
||||||
scope: CoroutineScope = Starbound.GLOBAL_SCOPE,
|
scope: CoroutineScope = Starbound.GLOBAL_SCOPE,
|
||||||
immediate: Boolean = false
|
|
||||||
): CompletableFuture<DungeonWorld> {
|
): CompletableFuture<DungeonWorld> {
|
||||||
require(anchor in anchorParts) { "$anchor does not belong to $name" }
|
require(anchor in anchorParts) { "$anchor does not belong to $name" }
|
||||||
val dungeonWorld = DungeonWorld(world, random, if (markSurfaceAndTerrain) y else null, terrainSurfaceSpaceExtends, expectedSize = expectedSize, immediate = immediate)
|
val dungeonWorld = DungeonWorld(world, random, if (markSurfaceAndTerrain) y else null, terrainSurfaceSpaceExtends, expectedSize = expectedSize)
|
||||||
|
|
||||||
return scope.async {
|
return scope.async {
|
||||||
generate0(anchor, dungeonWorld, x, y, forcePlacement, dungeonID)
|
generate0(anchor, dungeonWorld, x, y, forcePlacement, dungeonID)
|
||||||
|
@ -53,13 +53,6 @@ class DungeonWorld(
|
|||||||
val markSurfaceLevel: Int? = null,
|
val markSurfaceLevel: Int? = null,
|
||||||
val terrainSurfaceSpaceExtends: Int = 0,
|
val terrainSurfaceSpaceExtends: Int = 0,
|
||||||
expectedSize: Int = 0,
|
expectedSize: Int = 0,
|
||||||
|
|
||||||
/**
|
|
||||||
* Whenever tile changes should be passthrough, if possible
|
|
||||||
* (improved generation speed and memory usage, but expects world chunks to be already
|
|
||||||
* loaded into memory AND no concurrent chunkmap operations are performed)
|
|
||||||
*/
|
|
||||||
val immediate: Boolean = false,
|
|
||||||
) {
|
) {
|
||||||
val geometry = parent.geometry
|
val geometry = parent.geometry
|
||||||
|
|
||||||
@ -94,13 +87,13 @@ class DungeonWorld(
|
|||||||
var hasGenerated = false
|
var hasGenerated = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
val targetChunkState = if (parent.template.worldParameters is FloatingDungeonWorldParameters) ChunkState.FULL else ChunkState.TERRAIN
|
val targetChunkState = if (parent.template.worldParameters is FloatingDungeonWorldParameters) ChunkState.FULL else ChunkState.EMPTY
|
||||||
|
|
||||||
private val liquid = HashMap<Vector2i, AbstractLiquidState>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
private val liquid = HashMap<Vector2i, AbstractLiquidState>(max(8192, expectedSize * 2), 0.5f)
|
||||||
private val foregroundMaterial = HashMap<Vector2i, Material>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
private val foregroundMaterial = HashMap<Vector2i, Material>(max(8192, expectedSize * 2), 0.5f)
|
||||||
private val foregroundModifier = HashMap<Vector2i, Modifier>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
private val foregroundModifier = HashMap<Vector2i, Modifier>(max(8192, expectedSize * 2), 0.5f)
|
||||||
private val backgroundMaterial = HashMap<Vector2i, Material>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
private val backgroundMaterial = HashMap<Vector2i, Material>(max(8192, expectedSize * 2), 0.5f)
|
||||||
private val backgroundModifier = HashMap<Vector2i, Modifier>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
private val backgroundModifier = HashMap<Vector2i, Modifier>(max(8192, expectedSize * 2), 0.5f)
|
||||||
|
|
||||||
// for entity spaces which should be considered empty if they
|
// for entity spaces which should be considered empty if they
|
||||||
// are occupied by tile entity
|
// are occupied by tile entity
|
||||||
@ -109,8 +102,8 @@ class DungeonWorld(
|
|||||||
// entities themselves to be removed
|
// entities themselves to be removed
|
||||||
private val tileEntitiesToRemove = HashSet<TileEntity>(2048, 0.5f)
|
private val tileEntitiesToRemove = HashSet<TileEntity>(2048, 0.5f)
|
||||||
|
|
||||||
val touchedTiles = HashSet<Vector2i>(max(16384, expectedSize), 0.5f)
|
val touchedTiles = HashSet<Vector2i>(max(16384, expectedSize * 4), 0.5f)
|
||||||
val protectTile = HashSet<Vector2i>(max(16384, expectedSize), 0.5f)
|
val protectTile = HashSet<Vector2i>(max(16384, expectedSize * 4), 0.5f)
|
||||||
|
|
||||||
private val boundingBoxes = ArrayList<AABBi>()
|
private val boundingBoxes = ArrayList<AABBi>()
|
||||||
|
|
||||||
@ -276,15 +269,16 @@ class DungeonWorld(
|
|||||||
private val emptyMaterial = Material(AbstractTileState.EMPTY.material, AbstractTileState.EMPTY.hueShift, AbstractTileState.EMPTY.color)
|
private val emptyMaterial = Material(AbstractTileState.EMPTY.material, AbstractTileState.EMPTY.hueShift, AbstractTileState.EMPTY.color)
|
||||||
private val emptyModifier = Modifier(AbstractTileState.EMPTY.modifier, AbstractTileState.EMPTY.modifierHueShift)
|
private val emptyModifier = Modifier(AbstractTileState.EMPTY.modifier, AbstractTileState.EMPTY.modifierHueShift)
|
||||||
|
|
||||||
private fun setCombinedFallback(
|
fun setCombined(
|
||||||
x: Int, y: Int,
|
x: Int, y: Int,
|
||||||
foreground: AbstractTileState?,
|
foreground: AbstractTileState?,
|
||||||
background: AbstractTileState?,
|
background: AbstractTileState?,
|
||||||
liquid: AbstractLiquidState?,
|
liquid: AbstractLiquidState?,
|
||||||
setForegroundMaterial: Boolean,
|
dungeonId: Int? = null,
|
||||||
setForegroundModifier: Boolean,
|
setForegroundMaterial: Boolean = true,
|
||||||
setBackgroundMaterial: Boolean,
|
setForegroundModifier: Boolean = true,
|
||||||
setBackgroundModifier: Boolean,
|
setBackgroundMaterial: Boolean = true,
|
||||||
|
setBackgroundModifier: Boolean = true,
|
||||||
) {
|
) {
|
||||||
val pos = geometry.wrap(Vector2i(x, y))
|
val pos = geometry.wrap(Vector2i(x, y))
|
||||||
|
|
||||||
@ -305,95 +299,17 @@ class DungeonWorld(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (liquid != null) this.liquid[pos] = liquid
|
if (liquid != null) this.liquid[pos] = liquid
|
||||||
}
|
if (dungeonId != null) dungeonIDs[pos] = dungeonId
|
||||||
|
|
||||||
fun setCombined(
|
|
||||||
x: Int, y: Int,
|
|
||||||
foreground: AbstractTileState?,
|
|
||||||
background: AbstractTileState?,
|
|
||||||
liquid: AbstractLiquidState?,
|
|
||||||
dungeonId: Int? = null,
|
|
||||||
setForegroundMaterial: Boolean = true,
|
|
||||||
setForegroundModifier: Boolean = true,
|
|
||||||
setBackgroundMaterial: Boolean = true,
|
|
||||||
setBackgroundModifier: Boolean = true,
|
|
||||||
) {
|
|
||||||
if (immediate) {
|
|
||||||
val cell = parent.getCell(x, y).mutable()
|
|
||||||
if (foreground != null) cell.foreground.from(foreground, setForegroundMaterial, setForegroundModifier)
|
|
||||||
if (background != null) cell.background.from(background, setBackgroundMaterial, setBackgroundModifier)
|
|
||||||
if (liquid != null) cell.liquid.from(liquid)
|
|
||||||
|
|
||||||
cell.dungeonId = dungeonId ?: cell.dungeonId
|
|
||||||
|
|
||||||
if (!parent.setCell(x, y, cell.immutable())) {
|
|
||||||
LOGGER.debug("Cell at $x, $y is out of preloaded bounds for immediate dungeon generator... While this won't affect dungeon generation, it will degrade performance and signify there is a bug somewhere.")
|
|
||||||
|
|
||||||
setCombinedFallback(
|
|
||||||
x = x,
|
|
||||||
y = y,
|
|
||||||
foreground = foreground,
|
|
||||||
background = background,
|
|
||||||
liquid = liquid,
|
|
||||||
setForegroundMaterial = setForegroundMaterial,
|
|
||||||
setForegroundModifier = setForegroundModifier,
|
|
||||||
setBackgroundMaterial = setBackgroundMaterial,
|
|
||||||
setBackgroundModifier = setBackgroundModifier,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val pos = geometry.wrap(Vector2i(x, y))
|
|
||||||
|
|
||||||
if (foreground != null) {
|
|
||||||
if (setForegroundMaterial) this.foregroundMaterial.remove(pos)
|
|
||||||
if (setForegroundModifier) this.foregroundModifier.remove(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (background != null) {
|
|
||||||
if (setBackgroundMaterial) this.backgroundMaterial.remove(pos)
|
|
||||||
if (setBackgroundModifier) this.backgroundModifier.remove(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (liquid != null) this.liquid.remove(pos)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setCombinedFallback(
|
|
||||||
x = x,
|
|
||||||
y = y,
|
|
||||||
foreground = foreground,
|
|
||||||
background = background,
|
|
||||||
liquid = liquid,
|
|
||||||
setForegroundMaterial = setForegroundMaterial,
|
|
||||||
setForegroundModifier = setForegroundModifier,
|
|
||||||
setBackgroundMaterial = setBackgroundMaterial,
|
|
||||||
setBackgroundModifier = setBackgroundModifier,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearTile(x: Int, y: Int) {
|
fun clearTile(x: Int, y: Int) {
|
||||||
val pos = geometry.wrap(Vector2i(x, y))
|
val pos = geometry.wrap(Vector2i(x, y))
|
||||||
|
|
||||||
if (immediate) {
|
this.foregroundMaterial[pos] = emptyMaterial
|
||||||
if (parent.setCell(x, y, AbstractCell.EMPTY)) {
|
this.foregroundModifier[pos] = emptyModifier
|
||||||
this.foregroundMaterial.remove(pos)
|
this.backgroundMaterial[pos] = emptyMaterial
|
||||||
this.foregroundModifier.remove(pos)
|
this.backgroundModifier[pos] = emptyModifier
|
||||||
this.backgroundMaterial.remove(pos)
|
this.liquid[pos] = AbstractLiquidState.EMPTY
|
||||||
this.backgroundModifier.remove(pos)
|
|
||||||
this.liquid.remove(pos)
|
|
||||||
} else {
|
|
||||||
this.foregroundMaterial[pos] = emptyMaterial
|
|
||||||
this.foregroundModifier[pos] = emptyModifier
|
|
||||||
this.backgroundMaterial[pos] = emptyMaterial
|
|
||||||
this.backgroundModifier[pos] = emptyModifier
|
|
||||||
this.liquid[pos] = AbstractLiquidState.EMPTY
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.foregroundMaterial[pos] = emptyMaterial
|
|
||||||
this.foregroundModifier[pos] = emptyModifier
|
|
||||||
this.backgroundMaterial[pos] = emptyMaterial
|
|
||||||
this.backgroundModifier[pos] = emptyModifier
|
|
||||||
this.liquid[pos] = AbstractLiquidState.EMPTY
|
|
||||||
}
|
|
||||||
|
|
||||||
dungeonIDs.remove(pos)
|
dungeonIDs.remove(pos)
|
||||||
}
|
}
|
||||||
@ -623,7 +539,7 @@ class DungeonWorld(
|
|||||||
}.await()
|
}.await()
|
||||||
|
|
||||||
for (box in boundingBoxes) {
|
for (box in boundingBoxes) {
|
||||||
tickets.addAll(parent.permanentChunkTicket(box, targetChunkState).await())
|
tickets.addAll(parent.permanentChunkTicket(box, ChunkState.TERRAIN).await())
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply tiles to world per-chunk
|
// apply tiles to world per-chunk
|
||||||
|
@ -565,20 +565,8 @@ class ServerWorld private constructor(
|
|||||||
|
|
||||||
x = geometry.x.cell(x)
|
x = geometry.x.cell(x)
|
||||||
|
|
||||||
val tickets = ArrayList<ServerChunk.ITicket>()
|
|
||||||
|
|
||||||
val dungeonWorld = try {
|
val dungeonWorld = try {
|
||||||
// if immediate placement will cause issues it can be safely toggled off
|
LOGGER.info("Trying to place dungeon ${dungeon.dungeon.key} at $x, ${dungeon.baseHeight}...")
|
||||||
var immediate = false
|
|
||||||
|
|
||||||
if (dungeon.dungeon.value.anchorParts.size == 1 && dungeon.dungeon.value.partMap.size == 1) {
|
|
||||||
immediate = true
|
|
||||||
LOGGER.info("Trying to immediately place dungeon ${dungeon.dungeon.key} at $x, ${dungeon.baseHeight}...")
|
|
||||||
tickets.addAll(permanentChunkTicket(AABBi.withSide(Vector2i(x, dungeon.baseHeight), dungeon.dungeon.value.anchorParts.first().reader.size), ChunkState.TERRAIN).await())
|
|
||||||
tickets.forEach { it.chunk.await() }
|
|
||||||
} else {
|
|
||||||
LOGGER.info("Trying to place dungeon ${dungeon.dungeon.key} at $x, ${dungeon.baseHeight}...")
|
|
||||||
}
|
|
||||||
|
|
||||||
dungeon.dungeon.value.generate(
|
dungeon.dungeon.value.generate(
|
||||||
this,
|
this,
|
||||||
@ -586,12 +574,10 @@ class ServerWorld private constructor(
|
|||||||
x, dungeon.baseHeight,
|
x, dungeon.baseHeight,
|
||||||
dungeon.blendWithTerrain,
|
dungeon.blendWithTerrain,
|
||||||
dungeon.forcePlacement,
|
dungeon.forcePlacement,
|
||||||
dungeonID = currentDungeonID,
|
dungeonID = currentDungeonID).await()
|
||||||
immediate = immediate).await()
|
|
||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
LOGGER.error("Exception while placing dungeon ${dungeon.dungeon.key} at $x, ${dungeon.baseHeight}", err)
|
LOGGER.error("Exception while placing dungeon ${dungeon.dungeon.key} at $x, ${dungeon.baseHeight}", err)
|
||||||
// continue
|
// continue
|
||||||
tickets.forEach { it.cancel() }
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,11 +247,11 @@ abstract class CoordinateMapper {
|
|||||||
private var cellsEdgeFloat = cellsF
|
private var cellsEdgeFloat = cellsF
|
||||||
|
|
||||||
override fun diff(a: Int, b: Int): Int {
|
override fun diff(a: Int, b: Int): Int {
|
||||||
return (a - b).coerceIn(0, cells)
|
return (a - b).coerceIn(-cells, cells)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun diff(a: Double, b: Double): Double {
|
override fun diff(a: Double, b: Double): Double {
|
||||||
return (a - b).coerceIn(0.0, cellsD)
|
return (a - b).coerceIn(-cellsD, cellsD)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -304,11 +304,11 @@ abstract class CoordinateMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun nearestTo(source: Int, target: Int): Int {
|
override fun nearestTo(source: Int, target: Int): Int {
|
||||||
return diff(source, target)
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nearestTo(source: Double, target: Double): Double {
|
override fun nearestTo(source: Double, target: Double): Double {
|
||||||
return diff(source, target)
|
return target
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user