mirror of
https://github.com/chylex/Hardcore-Ender-Expansion-2.git
synced 2025-11-19 08:22:35 +01:00
Compare commits
7 Commits
wip4
...
components
| Author | SHA1 | Date | |
|---|---|---|---|
| b64005357e | |||
| 3279dde625 | |||
| a9df51e315 | |||
| 322c005648 | |||
| 5211731e62 | |||
| 08d2fcb19c | |||
| e9077c680f |
@@ -22,7 +22,6 @@ import net.minecraft.block.BlockState
|
|||||||
import net.minecraft.enchantment.EnchantmentHelper
|
import net.minecraft.enchantment.EnchantmentHelper
|
||||||
import net.minecraft.enchantment.Enchantments
|
import net.minecraft.enchantment.Enchantments
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
|
|
||||||
import net.minecraft.entity.EntityType
|
import net.minecraft.entity.EntityType
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.world.IBlockReader
|
import net.minecraft.world.IBlockReader
|
||||||
@@ -48,6 +47,14 @@ class BlockDustyStoneUnstable(builder: BlockBuilder) : BlockDustyStone(builder),
|
|||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isNonCreative(entity: Entity): Boolean {
|
||||||
|
return entity !is EntityPlayer || !entity.isCreative
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isLightMob(entity: Entity): Boolean {
|
||||||
|
return entity.height <= 0.5F || (entity.height <= 1F && entity.width <= 0.5F)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: EntityPlayer): Boolean {
|
override fun canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: EntityPlayer): Boolean {
|
||||||
@@ -87,7 +94,7 @@ class BlockDustyStoneUnstable(builder: BlockBuilder) : BlockDustyStone(builder),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onEntityCollisionAbove(world: World, pos: BlockPos, entity: Entity) {
|
override fun onEntityCollisionAbove(world: World, pos: BlockPos, entity: Entity) {
|
||||||
if (!world.isRemote && world.totalTime % 4L == 0L && !(entity.height <= 0.5F || (entity.height <= 1F && entity.width <= 0.5F)) && isNonCreative(entity)) {
|
if (!world.isRemote && world.totalTime % 4L == 0L && !isLightMob(entity) && isNonCreative(entity)) {
|
||||||
if (!doCrumbleTest(world, pos)) {
|
if (!doCrumbleTest(world, pos)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -103,7 +110,7 @@ class BlockDustyStoneUnstable(builder: BlockBuilder) : BlockDustyStone(builder),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onFallenUpon(world: World, pos: BlockPos, entity: Entity, fallDistance: Float) {
|
override fun onFallenUpon(world: World, pos: BlockPos, entity: Entity, fallDistance: Float) {
|
||||||
if (!world.isRemote && entity is EntityLivingBase && fallDistance > 1.3F && isNonCreative(entity)) {
|
if (!world.isRemote && entity is EntityLivingBase && fallDistance > (if (isLightMob(entity)) 3.3F else 1.3F) && isNonCreative(entity)) {
|
||||||
val rand = world.rand
|
val rand = world.rand
|
||||||
val aabb = entity.boundingBox
|
val aabb = entity.boundingBox
|
||||||
val y = pos.y
|
val y = pos.y
|
||||||
@@ -135,12 +142,8 @@ class BlockDustyStoneUnstable(builder: BlockBuilder) : BlockDustyStone(builder),
|
|||||||
super.onFallenUpon(world, pos, entity, fallDistance)
|
super.onFallenUpon(world, pos, entity, fallDistance)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canCreatureSpawn(state: BlockState, world: IBlockReader, pos: BlockPos, placementType: PlacementType, entityType: EntityType<*>?): Boolean {
|
override fun canEntitySpawn(state: BlockState, world: IBlockReader, pos: BlockPos, entityType: EntityType<*>): Boolean {
|
||||||
return super.canCreatureSpawn(state, world, pos, placementType, entityType) && getCrumbleStartPos(world, pos) == null
|
return super.canEntitySpawn(state, world, pos, entityType) && getCrumbleStartPos(world, pos) == null
|
||||||
}
|
|
||||||
|
|
||||||
private fun isNonCreative(entity: Entity): Boolean {
|
|
||||||
return entity !is EntityPlayer || !entity.isCreative
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doCrumbleTest(world: World, pos: BlockPos): Boolean {
|
private fun doCrumbleTest(world: World, pos: BlockPos): Boolean {
|
||||||
|
|||||||
@@ -9,14 +9,13 @@ import chylex.hee.game.entity.technical.EntityTechnicalTrigger.Types.ENERGY_SHRI
|
|||||||
import chylex.hee.game.world.center
|
import chylex.hee.game.world.center
|
||||||
import chylex.hee.game.world.feature.energyshrine.EnergyShrinePieces
|
import chylex.hee.game.world.feature.energyshrine.EnergyShrinePieces
|
||||||
import net.minecraft.block.BlockState
|
import net.minecraft.block.BlockState
|
||||||
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
|
|
||||||
import net.minecraft.entity.EntityType
|
import net.minecraft.entity.EntityType
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.world.IBlockReader
|
import net.minecraft.world.IBlockReader
|
||||||
import net.minecraft.world.IEntityReader
|
import net.minecraft.world.IEntityReader
|
||||||
|
|
||||||
class BlockGloomrock(builder: BlockBuilder) : BlockSimple(builder) {
|
class BlockGloomrock(builder: BlockBuilder) : BlockSimple(builder) {
|
||||||
override fun canCreatureSpawn(state: BlockState, world: IBlockReader, pos: BlockPos, type: PlacementType, entityType: EntityType<*>?): Boolean {
|
override fun canEntitySpawn(state: BlockState, world: IBlockReader, pos: BlockPos, entityType: EntityType<*>?): Boolean {
|
||||||
if (world !is IEntityReader) {
|
if (world !is IEntityReader) {
|
||||||
HEE.log.warn("[BlockGloomrock] attempted to check spawn on a world != IEntityReader (${world.javaClass})")
|
HEE.log.warn("[BlockGloomrock] attempted to check spawn on a world != IEntityReader (${world.javaClass})")
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import chylex.hee.system.random.nextFloat
|
|||||||
import chylex.hee.system.random.nextInt
|
import chylex.hee.system.random.nextInt
|
||||||
import net.minecraft.block.Block
|
import net.minecraft.block.Block
|
||||||
import net.minecraft.block.BlockState
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.entity.EntityType
|
||||||
import net.minecraft.item.BlockItemUseContext
|
import net.minecraft.item.BlockItemUseContext
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.state.StateContainer.Builder
|
import net.minecraft.state.StateContainer.Builder
|
||||||
@@ -88,6 +89,12 @@ open class BlockGraveDirt(builder: BlockBuilder) : BlockSimpleShaped(builder, Ax
|
|||||||
super.getShape(state, source, pos, context)
|
super.getShape(state, source, pos, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mobs
|
||||||
|
|
||||||
|
override fun canEntitySpawn(state: BlockState, worldIn: IBlockReader, pos: BlockPos, type: EntityType<*>): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Explosions
|
// Explosions
|
||||||
|
|
||||||
override fun canDropFromExplosion(explosion: Explosion): Boolean {
|
override fun canDropFromExplosion(explosion: Explosion): Boolean {
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ class EntityMobAngryEnderman(type: EntityType<EntityMobAngryEnderman>, world: Wo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateAITasks() {
|
override fun updateAITasks() {
|
||||||
teleportHandler.update()
|
teleportHandler.tickServer()
|
||||||
waterHandler.update()
|
waterHandler.tickServer()
|
||||||
|
|
||||||
val currentTarget = attackTarget
|
val currentTarget = attackTarget
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ import chylex.hee.game.mechanics.causatum.events.CausatumEventEndermanKill
|
|||||||
import chylex.hee.game.world.playServer
|
import chylex.hee.game.world.playServer
|
||||||
import chylex.hee.init.ModEntities
|
import chylex.hee.init.ModEntities
|
||||||
import chylex.hee.init.ModSounds
|
import chylex.hee.init.ModSounds
|
||||||
|
import chylex.hee.system.component.EntityComponents
|
||||||
|
import chylex.hee.system.component.general.deserializeFrom
|
||||||
|
import chylex.hee.system.component.general.serializeTo
|
||||||
|
import chylex.hee.system.component.general.tick
|
||||||
import chylex.hee.system.facades.Resource
|
import chylex.hee.system.facades.Resource
|
||||||
import chylex.hee.system.forge.SubscribeAllEvents
|
import chylex.hee.system.forge.SubscribeAllEvents
|
||||||
import chylex.hee.system.forge.SubscribeEvent
|
import chylex.hee.system.forge.SubscribeEvent
|
||||||
@@ -76,8 +80,6 @@ class EntityMobEnderman(type: EntityType<EntityMobEnderman>, world: World) : Ent
|
|||||||
|
|
||||||
@SubscribeAllEvents(modid = HEE.ID)
|
@SubscribeAllEvents(modid = HEE.ID)
|
||||||
companion object {
|
companion object {
|
||||||
private const val TELEPORT_HANDLER_TAG = "Teleport"
|
|
||||||
private const val WATER_HANDLER_TAG = "Water"
|
|
||||||
private const val CAN_PICK_UP_BLOCKS_TAG = "CanPickUpBlocks"
|
private const val CAN_PICK_UP_BLOCKS_TAG = "CanPickUpBlocks"
|
||||||
private const val HELD_BLOCK_TIMER_TAG = "HeldBlockTimer"
|
private const val HELD_BLOCK_TIMER_TAG = "HeldBlockTimer"
|
||||||
private const val HELD_BLOCK_DESPAWNS_TAG = "HeldBlockDespawns"
|
private const val HELD_BLOCK_DESPAWNS_TAG = "HeldBlockDespawns"
|
||||||
@@ -202,8 +204,9 @@ class EntityMobEnderman(type: EntityType<EntityMobEnderman>, world: World) : Ent
|
|||||||
|
|
||||||
// Instance
|
// Instance
|
||||||
|
|
||||||
|
private lateinit var components: EntityComponents
|
||||||
|
|
||||||
private lateinit var teleportHandler: EndermanTeleportHandler
|
private lateinit var teleportHandler: EndermanTeleportHandler
|
||||||
private lateinit var waterHandler: EndermanWaterHandler
|
|
||||||
private lateinit var blockHandler: EndermanBlockHandler
|
private lateinit var blockHandler: EndermanBlockHandler
|
||||||
|
|
||||||
private lateinit var aiAttackTarget: AIToggle
|
private lateinit var aiAttackTarget: AIToggle
|
||||||
@@ -227,6 +230,13 @@ class EntityMobEnderman(type: EntityType<EntityMobEnderman>, world: World) : Ent
|
|||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
||||||
|
override fun registerData() {
|
||||||
|
super.registerData()
|
||||||
|
|
||||||
|
components = EntityComponents()
|
||||||
|
components.attach(EndermanWaterHandler(this, takeDamageAfterWetTicks = 80))
|
||||||
|
}
|
||||||
|
|
||||||
override fun registerAttributes() {
|
override fun registerAttributes() {
|
||||||
super.registerAttributes()
|
super.registerAttributes()
|
||||||
|
|
||||||
@@ -238,8 +248,7 @@ class EntityMobEnderman(type: EntityType<EntityMobEnderman>, world: World) : Ent
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun registerGoals() {
|
override fun registerGoals() {
|
||||||
teleportHandler = EndermanTeleportHandler(this)
|
teleportHandler = EndermanTeleportHandler(this).also(components::attach)
|
||||||
waterHandler = EndermanWaterHandler(this, takeDamageAfterWetTicks = 80)
|
|
||||||
blockHandler = EndermanBlockHandler(this)
|
blockHandler = EndermanBlockHandler(this)
|
||||||
|
|
||||||
aiWatchTargetInShock = AIWatchTargetInShock(this, maxDistance = 72.0)
|
aiWatchTargetInShock = AIWatchTargetInShock(this, maxDistance = 72.0)
|
||||||
@@ -265,10 +274,9 @@ class EntityMobEnderman(type: EntityType<EntityMobEnderman>, world: World) : Ent
|
|||||||
override fun livingTick() {
|
override fun livingTick() {
|
||||||
super.livingTick()
|
super.livingTick()
|
||||||
|
|
||||||
if (!world.isRemote) {
|
components.tick(this)
|
||||||
teleportHandler.update()
|
|
||||||
waterHandler.update()
|
|
||||||
|
|
||||||
|
if (!world.isRemote) {
|
||||||
if (heldBlockTimer > 0 && --heldBlockTimer == 0.toShort()) {
|
if (heldBlockTimer > 0 && --heldBlockTimer == 0.toShort()) {
|
||||||
if (heldBlockDespawns || !blockHandler.tryPlaceBlock(allowPlayerProximity = false)) {
|
if (heldBlockDespawns || !blockHandler.tryPlaceBlock(allowPlayerProximity = false)) {
|
||||||
teleportHandler.teleportOutOfWorld(force = rand.nextBoolean())
|
teleportHandler.teleportOutOfWorld(force = rand.nextBoolean())
|
||||||
@@ -536,8 +544,7 @@ class EntityMobEnderman(type: EntityType<EntityMobEnderman>, world: World) : Ent
|
|||||||
override fun writeAdditional(nbt: TagCompound) = nbt.heeTag.use {
|
override fun writeAdditional(nbt: TagCompound) = nbt.heeTag.use {
|
||||||
super.writeAdditional(nbt)
|
super.writeAdditional(nbt)
|
||||||
|
|
||||||
put(TELEPORT_HANDLER_TAG, teleportHandler.serializeNBT())
|
components.serializeTo(this)
|
||||||
put(WATER_HANDLER_TAG, waterHandler.serializeNBT())
|
|
||||||
|
|
||||||
putBoolean(CAN_PICK_UP_BLOCKS_TAG, aiPickUpBlocks.enabled)
|
putBoolean(CAN_PICK_UP_BLOCKS_TAG, aiPickUpBlocks.enabled)
|
||||||
putShort(HELD_BLOCK_TIMER_TAG, heldBlockTimer)
|
putShort(HELD_BLOCK_TIMER_TAG, heldBlockTimer)
|
||||||
@@ -547,8 +554,7 @@ class EntityMobEnderman(type: EntityType<EntityMobEnderman>, world: World) : Ent
|
|||||||
override fun readAdditional(nbt: TagCompound) = nbt.heeTag.use {
|
override fun readAdditional(nbt: TagCompound) = nbt.heeTag.use {
|
||||||
super.readAdditional(nbt)
|
super.readAdditional(nbt)
|
||||||
|
|
||||||
teleportHandler.deserializeNBT(getCompound(TELEPORT_HANDLER_TAG))
|
components.deserializeFrom(this)
|
||||||
waterHandler.deserializeNBT(getCompound(WATER_HANDLER_TAG))
|
|
||||||
|
|
||||||
aiPickUpBlocks.enabled = getBoolean(CAN_PICK_UP_BLOCKS_TAG)
|
aiPickUpBlocks.enabled = getBoolean(CAN_PICK_UP_BLOCKS_TAG)
|
||||||
heldBlockTimer = getShort(HELD_BLOCK_TIMER_TAG)
|
heldBlockTimer = getShort(HELD_BLOCK_TIMER_TAG)
|
||||||
|
|||||||
@@ -56,11 +56,15 @@ import net.minecraft.block.BlockState
|
|||||||
import net.minecraft.entity.CreatureAttribute
|
import net.minecraft.entity.CreatureAttribute
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.entity.EntityType
|
import net.minecraft.entity.EntityType
|
||||||
|
import net.minecraft.entity.ILivingEntityData
|
||||||
import net.minecraft.entity.SharedMonsterAttributes.ATTACK_DAMAGE
|
import net.minecraft.entity.SharedMonsterAttributes.ATTACK_DAMAGE
|
||||||
import net.minecraft.entity.SharedMonsterAttributes.FOLLOW_RANGE
|
import net.minecraft.entity.SharedMonsterAttributes.FOLLOW_RANGE
|
||||||
import net.minecraft.entity.SharedMonsterAttributes.MAX_HEALTH
|
import net.minecraft.entity.SharedMonsterAttributes.MAX_HEALTH
|
||||||
import net.minecraft.entity.SharedMonsterAttributes.MOVEMENT_SPEED
|
import net.minecraft.entity.SharedMonsterAttributes.MOVEMENT_SPEED
|
||||||
|
import net.minecraft.entity.SpawnReason
|
||||||
|
import net.minecraft.entity.SpawnReason.SPAWNER
|
||||||
import net.minecraft.entity.ai.attributes.AttributeModifier
|
import net.minecraft.entity.ai.attributes.AttributeModifier
|
||||||
|
import net.minecraft.nbt.CompoundNBT
|
||||||
import net.minecraft.network.IPacket
|
import net.minecraft.network.IPacket
|
||||||
import net.minecraft.network.datasync.DataSerializers
|
import net.minecraft.network.datasync.DataSerializers
|
||||||
import net.minecraft.pathfinding.PathNavigator
|
import net.minecraft.pathfinding.PathNavigator
|
||||||
@@ -76,6 +80,8 @@ import net.minecraft.util.math.RayTraceResult.Type
|
|||||||
import net.minecraft.util.math.Vec3d
|
import net.minecraft.util.math.Vec3d
|
||||||
import net.minecraft.world.Difficulty.HARD
|
import net.minecraft.world.Difficulty.HARD
|
||||||
import net.minecraft.world.Difficulty.NORMAL
|
import net.minecraft.world.Difficulty.NORMAL
|
||||||
|
import net.minecraft.world.DifficultyInstance
|
||||||
|
import net.minecraft.world.IWorld
|
||||||
import net.minecraft.world.IWorldReader
|
import net.minecraft.world.IWorldReader
|
||||||
import net.minecraft.world.LightType.BLOCK
|
import net.minecraft.world.LightType.BLOCK
|
||||||
import net.minecraft.world.LightType.SKY
|
import net.minecraft.world.LightType.SKY
|
||||||
@@ -213,7 +219,7 @@ class EntityMobSpiderling(type: EntityType<EntityMobSpiderling>, world: World) :
|
|||||||
}
|
}
|
||||||
else if (wakeUpTimer > 0) {
|
else if (wakeUpTimer > 0) {
|
||||||
if (--wakeUpTimer == 0) {
|
if (--wakeUpTimer == 0) {
|
||||||
wakeUp(instant = false, preventSleep = false)
|
wakeUp(preventSleep = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ticksExisted % 4 == 0) {
|
else if (ticksExisted % 4 == 0) {
|
||||||
@@ -291,10 +297,18 @@ class EntityMobSpiderling(type: EntityType<EntityMobSpiderling>, world: World) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun wakeUp(instant: Boolean, preventSleep: Boolean) {
|
fun wakeUpInstantly(preventSleep: Boolean) {
|
||||||
|
wakeUp(preventSleep, aiDelayTicks = 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun wakeUp(preventSleep: Boolean) {
|
||||||
|
wakeUp(preventSleep, aiDelayTicks = rand.nextInt(25, 40))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun wakeUp(preventSleep: Boolean, aiDelayTicks: Int) {
|
||||||
if (isSleeping) {
|
if (isSleeping) {
|
||||||
isSleepingProp = false
|
isSleepingProp = false
|
||||||
wakeUpDelayAI = if (instant) 1 else rand.nextInt(25, 40)
|
wakeUpDelayAI = aiDelayTicks
|
||||||
|
|
||||||
if (preventSleep) {
|
if (preventSleep) {
|
||||||
canSleepAgain = false
|
canSleepAgain = false
|
||||||
@@ -303,7 +317,7 @@ class EntityMobSpiderling(type: EntityType<EntityMobSpiderling>, world: World) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setFire(seconds: Int) {
|
override fun setFire(seconds: Int) {
|
||||||
wakeUp(instant = true, preventSleep = true)
|
wakeUpInstantly(preventSleep = true)
|
||||||
super.setFire(seconds)
|
super.setFire(seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +328,7 @@ class EntityMobSpiderling(type: EntityType<EntityMobSpiderling>, world: World) :
|
|||||||
// Behavior (Light)
|
// Behavior (Light)
|
||||||
|
|
||||||
override fun onLightStartled(): Boolean {
|
override fun onLightStartled(): Boolean {
|
||||||
wakeUp(instant = false, preventSleep = true)
|
wakeUp(preventSleep = true)
|
||||||
|
|
||||||
if (world.totalTime < lightStartleResetTime) {
|
if (world.totalTime < lightStartleResetTime) {
|
||||||
return false
|
return false
|
||||||
@@ -401,7 +415,7 @@ class EntityMobSpiderling(type: EntityType<EntityMobSpiderling>, world: World) :
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
wakeUp(instant = true, preventSleep = true)
|
wakeUpInstantly(preventSleep = true)
|
||||||
|
|
||||||
if (!super.attackEntityFrom(source, if (source.isFireDamage) amount * 1.25F else amount)) {
|
if (!super.attackEntityFrom(source, if (source.isFireDamage) amount * 1.25F else amount)) {
|
||||||
return false
|
return false
|
||||||
@@ -445,6 +459,16 @@ class EntityMobSpiderling(type: EntityType<EntityMobSpiderling>, world: World) :
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Spawning
|
||||||
|
|
||||||
|
override fun onInitialSpawn(world: IWorld, difficulty: DifficultyInstance, reason: SpawnReason, data: ILivingEntityData?, nbt: CompoundNBT?): ILivingEntityData? {
|
||||||
|
if (reason == SPAWNER) {
|
||||||
|
wakeUpInstantly(preventSleep = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onInitialSpawn(world, difficulty, reason, data, nbt)
|
||||||
|
}
|
||||||
|
|
||||||
// Despawning
|
// Despawning
|
||||||
|
|
||||||
override fun isDespawnPeaceful(): Boolean {
|
override fun isDespawnPeaceful(): Boolean {
|
||||||
@@ -515,7 +539,7 @@ class EntityMobSpiderling(type: EntityType<EntityMobSpiderling>, world: World) :
|
|||||||
val sleepState = getInt(SLEEP_STATE_TAG)
|
val sleepState = getInt(SLEEP_STATE_TAG)
|
||||||
|
|
||||||
if (sleepState != 2) {
|
if (sleepState != 2) {
|
||||||
wakeUp(instant = true, preventSleep = sleepState != 1)
|
wakeUpInstantly(preventSleep = sleepState != 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
lightStartleResetTime = getLong(LIGHT_STARTLE_RESET_TIME_TAG)
|
lightStartleResetTime = getLong(LIGHT_STARTLE_RESET_TIME_TAG)
|
||||||
|
|||||||
@@ -137,19 +137,19 @@ class EntityMobUndread(type: EntityType<EntityMobUndread>, world: World) : Entit
|
|||||||
super.onDeathUpdate()
|
super.onDeathUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun playStepSound(pos: BlockPos, state: BlockState) {
|
public override fun playStepSound(pos: BlockPos, state: BlockState) {
|
||||||
playSound(Sounds.ENTITY_ZOMBIE_STEP, rand.nextFloat(0.4F, 0.5F), rand.nextFloat(0.9F, 1F))
|
playSound(Sounds.ENTITY_ZOMBIE_STEP, rand.nextFloat(0.4F, 0.5F), rand.nextFloat(0.9F, 1F))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getHurtSound(source: DamageSource): SoundEvent {
|
public override fun getHurtSound(source: DamageSource): SoundEvent {
|
||||||
return ModSounds.MOB_UNDREAD_HURT
|
return ModSounds.MOB_UNDREAD_HURT
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDeathSound(): SoundEvent {
|
public override fun getDeathSound(): SoundEvent {
|
||||||
return ModSounds.MOB_UNDREAD_DEATH
|
return ModSounds.MOB_UNDREAD_DEATH
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSoundPitch(): Float {
|
public override fun getSoundPitch(): Float {
|
||||||
return rand.nextFloat(0.8F, 1F)
|
return rand.nextFloat(0.8F, 1F)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import chylex.hee.game.particle.spawner.ParticleSpawnerCustom
|
|||||||
import chylex.hee.game.particle.spawner.properties.IShape.Point
|
import chylex.hee.game.particle.spawner.properties.IShape.Point
|
||||||
import chylex.hee.game.world.bottomCenter
|
import chylex.hee.game.world.bottomCenter
|
||||||
import chylex.hee.network.client.PacketClientFX
|
import chylex.hee.network.client.PacketClientFX
|
||||||
import chylex.hee.network.fx.IFxData
|
import chylex.hee.network.fx.FxVecData
|
||||||
import chylex.hee.network.fx.IFxHandler
|
import chylex.hee.network.fx.FxVecHandler
|
||||||
import chylex.hee.system.color.IntColor.Companion.RGB
|
import chylex.hee.system.color.IntColor.Companion.RGB
|
||||||
import chylex.hee.system.math.Vec
|
import chylex.hee.system.math.Vec
|
||||||
import chylex.hee.system.math.Vec3
|
import chylex.hee.system.math.Vec3
|
||||||
@@ -21,10 +21,7 @@ import chylex.hee.system.serialization.NBTList.Companion.putList
|
|||||||
import chylex.hee.system.serialization.NBTObjectList
|
import chylex.hee.system.serialization.NBTObjectList
|
||||||
import chylex.hee.system.serialization.TagCompound
|
import chylex.hee.system.serialization.TagCompound
|
||||||
import chylex.hee.system.serialization.getListOfCompounds
|
import chylex.hee.system.serialization.getListOfCompounds
|
||||||
import chylex.hee.system.serialization.readVec
|
|
||||||
import chylex.hee.system.serialization.use
|
import chylex.hee.system.serialization.use
|
||||||
import chylex.hee.system.serialization.writeVec
|
|
||||||
import net.minecraft.network.PacketBuffer
|
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.math.Vec3d
|
import net.minecraft.util.math.Vec3d
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
@@ -50,15 +47,9 @@ class EnderEyeSpawnerParticles(private val entity: EntityBossEnderEye) : INBTSer
|
|||||||
hideOnMinimalSetting = false
|
hideOnMinimalSetting = false
|
||||||
)
|
)
|
||||||
|
|
||||||
class ParticleData(private val point: Vec3d) : IFxData {
|
val FX_PARTICLE = object : FxVecHandler() {
|
||||||
override fun write(buffer: PacketBuffer) = buffer.use {
|
override fun handle(world: World, rand: Random, vec: Vec3d) {
|
||||||
writeVec(point)
|
PARTICLE_TICK.spawn(Point(vec, 2), rand)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val FX_PARTICLE = object : IFxHandler<ParticleData> {
|
|
||||||
override fun handle(buffer: PacketBuffer, world: World, rand: Random) = buffer.use {
|
|
||||||
PARTICLE_TICK.spawn(Point(readVec(), 2), rand)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +86,7 @@ class EnderEyeSpawnerParticles(private val entity: EntityBossEnderEye) : INBTSer
|
|||||||
else -> 1.0
|
else -> 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketClientFX(FX_PARTICLE, ParticleData(pos.addY(sqrt(progressCurvePoint) * 6.0))).sendToAllAround(entity.world, pos, 256.0)
|
PacketClientFX(FX_PARTICLE, FxVecData(pos.addY(sqrt(progressCurvePoint) * 6.0))).sendToAllAround(entity.world, pos, 256.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (distSq > prevDistSq || distSq < square(0.15)) {
|
if (distSq > prevDistSq || distSq < square(0.15)) {
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import chylex.hee.network.client.PacketClientFX
|
|||||||
import chylex.hee.network.fx.FxEntityData
|
import chylex.hee.network.fx.FxEntityData
|
||||||
import chylex.hee.network.fx.FxEntityHandler
|
import chylex.hee.network.fx.FxEntityHandler
|
||||||
import chylex.hee.system.color.IntColor.Companion.RGB
|
import chylex.hee.system.color.IntColor.Companion.RGB
|
||||||
|
import chylex.hee.system.component.general.SerializableComponent
|
||||||
|
import chylex.hee.system.component.general.TickableComponent
|
||||||
import chylex.hee.system.math.Vec
|
import chylex.hee.system.math.Vec
|
||||||
import chylex.hee.system.math.Vec3
|
import chylex.hee.system.math.Vec3
|
||||||
import chylex.hee.system.math.addY
|
import chylex.hee.system.math.addY
|
||||||
@@ -53,13 +55,12 @@ import net.minecraft.util.SoundCategory
|
|||||||
import net.minecraft.util.math.AxisAlignedBB
|
import net.minecraft.util.math.AxisAlignedBB
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.math.Vec3d
|
import net.minecraft.util.math.Vec3d
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
class EndermanTeleportHandler(private val enderman: EntityMobAbstractEnderman) : INBTSerializable<TagCompound> {
|
class EndermanTeleportHandler(private val enderman: EntityMobAbstractEnderman) : TickableComponent, SerializableComponent {
|
||||||
companion object {
|
companion object {
|
||||||
private const val DEFAULT_RESTORE_Y = -256.0
|
private const val DEFAULT_RESTORE_Y = -256.0
|
||||||
|
|
||||||
@@ -117,6 +118,9 @@ class EndermanTeleportHandler(private val enderman: EntityMobAbstractEnderman) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val serializationKey
|
||||||
|
get() = "Teleport"
|
||||||
|
|
||||||
val preventDespawn
|
val preventDespawn
|
||||||
get() = tpDelayTicks > 0
|
get() = tpDelayTicks > 0
|
||||||
|
|
||||||
@@ -133,7 +137,7 @@ class EndermanTeleportHandler(private val enderman: EntityMobAbstractEnderman) :
|
|||||||
|
|
||||||
private var lastDodged: UUID? = null
|
private var lastDodged: UUID? = null
|
||||||
|
|
||||||
fun update() {
|
override fun tickServer() {
|
||||||
if (tpCooldown > 0) {
|
if (tpCooldown > 0) {
|
||||||
--tpCooldown
|
--tpCooldown
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,16 @@ import chylex.hee.game.entity.OPERATION_MUL_INCR_INDIVIDUAL
|
|||||||
import chylex.hee.game.entity.living.EntityMobAbstractEnderman
|
import chylex.hee.game.entity.living.EntityMobAbstractEnderman
|
||||||
import chylex.hee.game.entity.tryApplyModifier
|
import chylex.hee.game.entity.tryApplyModifier
|
||||||
import chylex.hee.game.entity.tryRemoveModifier
|
import chylex.hee.game.entity.tryRemoveModifier
|
||||||
|
import chylex.hee.system.component.general.SerializableComponent
|
||||||
|
import chylex.hee.system.component.general.TickableComponent
|
||||||
import chylex.hee.system.random.nextInt
|
import chylex.hee.system.random.nextInt
|
||||||
import chylex.hee.system.serialization.TagCompound
|
import chylex.hee.system.serialization.TagCompound
|
||||||
import chylex.hee.system.serialization.use
|
import chylex.hee.system.serialization.use
|
||||||
import net.minecraft.entity.SharedMonsterAttributes.ATTACK_DAMAGE
|
import net.minecraft.entity.SharedMonsterAttributes.ATTACK_DAMAGE
|
||||||
import net.minecraft.entity.ai.attributes.AttributeModifier
|
import net.minecraft.entity.ai.attributes.AttributeModifier
|
||||||
import net.minecraft.util.DamageSource
|
import net.minecraft.util.DamageSource
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
|
||||||
|
|
||||||
class EndermanWaterHandler(private val enderman: EntityMobAbstractEnderman, private val takeDamageAfterWetTicks: Int) : INBTSerializable<TagCompound> {
|
class EndermanWaterHandler(private val enderman: EntityMobAbstractEnderman, private val takeDamageAfterWetTicks: Int) : TickableComponent, SerializableComponent {
|
||||||
private companion object {
|
private companion object {
|
||||||
private val DEBUFF_WEAKNESS = AttributeModifier("Water weakness", -0.5, OPERATION_MUL_INCR_INDIVIDUAL)
|
private val DEBUFF_WEAKNESS = AttributeModifier("Water weakness", -0.5, OPERATION_MUL_INCR_INDIVIDUAL)
|
||||||
|
|
||||||
@@ -20,10 +21,13 @@ class EndermanWaterHandler(private val enderman: EntityMobAbstractEnderman, priv
|
|||||||
private const val DEBUFF_TICKS_TAG = "DebuffTicks"
|
private const val DEBUFF_TICKS_TAG = "DebuffTicks"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val serializationKey
|
||||||
|
get() = "Water"
|
||||||
|
|
||||||
private var wetCounter = 0
|
private var wetCounter = 0
|
||||||
private var debuffTicks = 0
|
private var debuffTicks = 0
|
||||||
|
|
||||||
fun update() {
|
override fun tickServer() {
|
||||||
val isWet = enderman.isWet
|
val isWet = enderman.isWet
|
||||||
|
|
||||||
if (isWet) {
|
if (isWet) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import chylex.hee.game.world.feature.stronghold.piece.StrongholdRoom_Main_Portal
|
|||||||
import chylex.hee.game.world.feature.stronghold.piece.StrongholdRoom_Trap_CornerHoles
|
import chylex.hee.game.world.feature.stronghold.piece.StrongholdRoom_Trap_CornerHoles
|
||||||
import chylex.hee.game.world.feature.stronghold.piece.StrongholdRoom_Trap_Prison
|
import chylex.hee.game.world.feature.stronghold.piece.StrongholdRoom_Trap_Prison
|
||||||
import chylex.hee.game.world.feature.stronghold.piece.StrongholdRoom_Trap_TallIntersection
|
import chylex.hee.game.world.feature.stronghold.piece.StrongholdRoom_Trap_TallIntersection
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.piece.TombDungeonRoom_Tomb
|
||||||
import chylex.hee.init.ModEntities
|
import chylex.hee.init.ModEntities
|
||||||
import chylex.hee.system.delegate.NotifyOnChange
|
import chylex.hee.system.delegate.NotifyOnChange
|
||||||
import chylex.hee.system.serialization.TagCompound
|
import chylex.hee.system.serialization.TagCompound
|
||||||
@@ -28,6 +29,10 @@ class EntityTechnicalTrigger(type: EntityType<EntityTechnicalTrigger>, world: Wo
|
|||||||
this.type = type
|
this.type = type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(world: World, type: Types, nbt: TagCompound) : this(world, type) {
|
||||||
|
handler.deserializeNBT(nbt)
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private const val TYPE_TAG = "Type"
|
private const val TYPE_TAG = "Type"
|
||||||
private const val DATA_TAG = "Data"
|
private const val DATA_TAG = "Data"
|
||||||
@@ -62,6 +67,7 @@ class EntityTechnicalTrigger(type: EntityType<EntityTechnicalTrigger>, world: Wo
|
|||||||
STRONGHOLD_TRAP_TALL_INTERSECTION({ StrongholdRoom_Trap_TallIntersection.Trigger }),
|
STRONGHOLD_TRAP_TALL_INTERSECTION({ StrongholdRoom_Trap_TallIntersection.Trigger }),
|
||||||
ENERGY_SHRINE_GENERATOR({ EnergyShrineGenerator.GeneratorTrigger }),
|
ENERGY_SHRINE_GENERATOR({ EnergyShrineGenerator.GeneratorTrigger }),
|
||||||
ENERGY_SHRINE_GLOBAL({ EnergyShrineRoom_Main_Start.Particles }),
|
ENERGY_SHRINE_GLOBAL({ EnergyShrineRoom_Main_Start.Particles }),
|
||||||
|
TOMB_DUNGEON_UNDREAD_SPAWNER(TombDungeonRoom_Tomb::MobSpawnerTrigger),
|
||||||
OBSIDIAN_TOWER_TOP_GLOWSTONE(ObsidianTowerLevel_Top::GlowstoneTrigger),
|
OBSIDIAN_TOWER_TOP_GLOWSTONE(ObsidianTowerLevel_Top::GlowstoneTrigger),
|
||||||
OBSIDIAN_TOWER_DEATH_ANIMATION(ObsidianTowerLevel_Top::DeathAnimationTrigger)
|
OBSIDIAN_TOWER_DEATH_ANIMATION(ObsidianTowerLevel_Top::DeathAnimationTrigger)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package chylex.hee.game.item
|
|||||||
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
||||||
import chylex.hee.game.inventory.heeTag
|
import chylex.hee.game.inventory.heeTag
|
||||||
import chylex.hee.game.inventory.heeTagOrNull
|
import chylex.hee.game.inventory.heeTagOrNull
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.mechanics.energy.IEnergyQuantity
|
import chylex.hee.game.mechanics.energy.IEnergyQuantity
|
||||||
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Units
|
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Units
|
||||||
import chylex.hee.game.particle.ParticleEnergyTransferToPlayer
|
import chylex.hee.game.particle.ParticleEnergyTransferToPlayer
|
||||||
@@ -36,11 +37,11 @@ import chylex.hee.system.serialization.use
|
|||||||
import chylex.hee.system.serialization.writePos
|
import chylex.hee.system.serialization.writePos
|
||||||
import net.minecraft.client.util.ITooltipFlag
|
import net.minecraft.client.util.ITooltipFlag
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.network.PacketBuffer
|
import net.minecraft.network.PacketBuffer
|
||||||
import net.minecraft.util.ActionResultType
|
import net.minecraft.util.ActionResultType
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.math.MathHelper
|
import net.minecraft.util.math.MathHelper
|
||||||
import net.minecraft.util.text.ITextComponent
|
import net.minecraft.util.text.ITextComponent
|
||||||
import net.minecraft.util.text.TranslationTextComponent
|
import net.minecraft.util.text.TranslationTextComponent
|
||||||
@@ -50,7 +51,7 @@ import java.util.Random
|
|||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
abstract class ItemAbstractEnergyUser(properties: Properties) : Item(properties) {
|
abstract class ItemAbstractEnergyUser(properties: Properties) : ItemWithComponents(properties), UseOnBlockComponent {
|
||||||
companion object {
|
companion object {
|
||||||
private const val ENERGY_LEVEL_TAG = "EnergyLevel"
|
private const val ENERGY_LEVEL_TAG = "EnergyLevel"
|
||||||
|
|
||||||
@@ -100,6 +101,8 @@ abstract class ItemAbstractEnergyUser(properties: Properties) : Item(properties)
|
|||||||
init {
|
init {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
require(maxStackSize == 1) { "energy item must have a maximum stack size of 1" }
|
require(maxStackSize == 1) { "energy item must have a maximum stack size of 1" }
|
||||||
|
|
||||||
|
components.attach(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun getEnergyCapacity(stack: ItemStack): Units
|
protected abstract fun getEnergyCapacity(stack: ItemStack): Units
|
||||||
@@ -163,15 +166,11 @@ abstract class ItemAbstractEnergyUser(properties: Properties) : Item(properties)
|
|||||||
|
|
||||||
// Energy charging
|
// Energy charging
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType? {
|
||||||
val player = context.player ?: return FAIL
|
|
||||||
val world = context.world
|
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
val tile = pos.getTile<TileEntityEnergyCluster>(world)
|
val tile = pos.getTile<TileEntityEnergyCluster>(world)
|
||||||
val stack = player.getHeldItem(context.hand)
|
val stack = player.getHeldItem(ctx.hand)
|
||||||
|
|
||||||
if (tile == null || !player.canPlayerEdit(pos, context.face, stack)) {
|
if (tile == null || !player.canPlayerEdit(pos, ctx.face, stack)) {
|
||||||
return FAIL
|
return FAIL
|
||||||
}
|
}
|
||||||
else if (world.isRemote) {
|
else if (world.isRemote) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import net.minecraft.util.text.StringTextComponent
|
|||||||
import net.minecraft.util.text.TranslationTextComponent
|
import net.minecraft.util.text.TranslationTextComponent
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
|
|
||||||
abstract class ItemAbstractInfusable(properties: Properties) : Item(properties), IInfusableItem {
|
abstract class ItemAbstractInfusable(properties: Properties) : ItemWithComponents(properties), IInfusableItem {
|
||||||
companion object {
|
companion object {
|
||||||
fun onCanApplyInfusion(item: Item, infusion: Infusion): Boolean {
|
fun onCanApplyInfusion(item: Item, infusion: Infusion): Boolean {
|
||||||
return infusion.targetItems.contains(item)
|
return infusion.targetItems.contains(item)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package chylex.hee.game.item
|
package chylex.hee.game.item
|
||||||
|
|
||||||
import chylex.hee.game.inventory.size
|
import chylex.hee.game.inventory.size
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.world.BlockEditor
|
import chylex.hee.game.world.BlockEditor
|
||||||
import chylex.hee.init.ModItems
|
import chylex.hee.init.ModItems
|
||||||
import chylex.hee.network.client.PacketClientFX
|
import chylex.hee.network.client.PacketClientFX
|
||||||
@@ -15,7 +16,6 @@ import chylex.hee.system.migration.ItemBoneMeal
|
|||||||
import net.minecraft.block.DispenserBlock.FACING
|
import net.minecraft.block.DispenserBlock.FACING
|
||||||
import net.minecraft.dispenser.IBlockSource
|
import net.minecraft.dispenser.IBlockSource
|
||||||
import net.minecraft.dispenser.OptionalDispenseBehavior
|
import net.minecraft.dispenser.OptionalDispenseBehavior
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.util.ActionResultType
|
import net.minecraft.util.ActionResultType
|
||||||
@@ -25,7 +25,7 @@ import net.minecraft.world.server.ServerWorld
|
|||||||
import net.minecraftforge.common.util.FakePlayerFactory
|
import net.minecraftforge.common.util.FakePlayerFactory
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
class ItemCompost(properties: Properties) : Item(properties) {
|
class ItemCompost(properties: Properties) : ItemWithComponents(properties) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val BONE_MEAL_EQUIVALENT = 2
|
private const val BONE_MEAL_EQUIVALENT = 2
|
||||||
|
|
||||||
@@ -61,6 +61,24 @@ class ItemCompost(properties: Properties) : Item(properties) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
components.attach(object : UseOnBlockComponent {
|
||||||
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType {
|
||||||
|
if (!BlockEditor.canEdit(pos, player, item)) {
|
||||||
|
return FAIL
|
||||||
|
}
|
||||||
|
else if (world.isRemote) {
|
||||||
|
return SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applyCompost(world, pos, player)) {
|
||||||
|
item.shrink(1)
|
||||||
|
return SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
return PASS
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
BlockDispenser.registerDispenseBehavior(this, object : OptionalDispenseBehavior() {
|
BlockDispenser.registerDispenseBehavior(this, object : OptionalDispenseBehavior() {
|
||||||
override fun dispenseStack(source: IBlockSource, stack: ItemStack): ItemStack {
|
override fun dispenseStack(source: IBlockSource, stack: ItemStack): ItemStack {
|
||||||
val world = source.world
|
val world = source.world
|
||||||
@@ -77,26 +95,4 @@ class ItemCompost(properties: Properties) : Item(properties) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
|
||||||
val player = context.player ?: return FAIL
|
|
||||||
val world = context.world
|
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
|
||||||
|
|
||||||
if (!BlockEditor.canEdit(pos, player, heldItem)) {
|
|
||||||
return FAIL
|
|
||||||
}
|
|
||||||
else if (world.isRemote) {
|
|
||||||
return SUCCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applyCompost(world, pos, player)) {
|
|
||||||
heldItem.shrink(1)
|
|
||||||
return SUCCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
return PASS
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,27 +2,27 @@ package chylex.hee.game.item
|
|||||||
|
|
||||||
import chylex.hee.game.block.IBlockDeathFlowerDecaying
|
import chylex.hee.game.block.IBlockDeathFlowerDecaying
|
||||||
import chylex.hee.game.entity.item.EntityItemCauldronTrigger
|
import chylex.hee.game.entity.item.EntityItemCauldronTrigger
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.world.BlockEditor
|
import chylex.hee.game.world.BlockEditor
|
||||||
import chylex.hee.game.world.getBlock
|
import chylex.hee.game.world.getBlock
|
||||||
import chylex.hee.system.migration.ActionResult.FAIL
|
import chylex.hee.system.migration.ActionResult.FAIL
|
||||||
import chylex.hee.system.migration.ActionResult.PASS
|
import chylex.hee.system.migration.ActionResult.PASS
|
||||||
import chylex.hee.system.migration.ActionResult.SUCCESS
|
import chylex.hee.system.migration.ActionResult.SUCCESS
|
||||||
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.util.ActionResultType
|
import net.minecraft.util.ActionResultType
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
|
|
||||||
class ItemEndPowder(properties: Properties) : Item(properties) {
|
class ItemEndPowder(properties: Properties) : ItemWithComponents(properties), UseOnBlockComponent {
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
init {
|
||||||
val player = context.player ?: return FAIL
|
components.attach(this)
|
||||||
val world = context.world
|
}
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType? {
|
||||||
|
if (!BlockEditor.canEdit(pos, player, item)) {
|
||||||
if (!BlockEditor.canEdit(pos, player, heldItem)) {
|
|
||||||
return FAIL
|
return FAIL
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class ItemEndPowder(properties: Properties) : Item(properties) {
|
|||||||
block.healDeathFlower(world, pos)
|
block.healDeathFlower(world, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
heldItem.shrink(1)
|
item.shrink(1)
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import chylex.hee.system.math.angleBetween
|
|||||||
import chylex.hee.system.math.floorToInt
|
import chylex.hee.system.math.floorToInt
|
||||||
import chylex.hee.system.math.over
|
import chylex.hee.system.math.over
|
||||||
import chylex.hee.system.math.toDegrees
|
import chylex.hee.system.math.toDegrees
|
||||||
import chylex.hee.system.migration.ActionResult.FAIL
|
|
||||||
import chylex.hee.system.migration.ActionResult.SUCCESS
|
import chylex.hee.system.migration.ActionResult.SUCCESS
|
||||||
import chylex.hee.system.migration.EntityLivingBase
|
import chylex.hee.system.migration.EntityLivingBase
|
||||||
import chylex.hee.system.migration.EntityPlayer
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
@@ -150,17 +149,13 @@ class ItemEnergyOracle(properties: Properties) : ItemAbstractEnergyUser(properti
|
|||||||
return ItemAbstractInfusable.onCanApplyInfusion(this, infusion)
|
return ItemAbstractInfusable.onCanApplyInfusion(this, infusion)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType? {
|
||||||
val player = context.player ?: return FAIL
|
|
||||||
val world = context.world
|
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
if (player.isSneaking && pos.getTile<TileEntityEnergyCluster>(world) != null) {
|
if (player.isSneaking && pos.getTile<TileEntityEnergyCluster>(world) != null) {
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
val heldItem = player.getHeldItem(ctx.hand)
|
||||||
val entry = pos.toLong()
|
val entry = pos.toLong()
|
||||||
|
|
||||||
with(heldItem.heeTag) {
|
with(heldItem.heeTag) {
|
||||||
@@ -176,7 +171,7 @@ class ItemEnergyOracle(properties: Properties) : ItemAbstractEnergyUser(properti
|
|||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onItemUse(context)
|
return super.useOnBlock(world, pos, player, item, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inventoryTick(stack: ItemStack, world: World, entity: Entity, itemSlot: Int, isSelected: Boolean) {
|
override fun inventoryTick(stack: ItemStack, world: World, entity: Entity, itemSlot: Int, isSelected: Boolean) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import chylex.hee.client.color.NO_TINT
|
|||||||
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
||||||
import chylex.hee.game.inventory.heeTag
|
import chylex.hee.game.inventory.heeTag
|
||||||
import chylex.hee.game.inventory.heeTagOrNull
|
import chylex.hee.game.inventory.heeTagOrNull
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.item.infusion.Infusion.SAFETY
|
import chylex.hee.game.item.infusion.Infusion.SAFETY
|
||||||
import chylex.hee.game.item.infusion.Infusion.STABILITY
|
import chylex.hee.game.item.infusion.Infusion.STABILITY
|
||||||
import chylex.hee.game.item.infusion.InfusionList
|
import chylex.hee.game.item.infusion.InfusionList
|
||||||
@@ -27,10 +28,10 @@ import chylex.hee.system.forge.Side
|
|||||||
import chylex.hee.system.forge.Sided
|
import chylex.hee.system.forge.Sided
|
||||||
import chylex.hee.system.migration.ActionResult.FAIL
|
import chylex.hee.system.migration.ActionResult.FAIL
|
||||||
import chylex.hee.system.migration.ActionResult.SUCCESS
|
import chylex.hee.system.migration.ActionResult.SUCCESS
|
||||||
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
import chylex.hee.system.serialization.TagCompound
|
import chylex.hee.system.serialization.TagCompound
|
||||||
import chylex.hee.system.serialization.getIntegerOrNull
|
import chylex.hee.system.serialization.getIntegerOrNull
|
||||||
import chylex.hee.system.serialization.hasKey
|
import chylex.hee.system.serialization.hasKey
|
||||||
import chylex.hee.system.serialization.use
|
|
||||||
import net.minecraft.client.renderer.color.IItemColor
|
import net.minecraft.client.renderer.color.IItemColor
|
||||||
import net.minecraft.client.util.ITooltipFlag
|
import net.minecraft.client.util.ITooltipFlag
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
@@ -43,7 +44,7 @@ import net.minecraft.util.text.TranslationTextComponent
|
|||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
class ItemEnergyReceptacle(properties: Properties) : ItemAbstractInfusable(properties) {
|
class ItemEnergyReceptacle(properties: Properties) : ItemAbstractInfusable(properties), UseOnBlockComponent {
|
||||||
private companion object {
|
private companion object {
|
||||||
private const val CLUSTER_SNAPSHOT_TAG = "Cluster"
|
private const val CLUSTER_SNAPSHOT_TAG = "Cluster"
|
||||||
private const val UPDATE_TIME_TAG = "UpdateTime"
|
private const val UPDATE_TIME_TAG = "UpdateTime"
|
||||||
@@ -105,18 +106,14 @@ class ItemEnergyReceptacle(properties: Properties) : ItemAbstractInfusable(prope
|
|||||||
}
|
}
|
||||||
|
|
||||||
// POLISH tweak animation
|
// POLISH tweak animation
|
||||||
|
|
||||||
|
components.attach(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType? {
|
||||||
val player = context.player ?: return FAIL
|
with(item.heeTag) {
|
||||||
val world = context.world
|
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
val stack = player.getHeldItem(context.hand)
|
|
||||||
|
|
||||||
stack.heeTag.use {
|
|
||||||
if (hasKey(CLUSTER_SNAPSHOT_TAG)) {
|
if (hasKey(CLUSTER_SNAPSHOT_TAG)) {
|
||||||
val finalPos = BlockEditor.place(ModBlocks.ENERGY_CLUSTER, player, stack, context)
|
val finalPos = BlockEditor.place(ModBlocks.ENERGY_CLUSTER, player, item, ctx)
|
||||||
|
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
@@ -126,7 +123,7 @@ class ItemEnergyReceptacle(properties: Properties) : ItemAbstractInfusable(prope
|
|||||||
finalPos.getTile<TileEntityEnergyCluster>(world)?.let {
|
finalPos.getTile<TileEntityEnergyCluster>(world)?.let {
|
||||||
it.loadClusterSnapshot(ClusterSnapshot(getCompound(CLUSTER_SNAPSHOT_TAG)), inactive = false)
|
it.loadClusterSnapshot(ClusterSnapshot(getCompound(CLUSTER_SNAPSHOT_TAG)), inactive = false)
|
||||||
|
|
||||||
if (shouldLoseHealth(it, this, InfusionTag.getList(stack))) {
|
if (shouldLoseHealth(it, this, InfusionTag.getList(item))) {
|
||||||
it.deteriorateHealth()
|
it.deteriorateHealth()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +138,7 @@ class ItemEnergyReceptacle(properties: Properties) : ItemAbstractInfusable(prope
|
|||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (BlockEditor.canEdit(pos, player, stack)) {
|
else if (BlockEditor.canEdit(pos, player, item)) {
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import chylex.hee.game.entity.heeTag
|
|||||||
import chylex.hee.game.entity.heeTagOrNull
|
import chylex.hee.game.entity.heeTagOrNull
|
||||||
import chylex.hee.game.entity.posVec
|
import chylex.hee.game.entity.posVec
|
||||||
import chylex.hee.game.inventory.doDamage
|
import chylex.hee.game.inventory.doDamage
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.world.BlockEditor
|
import chylex.hee.game.world.BlockEditor
|
||||||
import chylex.hee.game.world.FLAG_NONE
|
import chylex.hee.game.world.FLAG_NONE
|
||||||
import chylex.hee.game.world.getBlock
|
import chylex.hee.game.world.getBlock
|
||||||
@@ -14,7 +15,6 @@ import chylex.hee.game.world.playServer
|
|||||||
import chylex.hee.game.world.removeBlock
|
import chylex.hee.game.world.removeBlock
|
||||||
import chylex.hee.game.world.setBlock
|
import chylex.hee.game.world.setBlock
|
||||||
import chylex.hee.init.ModBlocks
|
import chylex.hee.init.ModBlocks
|
||||||
import chylex.hee.system.compatibility.MinecraftForgeEventBus
|
|
||||||
import chylex.hee.system.forge.EventPriority
|
import chylex.hee.system.forge.EventPriority
|
||||||
import chylex.hee.system.forge.SubscribeAllEvents
|
import chylex.hee.system.forge.SubscribeAllEvents
|
||||||
import chylex.hee.system.forge.SubscribeEvent
|
import chylex.hee.system.forge.SubscribeEvent
|
||||||
@@ -26,7 +26,6 @@ import chylex.hee.system.migration.EntityPlayer
|
|||||||
import chylex.hee.system.migration.Sounds
|
import chylex.hee.system.migration.Sounds
|
||||||
import chylex.hee.system.random.nextFloat
|
import chylex.hee.system.random.nextFloat
|
||||||
import net.minecraft.block.Blocks
|
import net.minecraft.block.Blocks
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.util.ActionResultType
|
import net.minecraft.util.ActionResultType
|
||||||
@@ -36,7 +35,7 @@ import net.minecraft.util.math.BlockPos
|
|||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
import net.minecraftforge.event.world.ExplosionEvent
|
import net.minecraftforge.event.world.ExplosionEvent
|
||||||
|
|
||||||
class ItemFlintAndInfernium(properties: Properties) : Item(properties) {
|
class ItemFlintAndInfernium(properties: Properties) : ItemWithComponents(properties), UseOnBlockComponent {
|
||||||
@SubscribeAllEvents(modid = HEE.ID)
|
@SubscribeAllEvents(modid = HEE.ID)
|
||||||
companion object {
|
companion object {
|
||||||
private const val CREEPER_INFERNIUM_TAG = "Infernium"
|
private const val CREEPER_INFERNIUM_TAG = "Infernium"
|
||||||
@@ -55,7 +54,7 @@ class ItemFlintAndInfernium(properties: Properties) : Item(properties) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
MinecraftForgeEventBus.register(this)
|
components.attach(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun igniteTNT(world: World, pos: BlockPos, player: EntityPlayer?, ignoreTrap: Boolean) {
|
fun igniteTNT(world: World, pos: BlockPos, player: EntityPlayer?, ignoreTrap: Boolean) {
|
||||||
@@ -67,14 +66,8 @@ class ItemFlintAndInfernium(properties: Properties) : Item(properties) {
|
|||||||
pos.removeBlock(world)
|
pos.removeBlock(world)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType? {
|
||||||
val player = context.player ?: return FAIL
|
if (!BlockEditor.canEdit(pos, player, item)) {
|
||||||
val world = context.world
|
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
|
||||||
|
|
||||||
if (!BlockEditor.canEdit(pos, player, heldItem)) {
|
|
||||||
return FAIL
|
return FAIL
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,11 +78,11 @@ class ItemFlintAndInfernium(properties: Properties) : Item(properties) {
|
|||||||
igniteTNT(world, pos, player, ignoreTrap = false)
|
igniteTNT(world, pos, player, ignoreTrap = false)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BlockEditor.place(ModBlocks.ETERNAL_FIRE, player, heldItem, context) ?: return FAIL
|
BlockEditor.place(ModBlocks.ETERNAL_FIRE, player, item, ctx) ?: return FAIL
|
||||||
}
|
}
|
||||||
|
|
||||||
Sounds.ITEM_FLINTANDSTEEL_USE.playServer(world, pos, SoundCategory.BLOCKS, volume = 1.1F, pitch = world.rand.nextFloat(0.4F, 0.5F))
|
Sounds.ITEM_FLINTANDSTEEL_USE.playServer(world, pos, SoundCategory.BLOCKS, volume = 1.1F, pitch = world.rand.nextFloat(0.4F, 0.5F))
|
||||||
heldItem.doDamage(1, player, context.hand)
|
item.doDamage(1, player, ctx.hand)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import chylex.hee.game.entity.item.EntityTokenHolder
|
|||||||
import chylex.hee.game.entity.selectExistingEntities
|
import chylex.hee.game.entity.selectExistingEntities
|
||||||
import chylex.hee.game.inventory.heeTag
|
import chylex.hee.game.inventory.heeTag
|
||||||
import chylex.hee.game.inventory.heeTagOrNull
|
import chylex.hee.game.inventory.heeTagOrNull
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.mechanics.portal.DimensionTeleporter
|
import chylex.hee.game.mechanics.portal.DimensionTeleporter
|
||||||
import chylex.hee.game.mechanics.portal.EntityPortalContact
|
import chylex.hee.game.mechanics.portal.EntityPortalContact
|
||||||
import chylex.hee.game.world.BlockEditor
|
import chylex.hee.game.world.BlockEditor
|
||||||
@@ -34,7 +35,6 @@ import chylex.hee.system.serialization.putEnum
|
|||||||
import net.minecraft.client.renderer.color.IItemColor
|
import net.minecraft.client.renderer.color.IItemColor
|
||||||
import net.minecraft.client.util.ITooltipFlag
|
import net.minecraft.client.util.ITooltipFlag
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemGroup
|
import net.minecraft.item.ItemGroup
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
@@ -43,13 +43,14 @@ import net.minecraft.util.ActionResultType
|
|||||||
import net.minecraft.util.Hand
|
import net.minecraft.util.Hand
|
||||||
import net.minecraft.util.NonNullList
|
import net.minecraft.util.NonNullList
|
||||||
import net.minecraft.util.math.AxisAlignedBB
|
import net.minecraft.util.math.AxisAlignedBB
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.text.ITextComponent
|
import net.minecraft.util.text.ITextComponent
|
||||||
import net.minecraft.util.text.StringTextComponent
|
import net.minecraft.util.text.StringTextComponent
|
||||||
import net.minecraft.util.text.TranslationTextComponent
|
import net.minecraft.util.text.TranslationTextComponent
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
import net.minecraft.world.dimension.DimensionType
|
import net.minecraft.world.dimension.DimensionType
|
||||||
|
|
||||||
class ItemPortalToken(properties: Properties) : Item(properties) {
|
class ItemPortalToken(properties: Properties) : ItemWithComponents(properties), UseOnBlockComponent {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TYPE_TAG = "Type"
|
private const val TYPE_TAG = "Type"
|
||||||
private const val TERRITORY_TYPE_TAG = "Territory"
|
private const val TERRITORY_TYPE_TAG = "Territory"
|
||||||
@@ -72,6 +73,8 @@ class ItemPortalToken(properties: Properties) : Item(properties) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
components.attach(this)
|
||||||
|
|
||||||
addPropertyOverride(Resource.Custom("token_type")) { stack, _, _ ->
|
addPropertyOverride(Resource.Custom("token_type")) { stack, _, _ ->
|
||||||
getTokenType(stack).propertyValue + (if (stack.heeTagOrNull.hasKey(IS_CORRUPTED_TAG)) 0.5F else 0F)
|
getTokenType(stack).propertyValue + (if (stack.heeTagOrNull.hasKey(IS_CORRUPTED_TAG)) 0.5F else 0F)
|
||||||
}
|
}
|
||||||
@@ -178,10 +181,7 @@ class ItemPortalToken(properties: Properties) : Item(properties) {
|
|||||||
return ActionResult(SUCCESS, heldItem)
|
return ActionResult(SUCCESS, heldItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType {
|
||||||
val player = context.player ?: return FAIL
|
|
||||||
val world = context.world
|
|
||||||
|
|
||||||
if (!player.isCreative || player.isSneaking) {
|
if (!player.isCreative || player.isSneaking) {
|
||||||
return PASS
|
return PASS
|
||||||
}
|
}
|
||||||
@@ -190,16 +190,14 @@ class ItemPortalToken(properties: Properties) : Item(properties) {
|
|||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetPos = context.pos.up()
|
val targetPos = pos.up()
|
||||||
|
val territoryType = getTerritoryType(item)
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
if (territoryType == null || ctx.face != UP || !BlockEditor.canEdit(targetPos, player, item) || world.selectExistingEntities.inBox<EntityTokenHolder>(AxisAlignedBB(targetPos)).any()) {
|
||||||
val territoryType = getTerritoryType(heldItem)
|
|
||||||
|
|
||||||
if (territoryType == null || context.face != UP || !BlockEditor.canEdit(targetPos, player, heldItem) || world.selectExistingEntities.inBox<EntityTokenHolder>(AxisAlignedBB(targetPos)).any()) {
|
|
||||||
return FAIL
|
return FAIL
|
||||||
}
|
}
|
||||||
|
|
||||||
world.addEntity(EntityTokenHolder(world, targetPos, getTokenType(heldItem), territoryType))
|
world.addEntity(EntityTokenHolder(world, targetPos, getTokenType(item), territoryType))
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package chylex.hee.game.item
|
package chylex.hee.game.item
|
||||||
|
|
||||||
import chylex.hee.game.block.entity.TileEntityMinersBurialAltar
|
import chylex.hee.game.block.entity.TileEntityMinersBurialAltar
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.world.BlockEditor
|
import chylex.hee.game.world.BlockEditor
|
||||||
import chylex.hee.game.world.getTile
|
import chylex.hee.game.world.getTile
|
||||||
import chylex.hee.game.world.playUniversal
|
import chylex.hee.game.world.playUniversal
|
||||||
@@ -8,33 +9,34 @@ import chylex.hee.init.ModSounds
|
|||||||
import chylex.hee.system.migration.ActionResult.FAIL
|
import chylex.hee.system.migration.ActionResult.FAIL
|
||||||
import chylex.hee.system.migration.ActionResult.PASS
|
import chylex.hee.system.migration.ActionResult.PASS
|
||||||
import chylex.hee.system.migration.ActionResult.SUCCESS
|
import chylex.hee.system.migration.ActionResult.SUCCESS
|
||||||
import net.minecraft.item.Item
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.util.ActionResultType
|
import net.minecraft.util.ActionResultType
|
||||||
import net.minecraft.util.SoundCategory
|
import net.minecraft.util.SoundCategory
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
class ItemPuzzleMedallion(properties: Properties) : Item(properties) {
|
class ItemPuzzleMedallion(properties: Properties) : ItemWithComponents(properties) {
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
init {
|
||||||
val player = context.player ?: return FAIL
|
components.attach(object : UseOnBlockComponent {
|
||||||
val world = context.world
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType {
|
||||||
val pos = context.pos
|
if (!BlockEditor.canEdit(pos, player, item)) {
|
||||||
|
return FAIL
|
||||||
|
}
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
val tile = pos.getTile<TileEntityMinersBurialAltar>(world)
|
||||||
|
|
||||||
if (!BlockEditor.canEdit(pos, player, heldItem)) {
|
if (tile != null && !tile.hasMedallion) {
|
||||||
return FAIL
|
tile.hasMedallion = true
|
||||||
}
|
item.shrink(1)
|
||||||
|
|
||||||
val tile = pos.getTile<TileEntityMinersBurialAltar>(world)
|
ModSounds.ITEM_PUZZLE_MEDALLION_INSERT.playUniversal(player, pos, SoundCategory.BLOCKS, volume = 2F, pitch = 0.8F)
|
||||||
|
return SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
if (tile != null && !tile.hasMedallion) {
|
return PASS
|
||||||
tile.hasMedallion = true
|
}
|
||||||
heldItem.shrink(1)
|
})
|
||||||
|
|
||||||
ModSounds.ITEM_PUZZLE_MEDALLION_INSERT.playUniversal(player, pos, SoundCategory.BLOCKS, volume = 2F, pitch = 0.8F)
|
|
||||||
return SUCCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
return PASS
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package chylex.hee.game.item
|
|||||||
import chylex.hee.client.model.ModelHelper
|
import chylex.hee.client.model.ModelHelper
|
||||||
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
||||||
import chylex.hee.game.entity.item.EntityItemRevitalizationSubstance
|
import chylex.hee.game.entity.item.EntityItemRevitalizationSubstance
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.mechanics.energy.IClusterHealth.HealthOverride.REVITALIZING
|
import chylex.hee.game.mechanics.energy.IClusterHealth.HealthOverride.REVITALIZING
|
||||||
import chylex.hee.game.particle.ParticleSmokeCustom
|
import chylex.hee.game.particle.ParticleSmokeCustom
|
||||||
import chylex.hee.game.particle.spawner.ParticleSpawnerCustom
|
import chylex.hee.game.particle.spawner.ParticleSpawnerCustom
|
||||||
@@ -26,7 +27,6 @@ import chylex.hee.system.serialization.readPos
|
|||||||
import chylex.hee.system.serialization.use
|
import chylex.hee.system.serialization.use
|
||||||
import chylex.hee.system.serialization.writePos
|
import chylex.hee.system.serialization.writePos
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.network.PacketBuffer
|
import net.minecraft.network.PacketBuffer
|
||||||
@@ -37,7 +37,7 @@ import net.minecraft.util.math.BlockPos
|
|||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
class ItemRevitalizationSubstance(properties: Properties) : Item(properties) {
|
class ItemRevitalizationSubstance(properties: Properties) : ItemWithComponents(properties), UseOnBlockComponent {
|
||||||
companion object {
|
companion object {
|
||||||
private val PARTICLE_FAIL = ParticleSpawnerCustom(
|
private val PARTICLE_FAIL = ParticleSpawnerCustom(
|
||||||
type = ParticleSmokeCustom,
|
type = ParticleSmokeCustom,
|
||||||
@@ -70,11 +70,11 @@ class ItemRevitalizationSubstance(properties: Properties) : Item(properties) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
init {
|
||||||
val player = context.player ?: return FAIL
|
components.attach(this)
|
||||||
val world = context.world
|
}
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType? {
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
return FAIL // disable animation
|
return FAIL // disable animation
|
||||||
}
|
}
|
||||||
@@ -83,11 +83,11 @@ class ItemRevitalizationSubstance(properties: Properties) : Item(properties) {
|
|||||||
|
|
||||||
if (cluster.currentHealth != REVITALIZING) {
|
if (cluster.currentHealth != REVITALIZING) {
|
||||||
if (cluster.addRevitalizationSubstance()) {
|
if (cluster.addRevitalizationSubstance()) {
|
||||||
player.getHeldItem(context.hand).shrink(1)
|
player.getHeldItem(ctx.hand).shrink(1)
|
||||||
ModSounds.ITEM_REVITALIZATION_SUBSTANCE_USE_SUCCESS.playServer(world, pos, SoundCategory.BLOCKS, volume = 0.5F)
|
ModSounds.ITEM_REVITALIZATION_SUBSTANCE_USE_SUCCESS.playServer(world, pos, SoundCategory.BLOCKS, volume = 0.5F)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PacketClientFX(FX_FAIL, FxUseData(pos, player, context.hand)).sendToAllAround(player, 24.0)
|
PacketClientFX(FX_FAIL, FxUseData(pos, player, ctx.hand)).sendToAllAround(player, 24.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,33 +2,33 @@ package chylex.hee.game.item
|
|||||||
|
|
||||||
import chylex.hee.game.block.BlockAbstractTableTile
|
import chylex.hee.game.block.BlockAbstractTableTile
|
||||||
import chylex.hee.game.block.BlockTableBase
|
import chylex.hee.game.block.BlockTableBase
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.world.BlockEditor
|
import chylex.hee.game.world.BlockEditor
|
||||||
import chylex.hee.game.world.breakBlock
|
import chylex.hee.game.world.breakBlock
|
||||||
import chylex.hee.game.world.getBlock
|
import chylex.hee.game.world.getBlock
|
||||||
import chylex.hee.game.world.setBlock
|
import chylex.hee.game.world.setBlock
|
||||||
import chylex.hee.system.forge.Side
|
import chylex.hee.system.forge.Side
|
||||||
import chylex.hee.system.forge.Sided
|
import chylex.hee.system.forge.Sided
|
||||||
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
import net.minecraft.client.util.ITooltipFlag
|
import net.minecraft.client.util.ITooltipFlag
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.util.ActionResultType
|
import net.minecraft.util.ActionResultType
|
||||||
import net.minecraft.util.ActionResultType.FAIL
|
import net.minecraft.util.ActionResultType.FAIL
|
||||||
import net.minecraft.util.ActionResultType.PASS
|
import net.minecraft.util.ActionResultType.PASS
|
||||||
import net.minecraft.util.ActionResultType.SUCCESS
|
import net.minecraft.util.ActionResultType.SUCCESS
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.text.ITextComponent
|
import net.minecraft.util.text.ITextComponent
|
||||||
import net.minecraft.util.text.TranslationTextComponent
|
import net.minecraft.util.text.TranslationTextComponent
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
|
|
||||||
class ItemTableCore(private val tableBlocks: Array<BlockAbstractTableTile<*>>, properties: Properties) : Item(properties) {
|
class ItemTableCore(private val tableBlocks: Array<BlockAbstractTableTile<*>>, properties: Properties) : ItemWithComponents(properties), UseOnBlockComponent {
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
init {
|
||||||
val player = context.player ?: return FAIL
|
components.attach(this)
|
||||||
val world = context.world
|
}
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType {
|
||||||
|
if (!BlockEditor.canEdit(pos, player, item)) {
|
||||||
if (!BlockEditor.canEdit(pos, player, heldItem)) {
|
|
||||||
return FAIL
|
return FAIL
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ class ItemTableCore(private val tableBlocks: Array<BlockAbstractTableTile<*>>, p
|
|||||||
pos.setBlock(world, table)
|
pos.setBlock(world, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
heldItem.shrink(1)
|
item.shrink(1)
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import chylex.hee.game.item.ItemTableLink.Companion.SoundType.LINK_FAIL
|
|||||||
import chylex.hee.game.item.ItemTableLink.Companion.SoundType.LINK_OUTPUT
|
import chylex.hee.game.item.ItemTableLink.Companion.SoundType.LINK_OUTPUT
|
||||||
import chylex.hee.game.item.ItemTableLink.Companion.SoundType.LINK_RESTART
|
import chylex.hee.game.item.ItemTableLink.Companion.SoundType.LINK_RESTART
|
||||||
import chylex.hee.game.item.ItemTableLink.Companion.SoundType.LINK_SUCCESS
|
import chylex.hee.game.item.ItemTableLink.Companion.SoundType.LINK_SUCCESS
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
import chylex.hee.game.world.getBlock
|
import chylex.hee.game.world.getBlock
|
||||||
import chylex.hee.game.world.getTile
|
import chylex.hee.game.world.getTile
|
||||||
import chylex.hee.game.world.playClient
|
import chylex.hee.game.world.playClient
|
||||||
@@ -26,6 +27,7 @@ import chylex.hee.system.forge.Sided
|
|||||||
import chylex.hee.system.migration.ActionResult.FAIL
|
import chylex.hee.system.migration.ActionResult.FAIL
|
||||||
import chylex.hee.system.migration.ActionResult.SUCCESS
|
import chylex.hee.system.migration.ActionResult.SUCCESS
|
||||||
import chylex.hee.system.migration.EntityItem
|
import chylex.hee.system.migration.EntityItem
|
||||||
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
import chylex.hee.system.random.nextFloat
|
import chylex.hee.system.random.nextFloat
|
||||||
import chylex.hee.system.serialization.getPos
|
import chylex.hee.system.serialization.getPos
|
||||||
import chylex.hee.system.serialization.hasKey
|
import chylex.hee.system.serialization.hasKey
|
||||||
@@ -34,7 +36,6 @@ import chylex.hee.system.serialization.readPos
|
|||||||
import chylex.hee.system.serialization.use
|
import chylex.hee.system.serialization.use
|
||||||
import chylex.hee.system.serialization.writePos
|
import chylex.hee.system.serialization.writePos
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.ItemUseContext
|
import net.minecraft.item.ItemUseContext
|
||||||
import net.minecraft.network.PacketBuffer
|
import net.minecraft.network.PacketBuffer
|
||||||
@@ -44,7 +45,7 @@ import net.minecraft.util.math.BlockPos
|
|||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
class ItemTableLink(properties: Properties) : Item(properties) {
|
class ItemTableLink(properties: Properties) : ItemWithComponents(properties), UseOnBlockComponent {
|
||||||
companion object {
|
companion object {
|
||||||
private const val POS_TAG = "StoredPos"
|
private const val POS_TAG = "StoredPos"
|
||||||
private const val TIME_TAG = "StoredTime"
|
private const val TIME_TAG = "StoredTime"
|
||||||
@@ -106,11 +107,11 @@ class ItemTableLink(properties: Properties) : Item(properties) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemUse(context: ItemUseContext): ActionResultType {
|
init {
|
||||||
val player = context.player ?: return FAIL
|
components.attach(this)
|
||||||
val world = context.world
|
}
|
||||||
val pos = context.pos
|
|
||||||
|
|
||||||
|
override fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType? {
|
||||||
if (!player.isSneaking || !isValidTarget(world, pos)) {
|
if (!player.isSneaking || !isValidTarget(world, pos)) {
|
||||||
val pedestal = pos.getTile<TileEntityTablePedestal>(world)
|
val pedestal = pos.getTile<TileEntityTablePedestal>(world)
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ class ItemTableLink(properties: Properties) : Item(properties) {
|
|||||||
return SUCCESS
|
return SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
val heldItem = player.getHeldItem(context.hand)
|
val heldItem = player.getHeldItem(ctx.hand)
|
||||||
var newStoredPos = pos
|
var newStoredPos = pos
|
||||||
var soundType = LINK_RESTART
|
var soundType = LINK_RESTART
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import chylex.hee.game.world.structure.trigger.EntityStructureTrigger
|
|||||||
import chylex.hee.game.world.territory.TerritoryType
|
import chylex.hee.game.world.territory.TerritoryType
|
||||||
import chylex.hee.init.ModBlocks
|
import chylex.hee.init.ModBlocks
|
||||||
import chylex.hee.network.client.PacketClientFX
|
import chylex.hee.network.client.PacketClientFX
|
||||||
|
import chylex.hee.network.fx.FxVecData
|
||||||
import chylex.hee.system.facades.Facing4
|
import chylex.hee.system.facades.Facing4
|
||||||
import chylex.hee.system.math.addY
|
import chylex.hee.system.math.addY
|
||||||
import chylex.hee.system.math.offsetTowards
|
import chylex.hee.system.math.offsetTowards
|
||||||
@@ -145,9 +146,8 @@ abstract class ObsidianTowerLevel_Top(file: String) : ObsidianTowerLevel_General
|
|||||||
|
|
||||||
val offsetProgress = chargeAnim.pow(0.8F).toDouble()
|
val offsetProgress = chargeAnim.pow(0.8F).toDouble()
|
||||||
val particlePos = start.center.offsetTowards(tokenHolder.posVec.addY(tokenHolder.height * 0.5), offsetProgress).addY(progressCurvePoint * 6.0)
|
val particlePos = start.center.offsetTowards(tokenHolder.posVec.addY(tokenHolder.height * 0.5), offsetProgress).addY(progressCurvePoint * 6.0)
|
||||||
val particleData = EnderEyeSpawnerParticles.Companion.ParticleData(particlePos)
|
|
||||||
|
|
||||||
PacketClientFX(EnderEyeSpawnerParticles.FX_PARTICLE, particleData).sendToAllAround(entity.world, pos, 256.0)
|
PacketClientFX(EnderEyeSpawnerParticles.FX_PARTICLE, FxVecData(particlePos)).sendToAllAround(entity.world, pos, 256.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chargeAnim == 1F) {
|
if (chargeAnim == 1F) {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package chylex.hee.game.world.feature.tombdungeon
|
package chylex.hee.game.world.feature.tombdungeon
|
||||||
|
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount.HIGH
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount.MEDIUM
|
||||||
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces.PIECE_TOMB_RANDOM_MASS_5X_BASIC
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces.PIECE_TOMB_RANDOM_MASS_5X_BASIC
|
||||||
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces.PIECE_TOMB_RANDOM_MASS_5X_BORDER
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces.PIECE_TOMB_RANDOM_MASS_5X_BORDER
|
||||||
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces.PIECE_TOMB_RANDOM_MASS_5X_SPLIT
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces.PIECE_TOMB_RANDOM_MASS_5X_SPLIT
|
||||||
@@ -19,6 +21,7 @@ import chylex.hee.game.world.feature.tombdungeon.piece.TombDungeonAbstractPiece
|
|||||||
import chylex.hee.system.math.floorToInt
|
import chylex.hee.system.math.floorToInt
|
||||||
import chylex.hee.system.random.nextFloat
|
import chylex.hee.system.random.nextFloat
|
||||||
import chylex.hee.system.random.nextInt
|
import chylex.hee.system.random.nextInt
|
||||||
|
import chylex.hee.system.random.nextRounded
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -101,4 +104,46 @@ enum class TombDungeonLevel(val isFancy: Boolean, private val corridorFactor: In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun pickUndreadAndSpiderlingSpawns(rand: Random, amount: MobAmount): Pair<Int, Int> {
|
||||||
|
val m = if (amount >= MEDIUM) 1 else 0
|
||||||
|
val h = if (amount >= HIGH) 1 else 0
|
||||||
|
|
||||||
|
return when(this) {
|
||||||
|
FIRST -> when(rand.nextInt(0, 3)) {
|
||||||
|
0 -> MOBS(undreads = rand.nextRounded(0.2F), spiderlings = 1 + m + rand.nextInt(0, h))
|
||||||
|
1 -> MOBS(undreads = rand.nextRounded(0.3F * m), spiderlings = 1 + h + rand.nextInt(0, m))
|
||||||
|
2 -> MOBS(undreads = rand.nextRounded(0.3F * h), spiderlings = 2 + m)
|
||||||
|
else -> MOBS(undreads = 0, spiderlings = 1 + rand.nextInt(0, 1 + m))
|
||||||
|
}
|
||||||
|
|
||||||
|
SECOND -> when(rand.nextInt(0, 3)) {
|
||||||
|
0 -> MOBS(undreads = rand.nextRounded(0.3F), spiderlings = 1 + m + rand.nextInt(0, h))
|
||||||
|
1 -> MOBS(undreads = rand.nextRounded(0.4F * m), spiderlings = 1 + rand.nextInt(0, 2 * m))
|
||||||
|
else -> MOBS(undreads = 0, spiderlings = rand.nextRounded(1.8F + (m * 0.55F) + (h * 0.55F)))
|
||||||
|
}
|
||||||
|
|
||||||
|
THIRD -> when(rand.nextInt(0, 2)) {
|
||||||
|
0 -> MOBS(undreads = rand.nextInt(0, 1 + h), spiderlings = rand.nextRounded(1.4F + (m * 0.5F)) + rand.nextInt(0, m))
|
||||||
|
1 -> MOBS(undreads = rand.nextInt(0, 1 + m), spiderlings = rand.nextRounded(1.2F) + rand.nextInt(0, 2 * h))
|
||||||
|
else -> MOBS(undreads = rand.nextInt(0, 1 + m), spiderlings = 2 + rand.nextInt(0, m + h))
|
||||||
|
}
|
||||||
|
|
||||||
|
FOURTH -> when(rand.nextInt(0, 5)) {
|
||||||
|
in 0..1 -> MOBS(undreads = 1 + rand.nextInt(h, 3 + h), spiderlings = rand.nextRounded(0.4F * m) + rand.nextInt(0, m + h))
|
||||||
|
else -> MOBS(undreads = 2 + rand.nextInt(m, 2 * m), spiderlings = rand.nextRounded(0.3F + (m * 0.1F) + (h * 0.3F)))
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> when(rand.nextInt(0, 2)) {
|
||||||
|
0 -> MOBS(undreads = 1 + h + rand.nextInt(m, 1 + (m * 2)) + rand.nextInt(h, 1 + h), spiderlings = rand.nextInt(0, m))
|
||||||
|
else -> MOBS(undreads = 2 + h + rand.nextInt(m, 2 * m), spiderlings = rand.nextRounded(0.2F + (m * 0.2F)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MOBS(undreads: Int, spiderlings: Int) = undreads to spiderlings
|
||||||
|
|
||||||
|
enum class MobAmount {
|
||||||
|
LOW, MEDIUM, HIGH
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,57 @@
|
|||||||
package chylex.hee.game.world.feature.tombdungeon.piece
|
package chylex.hee.game.world.feature.tombdungeon.piece
|
||||||
|
|
||||||
|
import chylex.hee.game.block.BlockGraveDirt
|
||||||
|
import chylex.hee.game.entity.living.EntityMobSpiderling
|
||||||
|
import chylex.hee.game.entity.living.EntityMobUndread
|
||||||
|
import chylex.hee.game.entity.posVec
|
||||||
|
import chylex.hee.game.entity.selectExistingEntities
|
||||||
|
import chylex.hee.game.entity.selectVulnerableEntities
|
||||||
|
import chylex.hee.game.entity.technical.EntityTechnicalTrigger
|
||||||
|
import chylex.hee.game.entity.technical.EntityTechnicalTrigger.ITriggerHandler
|
||||||
|
import chylex.hee.game.entity.technical.EntityTechnicalTrigger.Types.TOMB_DUNGEON_UNDREAD_SPAWNER
|
||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
|
import chylex.hee.game.world.distanceSqTo
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnection
|
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnection
|
||||||
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnectionType.TOMB_ENTRANCE_INSIDE
|
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnectionType.TOMB_ENTRANCE_INSIDE
|
||||||
|
import chylex.hee.game.world.getBlock
|
||||||
|
import chylex.hee.game.world.getState
|
||||||
|
import chylex.hee.game.world.isAir
|
||||||
|
import chylex.hee.game.world.offsetWhile
|
||||||
|
import chylex.hee.game.world.playClient
|
||||||
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
import chylex.hee.game.world.structure.piece.IStructurePieceConnection
|
import chylex.hee.game.world.structure.piece.IStructurePieceConnection
|
||||||
|
import chylex.hee.game.world.structure.trigger.EntityStructureTrigger
|
||||||
|
import chylex.hee.init.ModEntities
|
||||||
|
import chylex.hee.network.client.PacketClientFX
|
||||||
|
import chylex.hee.network.fx.FxVecData
|
||||||
|
import chylex.hee.network.fx.FxVecHandler
|
||||||
|
import chylex.hee.system.math.Vec
|
||||||
|
import chylex.hee.system.math.Vec3
|
||||||
|
import chylex.hee.system.math.addY
|
||||||
|
import chylex.hee.system.math.directionTowards
|
||||||
|
import chylex.hee.system.math.square
|
||||||
|
import chylex.hee.system.math.toYaw
|
||||||
|
import chylex.hee.system.migration.BlockWeb
|
||||||
|
import chylex.hee.system.migration.EntityLivingBase
|
||||||
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
|
import chylex.hee.system.migration.Facing.DOWN
|
||||||
|
import chylex.hee.system.migration.Facing.NORTH
|
||||||
import chylex.hee.system.migration.Facing.SOUTH
|
import chylex.hee.system.migration.Facing.SOUTH
|
||||||
|
import chylex.hee.system.random.nextFloat
|
||||||
|
import chylex.hee.system.random.nextInt
|
||||||
|
import chylex.hee.system.random.nextItem
|
||||||
|
import chylex.hee.system.serialization.TagCompound
|
||||||
|
import chylex.hee.system.serialization.use
|
||||||
|
import net.minecraft.entity.EntitySpawnPlacementRegistry
|
||||||
|
import net.minecraft.entity.SpawnReason.STRUCTURE
|
||||||
|
import net.minecraft.util.Direction.Axis
|
||||||
|
import net.minecraft.util.math.AxisAlignedBB
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.util.math.Vec3d
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
abstract class TombDungeonRoom_Tomb(file: String, entranceY: Int, allowSecrets: Boolean, isFancy: Boolean) : TombDungeonRoom(file, isFancy) {
|
abstract class TombDungeonRoom_Tomb(file: String, entranceY: Int, allowSecrets: Boolean, isFancy: Boolean) : TombDungeonRoom(file, isFancy) {
|
||||||
final override val secretAttachWeight = if (allowSecrets) 2 else 0
|
final override val secretAttachWeight = if (allowSecrets) 2 else 0
|
||||||
@@ -13,4 +60,176 @@ abstract class TombDungeonRoom_Tomb(file: String, entranceY: Int, allowSecrets:
|
|||||||
final override val connections = arrayOf<IStructurePieceConnection>(
|
final override val connections = arrayOf<IStructurePieceConnection>(
|
||||||
TombDungeonConnection(TOMB_ENTRANCE_INSIDE, Pos(centerX, entranceY, maxZ), SOUTH)
|
TombDungeonConnection(TOMB_ENTRANCE_INSIDE, Pos(centerX, entranceY, maxZ), SOUTH)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
|
super.generate(world, instance)
|
||||||
|
generateSpawnerTrigger(world, instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun generateSpawnerTrigger(world: IStructureWorld, instance: Instance) {
|
||||||
|
val rand = world.rand
|
||||||
|
val level = instance.context ?: return
|
||||||
|
val mobAmount = getSpawnerTriggerMobAmount(rand, level) ?: return
|
||||||
|
|
||||||
|
val (undreads, spiderlings) = level.pickUndreadAndSpiderlingSpawns(rand, mobAmount)
|
||||||
|
MobSpawnerTrigger.place(world, entrance = connections.first().offset, width = maxX, depth = maxZ, undreads, spiderlings)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun getSpawnerTriggerMobAmount(rand: Random, level: TombDungeonLevel): MobAmount?
|
||||||
|
|
||||||
|
class MobSpawnerTrigger() : ITriggerHandler {
|
||||||
|
companion object {
|
||||||
|
private const val WIDTH_TAG = "Width"
|
||||||
|
private const val DEPTH_TAG = "Depth"
|
||||||
|
private const val UNDREADS_TAG = "Undreads"
|
||||||
|
private const val SPIDERLINGS_TAG = "Spiderlings"
|
||||||
|
|
||||||
|
fun place(world: IStructureWorld, entrance: BlockPos, width: Int, depth: Int, undreads: Int, spiderlings: Int) {
|
||||||
|
val nbt = MobSpawnerTrigger(width - 1.0, depth - 1.0, undreads, spiderlings).serializeNBT()
|
||||||
|
|
||||||
|
world.addTrigger(entrance, EntityStructureTrigger({ wrld ->
|
||||||
|
EntityTechnicalTrigger(wrld, TOMB_DUNGEON_UNDREAD_SPAWNER, nbt).apply { rotationYaw = NORTH.horizontalAngle }
|
||||||
|
}, yOffset = 0.5))
|
||||||
|
}
|
||||||
|
|
||||||
|
val FX_SPAWN_UNDREAD = object : FxVecHandler() {
|
||||||
|
override fun handle(world: World, rand: Random, vec: Vec3d) {
|
||||||
|
EntityMobUndread(world).apply {
|
||||||
|
setLocationAndAngles(vec.x, vec.y, vec.z, 0F, 0F)
|
||||||
|
spawnExplosionParticle()
|
||||||
|
deathSound.playClient(vec, soundCategory, volume = 1.2F, pitch = soundPitch * 0.7F)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val FX_SPAWN_SPIDERLING = object : FxVecHandler() {
|
||||||
|
override fun handle(world: World, rand: Random, vec: Vec3d) {
|
||||||
|
EntityMobSpiderling(world).apply {
|
||||||
|
setLocationAndAngles(vec.x, vec.y, vec.z, 0F, 0F)
|
||||||
|
spawnExplosionParticle()
|
||||||
|
ambientSound.playClient(vec, soundCategory, volume = 1F, pitch = soundPitch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var width = 0.0
|
||||||
|
private var depth = 0.0
|
||||||
|
private var undreads = 0
|
||||||
|
private var spiderlings = 0
|
||||||
|
|
||||||
|
constructor(width: Double, depth: Double, undreads: Int, spiderlings: Int) : this() {
|
||||||
|
this.width = width
|
||||||
|
this.depth = depth
|
||||||
|
this.undreads = undreads
|
||||||
|
this.spiderlings = spiderlings
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun check(world: World): Boolean {
|
||||||
|
return !world.isRemote
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(entity: EntityTechnicalTrigger) {
|
||||||
|
val world = entity.world
|
||||||
|
val facing = entity.horizontalFacing
|
||||||
|
val vecF = Vec3.fromYaw(facing.horizontalAngle)
|
||||||
|
val vecL = Vec3.fromYaw(facing.rotateYCCW().horizontalAngle)
|
||||||
|
val vecR = Vec3.fromYaw(facing.rotateY().horizontalAngle)
|
||||||
|
|
||||||
|
val aabb = AxisAlignedBB(
|
||||||
|
vecL.scale(width * 0.5).add(vecF.scale(0.3)),
|
||||||
|
vecR.scale(width * 0.5).add(vecF.scale(depth)).addY(2.5)
|
||||||
|
).offset(entity.posVec)
|
||||||
|
|
||||||
|
val nearbyPlayers = world.selectVulnerableEntities.inBox<EntityPlayer>(aabb)
|
||||||
|
if (nearbyPlayers.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val rand = world.rand
|
||||||
|
val minPlayerDist = ((depth * 0.4) + (width * 0.16)).coerceIn(1.5, 3.5)
|
||||||
|
|
||||||
|
for((entityCount, entityType, spawnParticle) in listOf(
|
||||||
|
Triple(undreads, ModEntities.UNDREAD, FX_SPAWN_UNDREAD),
|
||||||
|
Triple(spiderlings, ModEntities.SPIDERLING, FX_SPAWN_SPIDERLING)
|
||||||
|
)) {
|
||||||
|
repeat(entityCount) {
|
||||||
|
var bestPos: BlockPos? = null
|
||||||
|
|
||||||
|
for(attempt in 1..75) {
|
||||||
|
val pos = Pos(
|
||||||
|
rand.nextFloat(aabb.minX, aabb.maxX),
|
||||||
|
rand.nextFloat(aabb.minY, aabb.maxY) + 0.5,
|
||||||
|
rand.nextFloat(aabb.minZ, aabb.maxZ),
|
||||||
|
).offsetWhile(DOWN, 1..3) {
|
||||||
|
it.isAir(world) || it.getBlock(world) is BlockWeb
|
||||||
|
}
|
||||||
|
|
||||||
|
val collisionCheckAABB = entityType.getBoundingBoxWithSizeApplied(pos.x + 0.5, pos.y.toDouble(), pos.z + 0.5).grow(0.2, 0.0, 0.2)
|
||||||
|
|
||||||
|
if (EntitySpawnPlacementRegistry.func_223515_a(entityType, world, STRUCTURE, pos, rand) &&
|
||||||
|
world.hasNoCollisions(collisionCheckAABB) &&
|
||||||
|
world.selectExistingEntities.inBox<EntityLivingBase>(collisionCheckAABB.grow(0.4, 0.0, 0.4)).isEmpty() &&
|
||||||
|
world.players.none { pos.distanceSqTo(it) < square(minPlayerDist) }
|
||||||
|
) {
|
||||||
|
bestPos = pos
|
||||||
|
|
||||||
|
if (entityType === ModEntities.UNDREAD) {
|
||||||
|
if (rand.nextInt(5) == 0 || pos.down().getBlock(world) is BlockGraveDirt) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestPos != null) {
|
||||||
|
val x = bestPos.x + rand.nextFloat(0.35, 0.65)
|
||||||
|
val y = bestPos.y + bestPos.down().getState(world).getCollisionShape(world, bestPos).getEnd(Axis.Y) - 1.0
|
||||||
|
val z = bestPos.z + rand.nextFloat(0.35, 0.65)
|
||||||
|
val vec = Vec(x, y, z)
|
||||||
|
val target = rand.nextItem(nearbyPlayers)
|
||||||
|
|
||||||
|
entityType.create(world)?.apply {
|
||||||
|
setLocationAndAngles(x, y, z, vec.directionTowards(target.posVec).toYaw(), 0F)
|
||||||
|
rotationYawHead = rotationYaw
|
||||||
|
attackTarget = target
|
||||||
|
onGround = true // allow instant pathfinding in MeleeAttackGoal
|
||||||
|
|
||||||
|
if (this is EntityMobSpiderling) {
|
||||||
|
wakeUp(preventSleep = true, aiDelayTicks = if (rand.nextInt(10) == 0) rand.nextInt(4, 6) else rand.nextInt(11, 18))
|
||||||
|
}
|
||||||
|
|
||||||
|
onInitialSpawn(world, world.getDifficultyForLocation(bestPos), STRUCTURE, null, null)
|
||||||
|
world.addEntity(this)
|
||||||
|
|
||||||
|
PacketClientFX(spawnParticle, FxVecData(vec)).sendToAllAround(this, 24.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun nextTimer(rand: Random): Int {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serializeNBT() = TagCompound().apply {
|
||||||
|
putDouble(WIDTH_TAG, width)
|
||||||
|
putDouble(DEPTH_TAG, depth)
|
||||||
|
putInt(UNDREADS_TAG, undreads)
|
||||||
|
putInt(SPIDERLINGS_TAG, spiderlings)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserializeNBT(nbt: TagCompound) = nbt.use {
|
||||||
|
width = getDouble(WIDTH_TAG)
|
||||||
|
depth = getDouble(DEPTH_TAG)
|
||||||
|
undreads = getInt(UNDREADS_TAG)
|
||||||
|
spiderlings = getInt(SPIDERLINGS_TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package chylex.hee.game.world.feature.tombdungeon.piece
|
|||||||
|
|
||||||
import chylex.hee.game.block.BlockGraveDirt
|
import chylex.hee.game.block.BlockGraveDirt
|
||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonPieces
|
||||||
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnection
|
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnection
|
||||||
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnectionType.TOMB_ENTRANCE_INSIDE
|
import chylex.hee.game.world.feature.tombdungeon.connection.TombDungeonConnectionType.TOMB_ENTRANCE_INSIDE
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.piece.TombDungeonRoom_Tomb.MobSpawnerTrigger
|
||||||
import chylex.hee.game.world.generation.IBlockPicker.Single
|
import chylex.hee.game.world.generation.IBlockPicker.Single
|
||||||
import chylex.hee.game.world.generation.IBlockPicker.Single.Air
|
import chylex.hee.game.world.generation.IBlockPicker.Single.Air
|
||||||
import chylex.hee.game.world.math.Size
|
import chylex.hee.game.world.math.Size
|
||||||
@@ -32,6 +35,8 @@ class TombDungeonRoom_Tomb_Mass(width: Int, depth: Int, private val border: Bool
|
|||||||
super.generate(world, instance)
|
super.generate(world, instance)
|
||||||
|
|
||||||
val rand = world.rand
|
val rand = world.rand
|
||||||
|
val level = instance.context
|
||||||
|
|
||||||
val centerX = size.centerX
|
val centerX = size.centerX
|
||||||
val maxX = size.maxX
|
val maxX = size.maxX
|
||||||
val maxY = size.maxY
|
val maxY = size.maxY
|
||||||
@@ -56,8 +61,21 @@ class TombDungeonRoom_Tomb_Mass(width: Int, depth: Int, private val border: Bool
|
|||||||
|
|
||||||
if (rand.nextInt(6) == 0 && (border || split)) {
|
if (rand.nextInt(6) == 0 && (border || split)) {
|
||||||
placeJars(world, instance, listOf(Pos(centerX, 2, 1)))
|
placeJars(world, instance, listOf(Pos(centerX, 2, 1)))
|
||||||
|
|
||||||
|
if (level != null && rand.nextInt(9) != 0) {
|
||||||
|
placeSpawnerTrigger(world, level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (level != null && rand.nextInt(3) != 0) {
|
||||||
|
placeSpawnerTrigger(world, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
placeCobwebs(world, instance)
|
placeCobwebs(world, instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun placeSpawnerTrigger(world: IStructureWorld, level: TombDungeonLevel) {
|
||||||
|
val area = (size.x - 2) * (size.z - 2)
|
||||||
|
val (undreads, spiderlings) = level.pickUndreadAndSpiderlingSpawns(world.rand, if (area <= 30) MobAmount.LOW else MobAmount.MEDIUM)
|
||||||
|
MobSpawnerTrigger.place(world, entrance = connections.first().offset, width = size.maxX, depth = size.maxZ, undreads, spiderlings)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package chylex.hee.game.world.feature.tombdungeon.piece
|
|||||||
|
|
||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
import chylex.hee.game.world.structure.IStructureWorld
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
import chylex.hee.system.migration.Facing.NORTH
|
import chylex.hee.system.migration.Facing.NORTH
|
||||||
import chylex.hee.system.random.nextInt
|
import chylex.hee.system.random.nextInt
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
class TombDungeonRoom_Tomb_MassSpacious(file: String, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
class TombDungeonRoom_Tomb_MassSpacious(file: String, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
||||||
override fun generate(world: IStructureWorld, instance: Instance) {
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
@@ -32,4 +34,8 @@ class TombDungeonRoom_Tomb_MassSpacious(file: String, entranceY: Int, isFancy: B
|
|||||||
placeJars(world, instance, listOf(Pos(jarX, 3, maxZ - 2)))
|
placeJars(world, instance, listOf(Pos(jarX, 3, maxZ - 2)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSpawnerTriggerMobAmount(rand: Random, level: TombDungeonLevel): MobAmount? {
|
||||||
|
return MobAmount.HIGH.takeIf { rand.nextInt(11) < (if (level <= TombDungeonLevel.SECOND) 7 else 4) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ package chylex.hee.game.world.feature.tombdungeon.piece
|
|||||||
|
|
||||||
import chylex.hee.game.block.BlockGraveDirt
|
import chylex.hee.game.block.BlockGraveDirt
|
||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
import chylex.hee.game.world.structure.IStructureWorld
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
import chylex.hee.system.migration.Facing.EAST
|
import chylex.hee.system.migration.Facing.EAST
|
||||||
import chylex.hee.system.migration.Facing.WEST
|
import chylex.hee.system.migration.Facing.WEST
|
||||||
import chylex.hee.system.random.nextInt
|
import chylex.hee.system.random.nextInt
|
||||||
import chylex.hee.system.random.nextRounded
|
import chylex.hee.system.random.nextRounded
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
class TombDungeonRoom_Tomb_MultiDeep(file: String, private val tombsPerColumn: Int, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
class TombDungeonRoom_Tomb_MultiDeep(file: String, private val tombsPerColumn: Int, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
||||||
override fun generate(world: IStructureWorld, instance: Instance) {
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
@@ -37,4 +40,15 @@ class TombDungeonRoom_Tomb_MultiDeep(file: String, private val tombsPerColumn: I
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSpawnerTriggerMobAmount(rand: Random, level: TombDungeonLevel): MobAmount? {
|
||||||
|
if (rand.nextBoolean()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
tombsPerColumn <= 6 -> MobAmount.MEDIUM
|
||||||
|
else -> MobAmount.HIGH
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package chylex.hee.game.world.feature.tombdungeon.piece
|
package chylex.hee.game.world.feature.tombdungeon.piece
|
||||||
|
|
||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
import chylex.hee.game.world.structure.IStructureWorld
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
class TombDungeonRoom_Tomb_MultiNarrow(file: String, private val tombsPerColumn: Int, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
class TombDungeonRoom_Tomb_MultiNarrow(file: String, private val tombsPerColumn: Int, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
||||||
override fun generate(world: IStructureWorld, instance: Instance) {
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
@@ -18,4 +21,16 @@ class TombDungeonRoom_Tomb_MultiNarrow(file: String, private val tombsPerColumn:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSpawnerTriggerMobAmount(rand: Random, level: TombDungeonLevel): MobAmount? {
|
||||||
|
if (rand.nextInt(10) >= if (level.isFancy) 3 else 5) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
tombsPerColumn <= 4 -> MobAmount.LOW
|
||||||
|
tombsPerColumn <= 6 -> MobAmount.MEDIUM
|
||||||
|
else -> MobAmount.HIGH
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ package chylex.hee.game.world.feature.tombdungeon.piece
|
|||||||
|
|
||||||
import chylex.hee.game.block.BlockGraveDirt
|
import chylex.hee.game.block.BlockGraveDirt
|
||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
import chylex.hee.game.world.structure.IStructureWorld
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
import chylex.hee.system.migration.Facing.EAST
|
import chylex.hee.system.migration.Facing.EAST
|
||||||
import chylex.hee.system.migration.Facing.WEST
|
import chylex.hee.system.migration.Facing.WEST
|
||||||
import chylex.hee.system.random.nextInt
|
import chylex.hee.system.random.nextInt
|
||||||
import chylex.hee.system.random.nextRounded
|
import chylex.hee.system.random.nextRounded
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
class TombDungeonRoom_Tomb_MultiSpacious(file: String, private val tombsPerColumn: Int, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
class TombDungeonRoom_Tomb_MultiSpacious(file: String, private val tombsPerColumn: Int, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
||||||
override fun generate(world: IStructureWorld, instance: Instance) {
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
@@ -37,4 +40,15 @@ class TombDungeonRoom_Tomb_MultiSpacious(file: String, private val tombsPerColum
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSpawnerTriggerMobAmount(rand: Random, level: TombDungeonLevel): MobAmount? {
|
||||||
|
if (rand.nextInt(10) >= 6) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
tombsPerColumn <= 6 -> MobAmount.MEDIUM
|
||||||
|
else -> MobAmount.HIGH
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package chylex.hee.game.world.feature.tombdungeon.piece
|
||||||
|
|
||||||
|
import chylex.hee.game.world.Pos
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
|
import chylex.hee.system.migration.Facing.SOUTH
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
abstract class TombDungeonRoom_Tomb_Single(file: String, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
||||||
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
|
super.generate(world, instance)
|
||||||
|
|
||||||
|
if (world.rand.nextInt(10) < 3) {
|
||||||
|
placeChest(world, instance, Pos(centerX, 1, maxZ - 4), SOUTH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun getSpawnerTriggerMobAmount(rand: Random, level: TombDungeonLevel): MobAmount? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun placeSingleTombUndreadSpawner(world: IStructureWorld) {
|
||||||
|
MobSpawnerTrigger.place(world, entrance = connections.first().offset, width = maxX, depth = maxZ, undreads = 1, spiderlings = 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
package chylex.hee.game.world.feature.tombdungeon.piece
|
package chylex.hee.game.world.feature.tombdungeon.piece
|
||||||
|
|
||||||
import chylex.hee.game.world.Pos
|
|
||||||
import chylex.hee.game.world.structure.IStructureWorld
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
import chylex.hee.system.migration.Facing.SOUTH
|
|
||||||
|
|
||||||
open class TombDungeonRoom_Tomb_SingleNarrow(file: String, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb(file, entranceY, allowSecrets = false, isFancy) {
|
class TombDungeonRoom_Tomb_SingleNarrow(file: String, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb_Single(file, entranceY, isFancy) {
|
||||||
override fun generate(world: IStructureWorld, instance: Instance) {
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
super.generate(world, instance)
|
super.generate(world, instance)
|
||||||
|
|
||||||
if (world.rand.nextInt(10) < 3) {
|
if (world.rand.nextInt(5) == 0) {
|
||||||
placeChest(world, instance, Pos(centerX, 1, maxZ - 4), SOUTH)
|
placeSingleTombUndreadSpawner(world)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package chylex.hee.game.world.feature.tombdungeon.piece
|
|||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
import chylex.hee.game.world.structure.IStructureWorld
|
import chylex.hee.game.world.structure.IStructureWorld
|
||||||
|
|
||||||
class TombDungeonRoom_Tomb_SingleSpacious(file: String, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb_SingleNarrow(file, entranceY, isFancy) {
|
class TombDungeonRoom_Tomb_SingleSpacious(file: String, entranceY: Int, isFancy: Boolean) : TombDungeonRoom_Tomb_Single(file, entranceY, isFancy) {
|
||||||
override fun generate(world: IStructureWorld, instance: Instance) {
|
override fun generate(world: IStructureWorld, instance: Instance) {
|
||||||
super.generate(world, instance)
|
super.generate(world, instance)
|
||||||
|
|
||||||
@@ -14,6 +14,11 @@ class TombDungeonRoom_Tomb_SingleSpacious(file: String, entranceY: Int, isFancy:
|
|||||||
Pos(centerX - 2, 4, if (rand.nextBoolean()) maxZ - 3 else maxZ - 4),
|
Pos(centerX - 2, 4, if (rand.nextBoolean()) maxZ - 3 else maxZ - 4),
|
||||||
Pos(centerX + 2, 4, if (rand.nextBoolean()) maxZ - 3 else maxZ - 4),
|
Pos(centerX + 2, 4, if (rand.nextBoolean()) maxZ - 3 else maxZ - 4),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
placeSingleTombUndreadSpawner(world)
|
||||||
|
}
|
||||||
|
else if (rand.nextInt(10) < 4) {
|
||||||
|
placeSingleTombUndreadSpawner(world)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import chylex.hee.game.item.ItemTableLink
|
|||||||
import chylex.hee.game.mechanics.scorching.ScorchingHelper
|
import chylex.hee.game.mechanics.scorching.ScorchingHelper
|
||||||
import chylex.hee.game.mechanics.table.TableParticleHandler
|
import chylex.hee.game.mechanics.table.TableParticleHandler
|
||||||
import chylex.hee.game.potion.PotionBanishment
|
import chylex.hee.game.potion.PotionBanishment
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.piece.TombDungeonRoom_Tomb
|
||||||
import chylex.hee.network.BaseClientPacket
|
import chylex.hee.network.BaseClientPacket
|
||||||
import chylex.hee.network.fx.IFxData
|
import chylex.hee.network.fx.IFxData
|
||||||
import chylex.hee.network.fx.IFxHandler
|
import chylex.hee.network.fx.IFxHandler
|
||||||
@@ -79,7 +80,9 @@ class PacketClientFX<T : IFxData>() : BaseClientPacket() {
|
|||||||
EnderEyeSpawnerParticles.FX_PARTICLE,
|
EnderEyeSpawnerParticles.FX_PARTICLE,
|
||||||
EndermanTeleportHandler.FX_TELEPORT_FAIL,
|
EndermanTeleportHandler.FX_TELEPORT_FAIL,
|
||||||
EndermanTeleportHandler.FX_TELEPORT_OUT_OF_WORLD,
|
EndermanTeleportHandler.FX_TELEPORT_OUT_OF_WORLD,
|
||||||
PotionBanishment.FX_BANISH
|
PotionBanishment.FX_BANISH,
|
||||||
|
TombDungeonRoom_Tomb.MobSpawnerTrigger.FX_SPAWN_UNDREAD,
|
||||||
|
TombDungeonRoom_Tomb.MobSpawnerTrigger.FX_SPAWN_SPIDERLING,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package chylex.hee.game.item
|
||||||
|
|
||||||
|
import chylex.hee.game.item.components.UseOnBlockComponent
|
||||||
|
import chylex.hee.system.component.EntityComponents
|
||||||
|
import net.minecraft.item.Item
|
||||||
|
import net.minecraft.item.ItemUseContext
|
||||||
|
import net.minecraft.util.ActionResultType
|
||||||
|
import net.minecraft.util.ActionResultType.FAIL
|
||||||
|
import net.minecraft.util.ActionResultType.PASS
|
||||||
|
|
||||||
|
open class ItemWithComponents(properties: Properties) : Item(properties) {
|
||||||
|
val components = EntityComponents()
|
||||||
|
|
||||||
|
final override fun onItemUse(context: ItemUseContext): ActionResultType {
|
||||||
|
val player = context.player ?: return FAIL
|
||||||
|
return components.handle<UseOnBlockComponent, ActionResultType> { useOnBlock(context.world, context.pos, player, context.item, context) } ?: PASS
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package chylex.hee.game.item.components
|
||||||
|
|
||||||
|
import chylex.hee.system.migration.EntityPlayer
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.item.ItemUseContext
|
||||||
|
import net.minecraft.util.ActionResultType
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
interface UseOnBlockComponent { // TODO use as objects instead of inheriting the interface on Item
|
||||||
|
fun useOnBlock(world: World, pos: BlockPos, player: EntityPlayer, item: ItemStack, ctx: ItemUseContext): ActionResultType?
|
||||||
|
}
|
||||||
@@ -10,24 +10,6 @@ class RandomBiasedValueRange(range: ClosedFloatingPointRange<Float>, private val
|
|||||||
require(highestChanceValue in min..max) { "highestChanceValue must be between min and max" }
|
require(highestChanceValue in min..max) { "highestChanceValue must be between min and max" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
import java.util.Random
|
|
||||||
import chylex.hee.system.random.nextBiasedFloat
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
val rand = Random()
|
|
||||||
|
|
||||||
(1..100000).map {
|
|
||||||
val min = 3F
|
|
||||||
val max = 10F
|
|
||||||
val highestChanceValue = 6.5F
|
|
||||||
val biasSoftener = 3F
|
|
||||||
(highestChanceValue + (rand.nextBiasedFloat(biasSoftener) * (0.5F + max - highestChanceValue)) - (rand.nextBiasedFloat(biasSoftener) * (0.5F + highestChanceValue - min))).roundToInt()
|
|
||||||
}.groupBy { it }.mapValues { it.value.size }.toList().sortedBy { it.first }
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
override fun generateInt(rand: Random): Int {
|
override fun generateInt(rand: Random): Int {
|
||||||
return (highestChanceValue + (rand.nextBiasedFloat(biasSoftener) * (0.5F + max - highestChanceValue)) - (rand.nextBiasedFloat(biasSoftener) * (0.5F + highestChanceValue - min))).roundToInt()
|
return (highestChanceValue + (rand.nextBiasedFloat(biasSoftener) * (0.5F + max - highestChanceValue)) - (rand.nextBiasedFloat(biasSoftener) * (0.5F + highestChanceValue - min))).roundToInt()
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/system/src/main/java/chylex/hee/network/fx/FxVecData.kt
Normal file
12
src/system/src/main/java/chylex/hee/network/fx/FxVecData.kt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package chylex.hee.network.fx
|
||||||
|
|
||||||
|
import chylex.hee.system.serialization.use
|
||||||
|
import chylex.hee.system.serialization.writeVec
|
||||||
|
import net.minecraft.network.PacketBuffer
|
||||||
|
import net.minecraft.util.math.Vec3d
|
||||||
|
|
||||||
|
class FxVecData(private val vec: Vec3d) : IFxData {
|
||||||
|
override fun write(buffer: PacketBuffer) = buffer.use {
|
||||||
|
writeVec(vec)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package chylex.hee.network.fx
|
||||||
|
|
||||||
|
import chylex.hee.system.serialization.readVec
|
||||||
|
import chylex.hee.system.serialization.use
|
||||||
|
import net.minecraft.network.PacketBuffer
|
||||||
|
import net.minecraft.util.math.Vec3d
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
abstract class FxVecHandler : IFxHandler<FxVecData> {
|
||||||
|
override fun handle(buffer: PacketBuffer, world: World, rand: Random) = buffer.use {
|
||||||
|
handle(world, rand, readVec())
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun handle(world: World, rand: Random, vec: Vec3d)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package chylex.hee.system.component
|
||||||
|
|
||||||
|
abstract class AbstractAwareComponent {
|
||||||
|
var entityComponents: EntityComponents? = null
|
||||||
|
|
||||||
|
open fun onComponentAttached() {}
|
||||||
|
open fun onComponentDetached() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package chylex.hee.system.component
|
||||||
|
|
||||||
|
class EntityComponents {
|
||||||
|
private val mutableComponents = mutableListOf<Any>()
|
||||||
|
|
||||||
|
val components: List<Any>
|
||||||
|
get() = mutableComponents
|
||||||
|
|
||||||
|
fun attach(component: Any) {
|
||||||
|
require(!mutableComponents.contains(component)) { "[EntityComponents] component must not be registered twice" }
|
||||||
|
mutableComponents.add(component)
|
||||||
|
|
||||||
|
if (component is AbstractAwareComponent) {
|
||||||
|
require(component.entityComponents === null) { "[EntityComponents] component must not be registered in two entities" }
|
||||||
|
component.entityComponents = this
|
||||||
|
component.onComponentAttached()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun detach(component: Any) {
|
||||||
|
if (!mutableComponents.remove(component)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component is AbstractAwareComponent) {
|
||||||
|
require(component.entityComponents === this) { "[EntityComponents] component was not registered correctly" }
|
||||||
|
component.onComponentDetached()
|
||||||
|
component.entityComponents = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> on(f: T.() -> Unit) {
|
||||||
|
for(component in components) {
|
||||||
|
if (component is T) {
|
||||||
|
f(component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T, U> handle(f: T.() -> U?): U? {
|
||||||
|
for(component in components) {
|
||||||
|
if (component is T) {
|
||||||
|
val result = f(component)
|
||||||
|
if (result != null) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> list(): List<T> {
|
||||||
|
return components.filterIsInstance<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package chylex.hee.system.component.general
|
||||||
|
|
||||||
|
import chylex.hee.system.component.EntityComponents
|
||||||
|
import chylex.hee.system.serialization.TagCompound
|
||||||
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
|
|
||||||
|
interface SerializableComponent : INBTSerializable<TagCompound> {
|
||||||
|
val serializationKey: String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun EntityComponents.serializeTo(tag: TagCompound) {
|
||||||
|
this.on<SerializableComponent> {
|
||||||
|
require(!tag.contains(serializationKey)) { "[SerializableComponent] cannot serialize duplicate key: $serializationKey" }
|
||||||
|
tag.put(serializationKey, serializeNBT())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun EntityComponents.deserializeFrom(tag: TagCompound) {
|
||||||
|
this.on<SerializableComponent> { deserializeNBT(tag.getCompound(serializationKey)) }
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package chylex.hee.system.component.general
|
||||||
|
|
||||||
|
import chylex.hee.system.component.EntityComponents
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
|
||||||
|
interface TickableComponent {
|
||||||
|
@JvmDefault fun tickClient() {}
|
||||||
|
@JvmDefault fun tickServer() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("tickEntity")
|
||||||
|
fun <T : Entity> EntityComponents.tick(entity: T) {
|
||||||
|
if (entity.world.isRemote) {
|
||||||
|
this.on(TickableComponent::tickClient)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.on(TickableComponent::tickServer)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package chylex.hee.test.main
|
||||||
|
import chylex.hee.game.loot.rng.RandomBiasedValueRange
|
||||||
|
import java.util.Random
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val min = 3F
|
||||||
|
val max = 10F
|
||||||
|
val highestChanceValue = 6.5F
|
||||||
|
val biasSoftener = 3F
|
||||||
|
|
||||||
|
val rand = Random()
|
||||||
|
val generator = RandomBiasedValueRange(min..max, highestChanceValue, biasSoftener)
|
||||||
|
val reps = 100000
|
||||||
|
|
||||||
|
val results = (1..reps).map { generator.generateInt(rand) }
|
||||||
|
.groupBy { it }
|
||||||
|
.mapValues { it.value.size }
|
||||||
|
.toList()
|
||||||
|
.sortedBy { it.first }
|
||||||
|
|
||||||
|
val pad1 = results.maxOf { it.first.toString().length }
|
||||||
|
val pad2 = results.maxOf { it.second.toString().length }
|
||||||
|
|
||||||
|
println(results.joinToString("\n") {
|
||||||
|
"${it.first.toString().padStart(pad1)} | ${it.second.toString().padStart(pad2)} | ${((it.second * 100.0) / reps).roundToInt().toString().padStart(2)} %"
|
||||||
|
})
|
||||||
|
}
|
||||||
35
src/test/java/chylex/hee/test/main/TombDungeonMobCounts.kt
Normal file
35
src/test/java/chylex/hee/test/main/TombDungeonMobCounts.kt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package chylex.hee.test.main
|
||||||
|
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel
|
||||||
|
import chylex.hee.game.world.feature.tombdungeon.TombDungeonLevel.MobAmount
|
||||||
|
import java.util.Locale.ROOT
|
||||||
|
import java.util.Random
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val rand = Random()
|
||||||
|
|
||||||
|
for(level in TombDungeonLevel.values()) {
|
||||||
|
val reps = 100000
|
||||||
|
|
||||||
|
println()
|
||||||
|
println("== ${level.name} ${"=".repeat(24 - level.name.length)}")
|
||||||
|
|
||||||
|
for(amount in MobAmount.values()) {
|
||||||
|
println()
|
||||||
|
println(" ${amount.name}")
|
||||||
|
println()
|
||||||
|
|
||||||
|
val results = (1..reps)
|
||||||
|
.map { level.pickUndreadAndSpiderlingSpawns(rand, amount) }
|
||||||
|
.groupingBy { it }
|
||||||
|
.eachCount()
|
||||||
|
.entries
|
||||||
|
.map { ((it.value * 100.0) / reps).roundToInt() to it.key }
|
||||||
|
.sortedWith(compareBy({ -it.first }, { -it.second.first }, { -it.second.second }))
|
||||||
|
|
||||||
|
println(results.joinToString("\n") { " U = ${it.second.first} S = ${it.second.second} ${it.first.toString().padStart(2)} %" })
|
||||||
|
println(" U ~ ${"%.1f".format(ROOT, results.sumBy { it.second.first * it.first } * 0.01)} S ~ ${"%.1f".format(ROOT, results.sumBy { it.second.second * it.first } * 0.01)}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package chylex.hee.test.mechanics.damage
|
package chylex.hee.test.unit.mechanics.damage
|
||||||
|
|
||||||
import chylex.hee.game.mechanics.damage.DamageProperties
|
import chylex.hee.game.mechanics.damage.DamageProperties
|
||||||
import chylex.hee.game.mechanics.damage.DamageType
|
import chylex.hee.game.mechanics.damage.DamageType
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package chylex.hee.test.mechanics.energy
|
package chylex.hee.test.unit.mechanics.energy
|
||||||
|
|
||||||
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Floating
|
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Floating
|
||||||
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Internal
|
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Internal
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package chylex.hee.test.system.util
|
package chylex.hee.test.unit.system
|
||||||
|
|
||||||
import chylex.hee.game.world.Pos
|
import chylex.hee.game.world.Pos
|
||||||
import chylex.hee.system.math.Vec
|
import chylex.hee.system.math.Vec
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package chylex.hee.test.system.util
|
package chylex.hee.test.unit.system
|
||||||
|
|
||||||
import chylex.hee.game.inventory.cleanupNBT
|
import chylex.hee.game.inventory.cleanupNBT
|
||||||
import chylex.hee.game.inventory.heeTag
|
import chylex.hee.game.inventory.heeTag
|
||||||
Reference in New Issue
Block a user