Immediate dungeon placement
This commit is contained in:
parent
161d19f263
commit
566751b77b
@ -259,7 +259,7 @@ public class DirectCallExecutor {
|
|||||||
*/
|
*/
|
||||||
public Object[] resume(Continuation continuation)
|
public Object[] resume(Continuation continuation)
|
||||||
throws CallException, CallPausedException, InterruptedException {
|
throws CallException, CallPausedException, InterruptedException {
|
||||||
return execute(continuation, schedulingContextFactory.newInstance(), performJavaConversions);
|
return execute(continuation, schedulingContextFactory.newInstance(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Result implements CallEventHandler {
|
private static class Result implements CallEventHandler {
|
||||||
|
@ -29,6 +29,8 @@ import ru.dbotthepony.kstarbound.json.builder.JsonIgnore
|
|||||||
import ru.dbotthepony.kstarbound.util.random.random
|
import ru.dbotthepony.kstarbound.util.random.random
|
||||||
import ru.dbotthepony.kstarbound.world.Direction
|
import ru.dbotthepony.kstarbound.world.Direction
|
||||||
import ru.dbotthepony.kstarbound.world.api.AbstractLiquidState
|
import ru.dbotthepony.kstarbound.world.api.AbstractLiquidState
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.AbstractTileState
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.ImmutableTileState
|
||||||
import ru.dbotthepony.kstarbound.world.api.MutableLiquidState
|
import ru.dbotthepony.kstarbound.world.api.MutableLiquidState
|
||||||
import ru.dbotthepony.kstarbound.world.api.TileColor
|
import ru.dbotthepony.kstarbound.world.api.TileColor
|
||||||
|
|
||||||
@ -90,13 +92,7 @@ abstract class DungeonBrush {
|
|||||||
return
|
return
|
||||||
|
|
||||||
// TODO: delete objects too?
|
// TODO: delete objects too?
|
||||||
world.setLiquid(x, y, AbstractLiquidState.EMPTY)
|
world.clearTile(x, y)
|
||||||
world.setForeground(x, y, BuiltinMetaMaterials.EMPTY)
|
|
||||||
world.setForeground(x, y, BuiltinMetaMaterials.EMPTY_MOD)
|
|
||||||
world.setBackground(x, y, BuiltinMetaMaterials.EMPTY)
|
|
||||||
world.setBackground(x, y, BuiltinMetaMaterials.EMPTY_MOD)
|
|
||||||
|
|
||||||
world.setDungeonID(x, y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@ -145,24 +141,19 @@ abstract class DungeonBrush {
|
|||||||
val colorVariant: String = "0", // HOLY FUCKING SHIT
|
val colorVariant: String = "0", // HOLY FUCKING SHIT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val state by lazy {
|
||||||
|
ImmutableTileState(material.orEmptyTile, modifier.orEmptyModifier, color, hueShift, modHueShift)
|
||||||
|
}
|
||||||
|
|
||||||
override fun execute(x: Int, y: Int, phase: Phase, world: DungeonWorld) {
|
override fun execute(x: Int, y: Int, phase: Phase, world: DungeonWorld) {
|
||||||
if (phase !== Phase.PLACE_WALLS)
|
if (phase !== Phase.PLACE_WALLS)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (isBackground)
|
if (isBackground) {
|
||||||
world.setBackground(x, y, material.orEmptyTile, hueShift, color)
|
world.setCombined(x, y, background = state, foreground = null, liquid = null, setBackgroundModifier = modifier.isRealModifier)
|
||||||
else
|
} else {
|
||||||
world.setForeground(x, y, material.orEmptyTile, hueShift, color)
|
val liquid = if (material.orEmptyTile.value.collisionKind.isSolidCollision) AbstractLiquidState.EMPTY else null
|
||||||
|
world.setCombined(x, y, background = null, foreground = state, liquid = liquid, setForegroundModifier = modifier.isRealModifier)
|
||||||
if (!isBackground && material.orEmptyTile.value.collisionKind.isSolidCollision) {
|
|
||||||
world.setLiquid(x, y, AbstractLiquidState.EMPTY)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modifier.isRealModifier) {
|
|
||||||
if (isBackground)
|
|
||||||
world.setBackground(x, y, modifier.orEmptyModifier, modHueShift)
|
|
||||||
else
|
|
||||||
world.setForeground(x, y, modifier.orEmptyModifier, modHueShift)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,10 +220,11 @@ data class DungeonDefinition(
|
|||||||
dungeonID: Int = 0,
|
dungeonID: Int = 0,
|
||||||
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)
|
val dungeonWorld = DungeonWorld(world, random, if (markSurfaceAndTerrain) y else null, terrainSurfaceSpaceExtends, expectedSize = expectedSize, immediate = immediate)
|
||||||
|
|
||||||
val validAnchors = anchorParts.filter { world.template.threatLevel in it.minimumThreatLevel .. it.maximumThreatLevel }
|
val validAnchors = anchorParts.filter { world.template.threatLevel in it.minimumThreatLevel .. it.maximumThreatLevel }
|
||||||
|
|
||||||
@ -247,9 +248,21 @@ data class DungeonDefinition(
|
|||||||
}.asCompletableFuture()
|
}.asCompletableFuture()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(anchor: DungeonPart, world: ServerWorld, random: RandomGenerator, x: Int, y: Int, dungeonID: Int = NO_DUNGEON_ID, markSurfaceAndTerrain: Boolean = false, forcePlacement: Boolean = false, terrainSurfaceSpaceExtends: Int = 0, commit: Boolean = true, scope: CoroutineScope = Starbound.GLOBAL_SCOPE): CompletableFuture<DungeonWorld> {
|
fun build(
|
||||||
|
anchor: DungeonPart,
|
||||||
|
world: ServerWorld,
|
||||||
|
random: RandomGenerator,
|
||||||
|
x: Int, y: Int,
|
||||||
|
dungeonID: Int = NO_DUNGEON_ID,
|
||||||
|
markSurfaceAndTerrain: Boolean = false,
|
||||||
|
forcePlacement: Boolean = false,
|
||||||
|
terrainSurfaceSpaceExtends: Int = 0,
|
||||||
|
commit: Boolean = true,
|
||||||
|
scope: CoroutineScope = Starbound.GLOBAL_SCOPE,
|
||||||
|
immediate: Boolean = false
|
||||||
|
): 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)
|
val dungeonWorld = DungeonWorld(world, random, if (markSurfaceAndTerrain) y else null, terrainSurfaceSpaceExtends, expectedSize = expectedSize, immediate = immediate)
|
||||||
|
|
||||||
return scope.async {
|
return scope.async {
|
||||||
generate0(anchor, dungeonWorld, x, y, forcePlacement, dungeonID)
|
generate0(anchor, dungeonWorld, x, y, forcePlacement, dungeonID)
|
||||||
|
@ -27,7 +27,9 @@ import ru.dbotthepony.kstarbound.util.random.random
|
|||||||
import ru.dbotthepony.kstarbound.world.ChunkPos
|
import ru.dbotthepony.kstarbound.world.ChunkPos
|
||||||
import ru.dbotthepony.kstarbound.world.ChunkState
|
import ru.dbotthepony.kstarbound.world.ChunkState
|
||||||
import ru.dbotthepony.kstarbound.world.Direction
|
import ru.dbotthepony.kstarbound.world.Direction
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.AbstractCell
|
||||||
import ru.dbotthepony.kstarbound.world.api.AbstractLiquidState
|
import ru.dbotthepony.kstarbound.world.api.AbstractLiquidState
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.AbstractTileState
|
||||||
import ru.dbotthepony.kstarbound.world.api.MutableTileState
|
import ru.dbotthepony.kstarbound.world.api.MutableTileState
|
||||||
import ru.dbotthepony.kstarbound.world.api.TileColor
|
import ru.dbotthepony.kstarbound.world.api.TileColor
|
||||||
import ru.dbotthepony.kstarbound.world.entities.tile.TileEntity
|
import ru.dbotthepony.kstarbound.world.entities.tile.TileEntity
|
||||||
@ -45,7 +47,20 @@ import kotlin.math.max
|
|||||||
// Facade world for generating dungeons, so generation can be performed without affecting world state,
|
// Facade world for generating dungeons, so generation can be performed without affecting world state,
|
||||||
// and if error occurs, won't require world's rollback, as well allowing dungeon to be generated mostly
|
// and if error occurs, won't require world's rollback, as well allowing dungeon to be generated mostly
|
||||||
// off world's thread.
|
// off world's thread.
|
||||||
class DungeonWorld(val parent: ServerWorld, val random: RandomGenerator, val markSurfaceLevel: Int? = null, val terrainSurfaceSpaceExtends: Int = 0, expectedSize: Int = 0) {
|
class DungeonWorld(
|
||||||
|
val parent: ServerWorld,
|
||||||
|
val random: RandomGenerator,
|
||||||
|
val markSurfaceLevel: Int? = null,
|
||||||
|
val terrainSurfaceSpaceExtends: 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
|
||||||
|
|
||||||
data class Material(
|
data class Material(
|
||||||
@ -81,11 +96,11 @@ class DungeonWorld(val parent: ServerWorld, val random: RandomGenerator, val mar
|
|||||||
|
|
||||||
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.TERRAIN
|
||||||
|
|
||||||
private val liquid = HashMap<Vector2i, AbstractLiquidState>(max(8192, expectedSize), 0.5f)
|
private val liquid = HashMap<Vector2i, AbstractLiquidState>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
||||||
private val foregroundMaterial = HashMap<Vector2i, Material>(max(8192, expectedSize), 0.5f)
|
private val foregroundMaterial = HashMap<Vector2i, Material>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
||||||
private val foregroundModifier = HashMap<Vector2i, Modifier>(max(8192, expectedSize), 0.5f)
|
private val foregroundModifier = HashMap<Vector2i, Modifier>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
||||||
private val backgroundMaterial = HashMap<Vector2i, Material>(max(8192, expectedSize), 0.5f)
|
private val backgroundMaterial = HashMap<Vector2i, Material>(if (immediate) 2048 else max(8192, expectedSize), 0.5f)
|
||||||
private val backgroundModifier = HashMap<Vector2i, Modifier>(max(8192, expectedSize), 0.5f)
|
private val backgroundModifier = HashMap<Vector2i, Modifier>(if (immediate) 2048 else max(8192, expectedSize), 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
|
||||||
@ -117,8 +132,6 @@ class DungeonWorld(val parent: ServerWorld, val random: RandomGenerator, val mar
|
|||||||
|
|
||||||
private var currentBoundingBox: AABBi? = null
|
private var currentBoundingBox: AABBi? = null
|
||||||
|
|
||||||
fun touched(): Set<Vector2i> = Collections.unmodifiableSet(touchedTiles)
|
|
||||||
|
|
||||||
fun touch(x: Int, y: Int) {
|
fun touch(x: Int, y: Int) {
|
||||||
val wrapped = geometry.wrap(Vector2i(x, y))
|
val wrapped = geometry.wrap(Vector2i(x, y))
|
||||||
touchedTiles.add(wrapped)
|
touchedTiles.add(wrapped)
|
||||||
@ -260,6 +273,131 @@ class DungeonWorld(val parent: ServerWorld, val random: RandomGenerator, val mar
|
|||||||
setBackground(x, y, Modifier(modifier, hueShift))
|
setBackground(x, y, Modifier(modifier, hueShift))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val emptyMaterial = Material(AbstractTileState.EMPTY.material, AbstractTileState.EMPTY.hueShift, AbstractTileState.EMPTY.color)
|
||||||
|
private val emptyModifier = Modifier(AbstractTileState.EMPTY.modifier, AbstractTileState.EMPTY.modifierHueShift)
|
||||||
|
|
||||||
|
private fun setCombinedFallback(
|
||||||
|
x: Int, y: Int,
|
||||||
|
foreground: AbstractTileState?,
|
||||||
|
background: AbstractTileState?,
|
||||||
|
liquid: AbstractLiquidState?,
|
||||||
|
setForegroundMaterial: Boolean,
|
||||||
|
setForegroundModifier: Boolean,
|
||||||
|
setBackgroundMaterial: Boolean,
|
||||||
|
setBackgroundModifier: Boolean,
|
||||||
|
) {
|
||||||
|
val pos = geometry.wrap(Vector2i(x, y))
|
||||||
|
|
||||||
|
if (foreground != null) {
|
||||||
|
if (setForegroundMaterial)
|
||||||
|
this.foregroundMaterial[pos] = Material(foreground.material, foreground.hueShift, foreground.color)
|
||||||
|
|
||||||
|
if (setForegroundModifier)
|
||||||
|
this.foregroundModifier[pos] = Modifier(foreground.modifier, foreground.modifierHueShift)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (background != null) {
|
||||||
|
if (setBackgroundMaterial)
|
||||||
|
this.backgroundMaterial[pos] = Material(background.material, background.hueShift, background.color)
|
||||||
|
|
||||||
|
if (setBackgroundModifier)
|
||||||
|
this.backgroundModifier[pos] = Modifier(background.modifier, background.modifierHueShift)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (liquid != null) this.liquid[pos] = liquid
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
val pos = geometry.wrap(Vector2i(x, y))
|
||||||
|
|
||||||
|
if (immediate) {
|
||||||
|
if (parent.setCell(x, y, AbstractCell.EMPTY)) {
|
||||||
|
this.foregroundMaterial.remove(pos)
|
||||||
|
this.foregroundModifier.remove(pos)
|
||||||
|
this.backgroundMaterial.remove(pos)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
fun needsForegroundBiomeMod(x: Int, y: Int): Boolean {
|
fun needsForegroundBiomeMod(x: Int, y: Int): Boolean {
|
||||||
val pos = geometry.wrap(Vector2i(x, y))
|
val pos = geometry.wrap(Vector2i(x, y))
|
||||||
val material = foregroundMaterial[pos] ?: return false
|
val material = foregroundMaterial[pos] ?: return false
|
||||||
|
@ -142,6 +142,14 @@ data class AABBi(val mins: Vector2i, val maxs: Vector2i) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rectangle with given [width] * 2 and [height] * 2
|
||||||
|
*/
|
||||||
|
fun withSide(pos: IStruct2i, size: IStruct2i): AABBi {
|
||||||
|
val (width, height) = size
|
||||||
|
return withSide(pos, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
@JvmField val ZERO = AABBi(Vector2i.ZERO, Vector2i.ZERO)
|
@JvmField val ZERO = AABBi(Vector2i.ZERO, Vector2i.ZERO)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,13 +565,33 @@ class ServerWorld private constructor(
|
|||||||
|
|
||||||
x = geometry.x.cell(x)
|
x = geometry.x.cell(x)
|
||||||
|
|
||||||
LOGGER.info("Trying to place dungeon ${dungeon.dungeon.key} at $x, ${dungeon.baseHeight}...")
|
val tickets = ArrayList<ServerChunk.ITicket>()
|
||||||
|
|
||||||
val dungeonWorld = try {
|
val dungeonWorld = try {
|
||||||
dungeon.dungeon.value.generate(this, random(random.nextLong()), x, dungeon.baseHeight, dungeon.blendWithTerrain, dungeon.forcePlacement, dungeonID = currentDungeonID).await()
|
// if immediate placement will cause issues it can be safely toggled off
|
||||||
|
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(
|
||||||
|
this,
|
||||||
|
random(random.nextLong()),
|
||||||
|
x, dungeon.baseHeight,
|
||||||
|
dungeon.blendWithTerrain,
|
||||||
|
dungeon.forcePlacement,
|
||||||
|
dungeonID = currentDungeonID,
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,19 @@ data class MutableTileState(
|
|||||||
modifierHueShift = 0f
|
modifierHueShift = 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun from(other: AbstractTileState, setMaterial: Boolean = true, setModifer: Boolean = true) {
|
||||||
|
if (setMaterial) {
|
||||||
|
material = other.material
|
||||||
|
modifier = other.modifier
|
||||||
|
color = other.color
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setModifer) {
|
||||||
|
hueShift = other.hueShift
|
||||||
|
modifierHueShift = other.modifierHueShift
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setHueShift(value: Int): MutableTileState {
|
fun setHueShift(value: Int): MutableTileState {
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
hueShift = 0f
|
hueShift = 0f
|
||||||
|
Loading…
Reference in New Issue
Block a user