mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 09:26:11 -04:00
block entity ticking, campfire block game logic
This commit is contained in:
parent
1f791378ec
commit
820cf347f7
@ -13,11 +13,15 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.entities.block
|
package de.bixilon.minosoft.data.entities.block
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
||||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
abstract class BlockEntity(
|
abstract class BlockEntity(
|
||||||
val connection: PlayConnection,
|
val connection: PlayConnection,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
open fun updateNBT(nbt: Map<String, Any>) {}
|
open fun updateNBT(nbt: Map<String, Any>) {}
|
||||||
|
|
||||||
|
open fun realTick(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) {}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,16 @@ package de.bixilon.minosoft.data.entities.block
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.inventory.ItemStack
|
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.properties.BlockProperties
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.types.CampfireBlock
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||||
|
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
|
||||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
import de.bixilon.minosoft.util.KUtil.nullCast
|
import de.bixilon.minosoft.util.KUtil.nullCast
|
||||||
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast
|
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast
|
||||||
|
import glm_.vec3.Vec3i
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
class CampfireBlockEntity(connection: PlayConnection) : BlockEntity(connection) {
|
class CampfireBlockEntity(connection: PlayConnection) : BlockEntity(connection) {
|
||||||
val items: Array<ItemStack?> = arrayOfNulls(RenderConstants.CAMPFIRE_ITEMS)
|
val items: Array<ItemStack?> = arrayOfNulls(RenderConstants.CAMPFIRE_ITEMS)
|
||||||
@ -38,6 +44,23 @@ class CampfireBlockEntity(connection: PlayConnection) : BlockEntity(connection)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun realTick(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) {
|
||||||
|
val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer) ?: return
|
||||||
|
if (blockState.properties[BlockProperties.LIT] != true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (blockState.block !is CampfireBlock) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Random.nextFloat() < 0.11f) {
|
||||||
|
for (i in 0 until Random.nextInt(2) + 2) {
|
||||||
|
blockState.block.spawnSmokeParticles(connection, particleRenderer, blockState, blockPosition, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object : BlockEntityFactory<CampfireBlockEntity> {
|
companion object : BlockEntityFactory<CampfireBlockEntity> {
|
||||||
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minecraft:campfire")
|
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minecraft:campfire")
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ open class Block(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
open fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
||||||
if (blockEntityType == null) {
|
if (blockEntityType == null) {
|
||||||
return BlockUsages.PASS
|
return BlockUsages.PASS
|
||||||
}
|
}
|
||||||
@ -107,6 +107,7 @@ open class Block(
|
|||||||
"NoteBlock" -> NoteBlock(resourceLocation, mappings, data)
|
"NoteBlock" -> NoteBlock(resourceLocation, mappings, data)
|
||||||
"RepeaterBlock" -> RepeaterBlock(resourceLocation, mappings, data)
|
"RepeaterBlock" -> RepeaterBlock(resourceLocation, mappings, data)
|
||||||
"ComparatorBlock" -> ComparatorBlock(resourceLocation, mappings, data)
|
"ComparatorBlock" -> ComparatorBlock(resourceLocation, mappings, data)
|
||||||
|
"CampfireBlock" -> CampfireBlock(resourceLocation, mappings, data)
|
||||||
else -> Block(resourceLocation, mappings, data)
|
else -> Block(resourceLocation, mappings, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.data.mappings.blocks.types
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||||
|
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.BlockUsages
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.properties.BlockProperties
|
||||||
|
import de.bixilon.minosoft.data.mappings.items.tools.ShovelItem
|
||||||
|
import de.bixilon.minosoft.data.mappings.versions.Registries
|
||||||
|
import de.bixilon.minosoft.data.player.Hands
|
||||||
|
import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit
|
||||||
|
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle
|
||||||
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
|
import glm_.vec3.Vec3
|
||||||
|
import glm_.vec3.Vec3i
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
open class CampfireBlock(resourceLocation: ResourceLocation, mappings: Registries, data: JsonObject) : Block(resourceLocation, mappings, data) {
|
||||||
|
|
||||||
|
private fun extinguish(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) {
|
||||||
|
val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer) ?: return
|
||||||
|
for (i in 0 until 20) {
|
||||||
|
spawnSmokeParticles(connection, particleRenderer, blockState, blockPosition, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun spawnSmokeParticles(connection: PlayConnection, particleRenderer: ParticleRenderer, blockState: BlockState, blockPosition: Vec3i, extinguished: Boolean) {
|
||||||
|
val horizontal = { 0.5f + Random.nextFloat() / 3.0f * if (Random.nextBoolean()) 1.0f else -1.0f }
|
||||||
|
val position = Vec3(
|
||||||
|
blockPosition.x + horizontal(),
|
||||||
|
blockPosition.y + Random.nextFloat() + Random.nextFloat(),
|
||||||
|
blockPosition.z + horizontal()
|
||||||
|
)
|
||||||
|
val isSignal = blockState.properties[BlockProperties.CAMPFIRE_SIGNAL_FIRE] == true
|
||||||
|
|
||||||
|
val data = connection.registries.particleTypeRegistry[if (isSignal) {
|
||||||
|
CampfireSmokeParticle.SignalSmokeParticleFactory
|
||||||
|
} else {
|
||||||
|
CampfireSmokeParticle.CosySmokeParticleFactory
|
||||||
|
}]!!
|
||||||
|
|
||||||
|
particleRenderer.add(CampfireSmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.07f, 0.0f), data.simple(), isSignal))
|
||||||
|
|
||||||
|
if (extinguished) {
|
||||||
|
// ToDo: Spawn smoke particles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
||||||
|
if (itemStack?.item !is ShovelItem || blockState.properties[BlockProperties.LIT] != true) {
|
||||||
|
return super.onUse(connection, blockState, blockPosition, raycastHit, hands, itemStack)
|
||||||
|
}
|
||||||
|
connection.world.setBlockState(blockPosition, blockState.withProperties(BlockProperties.LIT to false))
|
||||||
|
extinguish(connection, blockState, blockPosition)
|
||||||
|
return BlockUsages.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ open class ComparatorBlock(resourceLocation: ResourceLocation, mappings: Registr
|
|||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
||||||
connection.world[blockPosition] = blockState.cycle(BlockProperties.STRUCTURE_BLOCK_MODE)
|
connection.world[blockPosition] = blockState.cycle(BlockProperties.STRUCTURE_BLOCK_MODE)
|
||||||
|
|
||||||
return BlockUsages.SUCCESS
|
return BlockUsages.SUCCESS
|
||||||
|
@ -32,7 +32,7 @@ open class DoorBlock(resourceLocation: ResourceLocation, mappings: Registries, d
|
|||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
||||||
if (blockState.material.resourceLocation == DefaultMaterials.METAL) {
|
if (blockState.material.resourceLocation == DefaultMaterials.METAL) {
|
||||||
return BlockUsages.CONSUME
|
return BlockUsages.CONSUME
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ open class LeverBlock(resourceLocation: ResourceLocation, mappings: Registries,
|
|||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
||||||
connection.world[blockPosition] = blockState.cycle(BlockProperties.POWERED)
|
connection.world[blockPosition] = blockState.cycle(BlockProperties.POWERED)
|
||||||
|
|
||||||
return BlockUsages.SUCCESS
|
return BlockUsages.SUCCESS
|
||||||
|
@ -26,7 +26,7 @@ import glm_.vec3.Vec3i
|
|||||||
|
|
||||||
open class NoteBlock(resourceLocation: ResourceLocation, mappings: Registries, data: JsonObject) : Block(resourceLocation, mappings, data) {
|
open class NoteBlock(resourceLocation: ResourceLocation, mappings: Registries, data: JsonObject) : Block(resourceLocation, mappings, data) {
|
||||||
|
|
||||||
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
||||||
return BlockUsages.SUCCESS
|
return BlockUsages.SUCCESS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ open class RepeaterBlock(resourceLocation: ResourceLocation, mappings: Registrie
|
|||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
||||||
connection.world[blockPosition] = blockState.cycle(BlockProperties.REPEATER_DELAY)
|
connection.world[blockPosition] = blockState.cycle(BlockProperties.REPEATER_DELAY)
|
||||||
|
|
||||||
return BlockUsages.SUCCESS
|
return BlockUsages.SUCCESS
|
||||||
|
@ -16,8 +16,13 @@ import de.bixilon.minosoft.data.entities.block.BlockEntity
|
|||||||
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
||||||
import de.bixilon.minosoft.data.world.biome.source.BiomeSource
|
import de.bixilon.minosoft.data.world.biome.source.BiomeSource
|
||||||
import de.bixilon.minosoft.data.world.light.LightAccessor
|
import de.bixilon.minosoft.data.world.light.LightAccessor
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
|
||||||
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,6 +95,18 @@ class Chunk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun realTick(connection: PlayConnection, chunkPosition: Vec2i) {
|
||||||
|
if (!isFullyLoaded) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val sections = sections
|
||||||
|
sections ?: return
|
||||||
|
for ((height, section) in sections.toSynchronizedMap()) {
|
||||||
|
section.realTick(connection, Vec3i.of(chunkPosition, height, Vec3i.EMPTY))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getBlockEntity(inChunkPosition: Vec3i): BlockEntity? {
|
fun getBlockEntity(inChunkPosition: Vec3i): BlockEntity? {
|
||||||
return sections?.get(inChunkPosition.sectionHeight)?.getBlockEntity(inChunkPosition.inChunkSectionPosition)
|
return sections?.get(inChunkPosition.sectionHeight)?.getBlockEntity(inChunkPosition.inChunkSectionPosition)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
|||||||
import de.bixilon.minosoft.data.world.block.entities.ArrayBlockEntityProvider
|
import de.bixilon.minosoft.data.world.block.entities.ArrayBlockEntityProvider
|
||||||
import de.bixilon.minosoft.data.world.block.entities.BlockEntityProvider
|
import de.bixilon.minosoft.data.world.block.entities.BlockEntityProvider
|
||||||
import de.bixilon.minosoft.data.world.block.entities.MapBlockEntityProvider
|
import de.bixilon.minosoft.data.world.block.entities.MapBlockEntityProvider
|
||||||
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
@ -55,6 +56,12 @@ class ChunkSection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun realTick(connection: PlayConnection, chunkSectionPosition: Vec3i) {
|
||||||
|
blockEntities.forEach { entity, inChunkSectionPosition ->
|
||||||
|
entity.realTick(connection, blocks[inChunkSectionPosition.index]!!, chunkSectionPosition + inChunkSectionPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val Vec3i.index: Int
|
val Vec3i.index: Int
|
||||||
get() = getIndex(x, y, z)
|
get() = getIndex(x, y, z)
|
||||||
|
@ -30,6 +30,7 @@ import de.bixilon.minosoft.modding.event.events.BlockSetEvent
|
|||||||
import de.bixilon.minosoft.modding.event.events.ChunkUnloadEvent
|
import de.bixilon.minosoft.modding.event.events.ChunkUnloadEvent
|
||||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
@ -155,6 +156,12 @@ class World(
|
|||||||
return biomeAccessor.getBiome(blockPosition)
|
return biomeAccessor.getBiome(blockPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun realTick() {
|
||||||
|
for ((chunkPosition, chunk) in chunks.toSynchronizedMap()) {
|
||||||
|
chunk.realTick(connection, chunkPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getBlocks(start: Vec3i, end: Vec3i): Map<Vec3i, BlockState> {
|
fun getBlocks(start: Vec3i, end: Vec3i): Map<Vec3i, BlockState> {
|
||||||
val blocks: MutableMap<Vec3i, BlockState> = mutableMapOf()
|
val blocks: MutableMap<Vec3i, BlockState> = mutableMapOf()
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.world.block.entities
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
||||||
import de.bixilon.minosoft.data.world.ChunkSection.Companion.index
|
import de.bixilon.minosoft.data.world.ChunkSection.Companion.index
|
||||||
|
import de.bixilon.minosoft.data.world.ChunkSection.Companion.indexPosition
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
@ -47,4 +48,11 @@ class ArrayBlockEntityProvider(
|
|||||||
override fun clone(): ArrayBlockEntityProvider {
|
override fun clone(): ArrayBlockEntityProvider {
|
||||||
return ArrayBlockEntityProvider(blockEntities.clone())
|
return ArrayBlockEntityProvider(blockEntities.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun forEach(lambda: (entity: BlockEntity, inChunkSectionPosition: Vec3i) -> Unit) {
|
||||||
|
for ((index, blockEntity) in blockEntities.withIndex()) {
|
||||||
|
blockEntity ?: continue
|
||||||
|
lambda(blockEntity, index.indexPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ interface BlockEntityProvider {
|
|||||||
|
|
||||||
fun clone(): BlockEntityProvider
|
fun clone(): BlockEntityProvider
|
||||||
|
|
||||||
|
fun forEach(lambda: (entity: BlockEntity, inChunkSectionPosition: Vec3i) -> Unit)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val BLOCK_ENTITY_MAP_LIMIT_UP = 15
|
const val BLOCK_ENTITY_MAP_LIMIT_UP = 15
|
||||||
const val BLOCK_ENTITY_MAP_LIMIT_DOWN = 5
|
const val BLOCK_ENTITY_MAP_LIMIT_DOWN = 5
|
||||||
|
@ -15,10 +15,12 @@ package de.bixilon.minosoft.data.world.block.entities
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
||||||
import de.bixilon.minosoft.data.world.ChunkSection.Companion.indexPosition
|
import de.bixilon.minosoft.data.world.ChunkSection.Companion.indexPosition
|
||||||
|
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
class MapBlockEntityProvider(
|
class MapBlockEntityProvider(
|
||||||
var blockEntities: MutableMap<Vec3i, BlockEntity> = mutableMapOf(),
|
var blockEntities: MutableMap<Vec3i, BlockEntity> = synchronizedMapOf(),
|
||||||
) : BlockEntityProvider {
|
) : BlockEntityProvider {
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = blockEntities.size
|
get() = blockEntities.size
|
||||||
@ -47,4 +49,10 @@ class MapBlockEntityProvider(
|
|||||||
override fun clone(): MapBlockEntityProvider {
|
override fun clone(): MapBlockEntityProvider {
|
||||||
return MapBlockEntityProvider(blockEntities.toMutableMap())
|
return MapBlockEntityProvider(blockEntities.toMutableMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun forEach(lambda: (entity: BlockEntity, inChunkSectionPosition: Vec3i) -> Unit) {
|
||||||
|
for ((position, blockEntity) in blockEntities.toSynchronizedMap()) {
|
||||||
|
lambda(blockEntity, position)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class RightClickHandler(
|
|||||||
val usage = if (renderWindow.inputHandler.camera.sneaking) {
|
val usage = if (renderWindow.inputHandler.camera.sneaking) {
|
||||||
BlockUsages.PASS
|
BlockUsages.PASS
|
||||||
} else {
|
} else {
|
||||||
raycastHit.blockState.block.use(renderWindow.connection, raycastHit.blockState, raycastHit.blockPosition, raycastHit, Hands.MAIN_HAND, itemInHand)
|
raycastHit.blockState.block.onUse(renderWindow.connection, raycastHit.blockState, raycastHit.blockPosition, raycastHit, Hands.MAIN_HAND, itemInHand)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTime - lastInteractionSent < ProtocolDefinition.TICK_TIME) {
|
if (currentTime - lastInteractionSent < ProtocolDefinition.TICK_TIME) {
|
||||||
|
@ -20,7 +20,6 @@ import de.bixilon.minosoft.gui.rendering.Renderer
|
|||||||
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
||||||
import de.bixilon.minosoft.gui.rendering.modding.events.CameraMatrixChangeEvent
|
import de.bixilon.minosoft.gui.rendering.modding.events.CameraMatrixChangeEvent
|
||||||
import de.bixilon.minosoft.gui.rendering.particle.types.Particle
|
import de.bixilon.minosoft.gui.rendering.particle.types.Particle
|
||||||
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle
|
|
||||||
import de.bixilon.minosoft.gui.rendering.shader.Shader
|
import de.bixilon.minosoft.gui.rendering.shader.Shader
|
||||||
import de.bixilon.minosoft.gui.rendering.textures.Texture
|
import de.bixilon.minosoft.gui.rendering.textures.Texture
|
||||||
import de.bixilon.minosoft.gui.rendering.textures.TextureArray
|
import de.bixilon.minosoft.gui.rendering.textures.TextureArray
|
||||||
@ -32,7 +31,6 @@ import de.bixilon.minosoft.util.KUtil.toSynchronizedSet
|
|||||||
import de.bixilon.minosoft.util.MMath
|
import de.bixilon.minosoft.util.MMath
|
||||||
import glm_.vec3.Vec3
|
import glm_.vec3.Vec3
|
||||||
import org.lwjgl.opengl.GL11.glDepthMask
|
import org.lwjgl.opengl.GL11.glDepthMask
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
|
|
||||||
class ParticleRenderer(
|
class ParticleRenderer(
|
||||||
@ -78,7 +76,6 @@ class ParticleRenderer(
|
|||||||
particles += particle
|
particles += particle
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastTickTime = System.currentTimeMillis()
|
|
||||||
|
|
||||||
override fun draw() {
|
override fun draw() {
|
||||||
particleShader.use()
|
particleShader.use()
|
||||||
@ -86,25 +83,6 @@ class ParticleRenderer(
|
|||||||
particleMesh.unload()
|
particleMesh.unload()
|
||||||
particleMesh = ParticleMesh()
|
particleMesh = ParticleMesh()
|
||||||
|
|
||||||
// ToDo: Remove, this ist just for testing purposes
|
|
||||||
if (System.currentTimeMillis() - lastTickTime > ProtocolDefinition.TICK_TIME) {
|
|
||||||
val blockPosition = Vec3(0, 5, 0)
|
|
||||||
if (Random.nextFloat() < 0.11f) {
|
|
||||||
for (i in 0 until Random.nextInt(2) + 2) {
|
|
||||||
val horizontal = { 0.5f + Random.nextFloat() / 3.0f * if (Random.nextBoolean()) 1.0f else -1.0f }
|
|
||||||
val position = Vec3(
|
|
||||||
blockPosition.x + horizontal(),
|
|
||||||
blockPosition.y + Random.nextFloat() + Random.nextFloat(),
|
|
||||||
blockPosition.z + horizontal()
|
|
||||||
)
|
|
||||||
|
|
||||||
val data = connection.registries.particleTypeRegistry[CampfireSmokeParticle.CosySmokeParticleFactory]!!
|
|
||||||
val particle = CampfireSmokeParticle(connection, this, position, Vec3(0.0f, 0.07f, 0.0f), data.simple(), true)
|
|
||||||
add(particle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastTickTime = System.currentTimeMillis()
|
|
||||||
}
|
|
||||||
|
|
||||||
for (particle in particles.toSynchronizedSet()) {
|
for (particle in particles.toSynchronizedSet()) {
|
||||||
particle.tick()
|
particle.tick()
|
||||||
|
@ -62,7 +62,6 @@ abstract class Particle(
|
|||||||
var spacing: Vec3 = Vec3.EMPTY
|
var spacing: Vec3 = Vec3.EMPTY
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field == value) {
|
if (field == value) {
|
||||||
return
|
|
||||||
}
|
}
|
||||||
field = value
|
field = value
|
||||||
|
|
||||||
|
@ -150,33 +150,27 @@ object VecUtil {
|
|||||||
return Pair(Vec2(this[0].asFloat, BlockModelElement.BLOCK_RESOLUTION - this[1].asFloat), Vec2(this[2].asFloat, BlockModelElement.BLOCK_RESOLUTION - this[3].asFloat))
|
return Pair(Vec2(this[0].asFloat, BlockModelElement.BLOCK_RESOLUTION - this[1].asFloat), Vec2(this[2].asFloat, BlockModelElement.BLOCK_RESOLUTION - this[3].asFloat))
|
||||||
}
|
}
|
||||||
|
|
||||||
val Vec3i.chunkPosition: Vec2i
|
fun Int.chunkPosition(multiplier: Int): Int {
|
||||||
get() {
|
return if (this >= 0) {
|
||||||
val chunkX = if (this.x >= 0) {
|
this / multiplier
|
||||||
this.x / ProtocolDefinition.SECTION_WIDTH_X
|
} else {
|
||||||
} else {
|
((this + 1) / multiplier) - 1
|
||||||
((this.x + 1) / ProtocolDefinition.SECTION_WIDTH_X) - 1
|
|
||||||
}
|
|
||||||
val chunkY = if (this.z >= 0) {
|
|
||||||
this.z / ProtocolDefinition.SECTION_WIDTH_Z
|
|
||||||
} else {
|
|
||||||
((this.z + 1) / ProtocolDefinition.SECTION_WIDTH_Z) - 1
|
|
||||||
}
|
|
||||||
return Vec2i(chunkX, chunkY)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val Vec3i.chunkPosition: Vec2i
|
||||||
|
get() = Vec2i(this.x.chunkPosition(ProtocolDefinition.SECTION_WIDTH_X), this.z.chunkPosition(ProtocolDefinition.SECTION_WIDTH_Z))
|
||||||
|
|
||||||
|
fun Int.inChunkPosition(multiplier: Int): Int {
|
||||||
|
var coordinate: Int = this % multiplier
|
||||||
|
if (coordinate < 0) {
|
||||||
|
coordinate += multiplier
|
||||||
|
}
|
||||||
|
return coordinate
|
||||||
|
}
|
||||||
|
|
||||||
val Vec3i.inChunkPosition: Vec3i
|
val Vec3i.inChunkPosition: Vec3i
|
||||||
get() {
|
get() = Vec3i(this.x.inChunkPosition(ProtocolDefinition.SECTION_WIDTH_X), y, this.z.inChunkPosition(ProtocolDefinition.SECTION_WIDTH_Z))
|
||||||
var x: Int = this.x % ProtocolDefinition.SECTION_WIDTH_X
|
|
||||||
if (x < 0) {
|
|
||||||
x += ProtocolDefinition.SECTION_WIDTH_X
|
|
||||||
}
|
|
||||||
var z: Int = this.z % ProtocolDefinition.SECTION_WIDTH_Z
|
|
||||||
if (z < 0) {
|
|
||||||
z += ProtocolDefinition.SECTION_WIDTH_Z
|
|
||||||
}
|
|
||||||
return Vec3i(x, y, z)
|
|
||||||
}
|
|
||||||
|
|
||||||
val Vec3i.inChunkSectionPosition: Vec3i
|
val Vec3i.inChunkSectionPosition: Vec3i
|
||||||
get() {
|
get() {
|
||||||
@ -199,20 +193,20 @@ object VecUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val Vec3i.entityPosition: Vec3
|
val Vec3i.entityPosition: Vec3
|
||||||
get() = Vec3(x + 0.5f, y, z + 0.5f) // ToDo
|
get() = Vec3(x + 0.5f, y, z + 0.5f) // ToDo: Confirm
|
||||||
|
|
||||||
val Vec3.blockPosition: Vec3i
|
val Vec3.blockPosition: Vec3i
|
||||||
get() = Vec3i((x - 0.5f).toInt(), y.toInt(), (z - 0.5f).toInt()) // ToDo
|
get() = Vec3i((x - 0.5f).toInt(), y.toInt(), (z - 0.5f).toInt()) // ToDo: Confirm
|
||||||
|
|
||||||
val Vec3i.center: Vec3
|
val Vec3i.center: Vec3
|
||||||
get() = Vec3(x + 0.5f, y + 0.5f, z + 0.5f) // ToDo
|
get() = Vec3(x + 0.5f, y + 0.5f, z + 0.5f) // ToDo: Confirm
|
||||||
|
|
||||||
fun Vec3i.Companion.of(chunkPosition: Vec2i, sectionHeight: Int, inChunkSectionPosition: Vec3i): Vec3i {
|
fun Vec3i.Companion.of(chunkPosition: Vec2i, sectionHeight: Int, inChunkSectionPosition: Vec3i): Vec3i {
|
||||||
return Vec3i(
|
return Vec3i(
|
||||||
chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X + inChunkSectionPosition.x,
|
chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X + inChunkSectionPosition.x,
|
||||||
sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y + inChunkSectionPosition.y,
|
sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y + inChunkSectionPosition.y,
|
||||||
chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z + inChunkSectionPosition.z
|
chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z + inChunkSectionPosition.z
|
||||||
) // ToDo
|
) // ToDo: Confirm
|
||||||
}
|
}
|
||||||
|
|
||||||
infix operator fun Vec3i.plus(vec3: Vec3i?): Vec3i {
|
infix operator fun Vec3i.plus(vec3: Vec3i?): Vec3i {
|
||||||
|
@ -80,6 +80,7 @@ class PlayConnection(
|
|||||||
|
|
||||||
lateinit var velocityHandlerTask: TimeWorkerTask
|
lateinit var velocityHandlerTask: TimeWorkerTask
|
||||||
private var velocityHandlerLastExecutionTime: Long = 0L
|
private var velocityHandlerLastExecutionTime: Long = 0L
|
||||||
|
lateinit var worldTickTask: TimeWorkerTask
|
||||||
val collisionDetector = CollisionDetector(this)
|
val collisionDetector = CollisionDetector(this)
|
||||||
|
|
||||||
override var connectionState: ConnectionStates = ConnectionStates.DISCONNECTED
|
override var connectionState: ConnectionStates = ConnectionStates.DISCONNECTED
|
||||||
@ -137,6 +138,11 @@ class PlayConnection(
|
|||||||
}
|
}
|
||||||
TimeWorker.addTask(velocityHandlerTask)
|
TimeWorker.addTask(velocityHandlerTask)
|
||||||
|
|
||||||
|
worldTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME) {
|
||||||
|
world.realTick()
|
||||||
|
}
|
||||||
|
TimeWorker.addTask(worldTickTask)
|
||||||
|
|
||||||
registerEvent(CallbackEventInvoker.of<ChatMessageReceiveEvent> {
|
registerEvent(CallbackEventInvoker.of<ChatMessageReceiveEvent> {
|
||||||
val additionalPrefix = when (it.position) {
|
val additionalPrefix = when (it.position) {
|
||||||
ChatTextPositions.SYSTEM_MESSAGE -> "[SYSTEM] "
|
ChatTextPositions.SYSTEM_MESSAGE -> "[SYSTEM] "
|
||||||
@ -157,6 +163,9 @@ class PlayConnection(
|
|||||||
if (this::velocityHandlerTask.isInitialized) {
|
if (this::velocityHandlerTask.isInitialized) {
|
||||||
TimeWorker.removeTask(velocityHandlerTask)
|
TimeWorker.removeTask(velocityHandlerTask)
|
||||||
}
|
}
|
||||||
|
if (this::worldTickTask.isInitialized) {
|
||||||
|
TimeWorker.removeTask(worldTickTask)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
|
@ -43,18 +43,18 @@ class ContainerOpenS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val title: ChatComponent = buffer.readChatComponent()
|
val title: ChatComponent = buffer.readChatComponent()
|
||||||
val slotCount: Int = if (buffer.versionId < V_19W02A || buffer.versionId >= V_19W11A) {
|
val slotCount: Int = if (buffer.versionId <= V_19W11A) { // ToDo: This is completely guessed, it is not present in 1.16.5 (unchecked)
|
||||||
buffer.readUnsignedByte()
|
buffer.readUnsignedByte()
|
||||||
} else {
|
} else {
|
||||||
// ToDo: load from pixlyzer
|
// ToDo: load from pixlyzer
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
val hasTitle: Boolean = if (buffer.versionId > V_14W03B) {
|
val hasTitle: Boolean = if (buffer.versionId > V_14W03B && buffer.versionId <= V_1_16) { // also completely guessed
|
||||||
buffer.readBoolean()
|
buffer.readBoolean()
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
var entityId: Int? = if (containerType.resourceLocation == DefaultInventoryTypes.HORSE || buffer.versionId < V_14W03B) {
|
var entityId: Int? = if (containerType.resourceLocation == DefaultInventoryTypes.HORSE || buffer.versionId < V_14W03B) { // ToDo: This was removed at some point
|
||||||
buffer.readInt()
|
buffer.readInt()
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
@ -12,16 +12,25 @@ object TimeWorker {
|
|||||||
while (true) {
|
while (true) {
|
||||||
val currentTime = System.currentTimeMillis()
|
val currentTime = System.currentTimeMillis()
|
||||||
for (task in TASKS.toSynchronizedSet()) {
|
for (task in TASKS.toSynchronizedSet()) {
|
||||||
if (!task.getsExecuted && currentTime - task.lastExecution >= task.interval) {
|
if (task.getsExecuted) {
|
||||||
Minosoft.THREAD_POOL.execute {
|
continue
|
||||||
|
}
|
||||||
|
if (currentTime - task.lastExecution <= task.interval) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
Minosoft.THREAD_POOL.execute {
|
||||||
|
synchronized(task.getsExecuted) {
|
||||||
|
if (task.getsExecuted) {
|
||||||
|
return@execute
|
||||||
|
}
|
||||||
task.getsExecuted = true
|
task.getsExecuted = true
|
||||||
task.runnable.run()
|
task.runnable.run()
|
||||||
task.lastExecution = currentTime
|
task.lastExecution = currentTime
|
||||||
task.getsExecuted = false
|
task.getsExecuted = false
|
||||||
}
|
}
|
||||||
if (task.runOnce) {
|
}
|
||||||
TASKS -= task
|
if (task.runOnce) {
|
||||||
}
|
TASKS -= task
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Thread.sleep(1)
|
Thread.sleep(1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user