Skip to content

Commit 8d02c9c

Browse files
committed
rewrite item carrier
1 parent fa79d00 commit 8d02c9c

File tree

7 files changed

+335
-13
lines changed

7 files changed

+335
-13
lines changed

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ loader_version=0.16.3
99
fabric_kotlin_version=1.12.1+kotlin.2.0.20
1010

1111
# Mod Properties
12-
mod_version=0.1.6
12+
mod_version=0.2.1
1313
maven_group=dev.sterner
1414
archives_base_name=voidbound
1515

src/main/kotlin/dev/sterner/api/util/VoidBoundBlockUtils.kt

+19-4
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,24 @@ import kotlin.math.abs
1717

1818
object VoidBoundBlockUtils {
1919

20+
/**
21+
* Finds the furthest block from the origin.
22+
*/
23+
private fun findFurthestBlock(logs: List<BlockPos>, origin: BlockPos): BlockPos {
24+
return logs.maxByOrNull { it.distManhattan(origin) } ?: origin
25+
}
2026

2127
/**
2228
* Recursively gathers all connected log blocks of the same type.
29+
* If returnFurthestOnly is true, it returns only the furthest block away from the origin.
2330
*/
2431
fun gatherConnectedLogs(
2532
level: Level,
2633
pos: BlockPos,
2734
logsToBreak: MutableList<BlockPos>,
28-
logType: Block
35+
logType: Block,
36+
returnFurthestOnly: Boolean = false,
37+
origin: BlockPos = pos
2938
): List<BlockPos> {
3039
if (logsToBreak.size > 256) return logsToBreak
3140

@@ -36,12 +45,18 @@ object VoidBoundBlockUtils {
3645
val checkPositions = surroundingLogs.filter { !logsToBreak.contains(it) && isLogMatch(level, it, logType) }
3746
logsToBreak.addAll(checkPositions)
3847

39-
if (checkPositions.isEmpty()) return logsToBreak
48+
if (checkPositions.isEmpty()) {
49+
return if (returnFurthestOnly) {
50+
listOf(findFurthestBlock(logsToBreak, origin))
51+
} else {
52+
logsToBreak
53+
}
54+
}
4055

41-
checkPositions.forEach { gatherConnectedLogs(level, it, logsToBreak, logType) }
56+
checkPositions.forEach { gatherConnectedLogs(level, it, logsToBreak, logType, returnFurthestOnly, origin) }
4257

4358
val upwardPosition = pos.above(2)
44-
return gatherConnectedLogs(level, upwardPosition.immutable(), logsToBreak, logType)
59+
return gatherConnectedLogs(level, upwardPosition.immutable(), logsToBreak, logType, returnFurthestOnly, origin)
4560
}
4661

4762
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package dev.sterner.client.renderer.entity
2+
3+
import com.mojang.blaze3d.vertex.PoseStack
4+
import com.mojang.math.Axis
5+
import com.sammy.malum.client.RenderUtils
6+
import com.sammy.malum.client.SpiritBasedWorldVFXBuilder
7+
import com.sammy.malum.common.entity.FloatingItemEntity
8+
import com.sammy.malum.core.systems.spirit.MalumSpiritType
9+
import com.sammy.malum.registry.client.MalumRenderTypeTokens
10+
import com.sammy.malum.registry.common.SpiritTypeRegistry
11+
import dev.sterner.common.entity.ItemCarrierItemEntity
12+
import net.minecraft.client.Minecraft
13+
import net.minecraft.client.renderer.MultiBufferSource
14+
import net.minecraft.client.renderer.entity.EntityRenderer
15+
import net.minecraft.client.renderer.entity.EntityRendererProvider
16+
import net.minecraft.client.renderer.entity.ItemRenderer
17+
import net.minecraft.client.renderer.texture.OverlayTexture
18+
import net.minecraft.client.renderer.texture.TextureAtlas
19+
import net.minecraft.resources.ResourceLocation
20+
import net.minecraft.world.entity.LivingEntity
21+
import net.minecraft.world.item.ItemDisplayContext
22+
import net.minecraft.world.level.Level
23+
import team.lodestar.lodestone.helpers.EasingHelper
24+
import team.lodestar.lodestone.registry.client.LodestoneRenderTypeRegistry
25+
import team.lodestar.lodestone.systems.easing.Easing
26+
import team.lodestar.lodestone.systems.rendering.LodestoneRenderType
27+
import team.lodestar.lodestone.systems.rendering.VFXBuilders.WorldVFXBuilder
28+
import java.awt.Color
29+
import kotlin.math.abs
30+
import kotlin.math.sin
31+
32+
class ItemCarrierItemEntityRenderer(context: EntityRendererProvider.Context) :
33+
EntityRenderer<ItemCarrierItemEntity>(context) {
34+
35+
val itemRenderer: ItemRenderer = context.itemRenderer
36+
37+
override fun render(
38+
entity: ItemCarrierItemEntity,
39+
entityYaw: Float,
40+
partialTicks: Float,
41+
poseStack: PoseStack,
42+
bufferIn: MultiBufferSource,
43+
packedLightIn: Int
44+
) {
45+
val spiritType = SpiritTypeRegistry.AQUEOUS_SPIRIT
46+
val trailBuilder = SpiritBasedWorldVFXBuilder.create(spiritType).setRenderType(TRAIL_TYPE)
47+
RenderUtils.renderEntityTrail(
48+
poseStack,
49+
trailBuilder,
50+
entity.trailPointBuilder,
51+
entity,
52+
spiritType.primaryColor,
53+
spiritType.secondaryColor,
54+
1.0f,
55+
partialTicks
56+
)
57+
renderSpiritEntity(
58+
entity,
59+
this.itemRenderer, partialTicks, poseStack, bufferIn, packedLightIn
60+
)
61+
super.render(entity, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn)
62+
}
63+
64+
override fun getTextureLocation(entity: ItemCarrierItemEntity): ResourceLocation {
65+
return TextureAtlas.LOCATION_BLOCKS
66+
}
67+
68+
init {
69+
this.shadowRadius = 0.0f
70+
this.shadowStrength = 0.0f
71+
}
72+
73+
companion object {
74+
private val TRAIL_TYPE: LodestoneRenderType =
75+
LodestoneRenderTypeRegistry.ADDITIVE_TEXTURE_TRIANGLE.applyAndCache(MalumRenderTypeTokens.CONCENTRATED_TRAIL)
76+
private val TWINKLE: LodestoneRenderType =
77+
LodestoneRenderTypeRegistry.ADDITIVE_TEXTURE.applyAndCache(MalumRenderTypeTokens.TWINKLE)
78+
private val STAR: LodestoneRenderType =
79+
LodestoneRenderTypeRegistry.ADDITIVE_TEXTURE.applyAndCache(MalumRenderTypeTokens.STAR)
80+
81+
fun renderSpiritEntity(
82+
entity: ItemCarrierItemEntity,
83+
itemRenderer: ItemRenderer,
84+
partialTicks: Float,
85+
poseStack: PoseStack,
86+
bufferIn: MultiBufferSource?,
87+
packedLightIn: Int
88+
) {
89+
val itemStack = entity.itemStack
90+
val model = itemRenderer.getModel(itemStack, entity.level(), null as LivingEntity?, entity.itemStack.count)
91+
val yOffset = entity.getYOffset(partialTicks)
92+
val scale = model.transforms.getTransform(ItemDisplayContext.GROUND).scale.y()
93+
val rotation = entity.getRotation(partialTicks)
94+
poseStack.pushPose()
95+
poseStack.translate(0.0, (yOffset - 0.25f * scale).toDouble(), 0.0)
96+
poseStack.mulPose(Axis.YP.rotation(rotation))
97+
itemRenderer.render(
98+
itemStack,
99+
ItemDisplayContext.GROUND,
100+
false,
101+
poseStack,
102+
bufferIn,
103+
packedLightIn,
104+
OverlayTexture.NO_OVERLAY,
105+
model
106+
)
107+
poseStack.popPose()
108+
poseStack.pushPose()
109+
poseStack.translate(0.0, yOffset.toDouble(), 0.0)
110+
renderSpiritGlimmer(poseStack, SpiritTypeRegistry.AQUEOUS_SPIRIT, partialTicks)
111+
poseStack.popPose()
112+
}
113+
114+
fun renderSpiritGlimmer(poseStack: PoseStack, spiritType: MalumSpiritType, partialTicks: Float) {
115+
renderSpiritGlimmer(poseStack, spiritType, 1.0f, partialTicks)
116+
}
117+
118+
fun renderSpiritGlimmer(poseStack: PoseStack, spiritType: MalumSpiritType, scalar: Float, partialTicks: Float) {
119+
renderSpiritGlimmer(
120+
poseStack,
121+
SpiritBasedWorldVFXBuilder.create(spiritType),
122+
spiritType.primaryColor,
123+
spiritType.secondaryColor,
124+
scalar,
125+
scalar,
126+
partialTicks
127+
)
128+
}
129+
130+
fun renderSpiritGlimmer(
131+
poseStack: PoseStack,
132+
builder: WorldVFXBuilder,
133+
primaryColor: Color?,
134+
secondaryColor: Color?,
135+
scaleScalar: Float,
136+
alphaScalar: Float,
137+
partialTicks: Float
138+
) {
139+
val level: Level? = Minecraft.getInstance().level
140+
val gameTime = level!!.gameTime.toFloat() + partialTicks
141+
val sine = abs(sin((gameTime / 80.0f % 360.0f).toDouble()) * 0.07500000298023224)
142+
.toFloat()
143+
val bounce =
144+
EasingHelper.weightedEasingLerp(Easing.BOUNCE_IN_OUT, gameTime % 20.0f / 20.0f, 0.025f, 0.05f, 0.025f)
145+
val scale = (0.12f + sine + bounce) * scaleScalar
146+
poseStack.pushPose()
147+
poseStack.mulPose(Minecraft.getInstance().entityRenderDispatcher.cameraOrientation())
148+
poseStack.mulPose(Axis.YP.rotationDegrees(180.0f))
149+
builder.setAlpha(0.6f * alphaScalar).setColor(primaryColor).setRenderType(STAR)
150+
.renderQuad(poseStack, scale * 0.8f)
151+
builder.setAlpha(0.8f * alphaScalar).setRenderType(TWINKLE).renderQuad(poseStack, scale * 0.8f)
152+
builder.setAlpha(0.2f * alphaScalar).setColor(secondaryColor).renderQuad(poseStack, scale * 1.2f)
153+
poseStack.popPose()
154+
}
155+
}
156+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package dev.sterner.common.entity
2+
3+
import com.sammy.malum.common.entity.FloatingEntity
4+
import com.sammy.malum.registry.common.SpiritTypeRegistry
5+
import com.sammy.malum.registry.common.item.ItemRegistry
6+
import com.sammy.malum.visual_effects.SpiritLightSpecs
7+
import dev.sterner.registry.VoidBoundEntityTypeRegistry
8+
import net.minecraft.nbt.CompoundTag
9+
import net.minecraft.network.syncher.EntityDataAccessor
10+
import net.minecraft.network.syncher.EntityDataSerializers
11+
import net.minecraft.network.syncher.SynchedEntityData
12+
import net.minecraft.world.item.Item
13+
import net.minecraft.world.item.ItemStack
14+
import net.minecraft.world.item.Items
15+
import net.minecraft.world.level.Level
16+
import net.minecraft.world.phys.Vec3
17+
import team.lodestar.lodestone.helpers.ItemHelper
18+
import team.lodestar.lodestone.systems.particle.ParticleEffectSpawner
19+
import java.util.*
20+
21+
22+
class ItemCarrierItemEntity(level: Level?) : FloatingEntity(VoidBoundEntityTypeRegistry.ITEM_CARRIER_ENTITY.get(), level) {
23+
var itemStack: ItemStack = ItemStack(Items.STICK)
24+
25+
constructor(
26+
level: Level?,
27+
ownerUUID: UUID?,
28+
stack: ItemStack,
29+
posX: Double,
30+
posY: Double,
31+
posZ: Double,
32+
velX: Double,
33+
velY: Double,
34+
velZ: Double
35+
): this(level) {
36+
37+
this.setOwner(ownerUUID)
38+
this.setItem(stack)
39+
this.itemStack = stack
40+
this.setPos(posX, posY, posZ)
41+
this.setDeltaMovement(velX, velY, velZ)
42+
this.maxAge = 800
43+
}
44+
45+
override fun addAdditionalSaveData(pCompound: CompoundTag) {
46+
super.addAdditionalSaveData(pCompound)
47+
val itemstack = this.getItemRaw()
48+
if (!itemstack.isEmpty) {
49+
pCompound.put("Item", itemstack.save(CompoundTag()))
50+
}
51+
}
52+
53+
override fun readAdditionalSaveData(pCompound: CompoundTag) {
54+
super.readAdditionalSaveData(pCompound)
55+
val itemstack = ItemStack.of(pCompound.getCompound("Item"))
56+
this.setItem(itemstack)
57+
}
58+
59+
fun setItem(pStack: ItemStack) {
60+
getEntityData().set(DATA_ITEM_STACK, pStack)
61+
}
62+
63+
override fun defineSynchedData() {
64+
getEntityData().define(DATA_ITEM_STACK, ItemStack.EMPTY)
65+
}
66+
67+
override fun onSyncedDataUpdated(pKey: EntityDataAccessor<*>) {
68+
if (DATA_ITEM_STACK == pKey) {
69+
this.itemStack = getEntityData().get(DATA_ITEM_STACK) as ItemStack
70+
}
71+
72+
super.onSyncedDataUpdated(pKey)
73+
}
74+
75+
override fun collect() {
76+
ItemHelper.giveItemToEntity(this.owner, getItem())
77+
}
78+
79+
override fun getMotionCoefficient(): Float {
80+
return 0.1f
81+
}
82+
83+
protected fun getItemRaw(): ItemStack {
84+
return getEntityData().get(DATA_ITEM_STACK) as ItemStack
85+
}
86+
87+
protected fun getDefaultItem(): Item {
88+
return ItemRegistry.ARCANE_SPIRIT.get() as Item
89+
}
90+
91+
fun getItem(): ItemStack {
92+
val itemstack = this.getItemRaw()
93+
return if (itemstack.isEmpty) ItemStack(this.getDefaultItem()) else itemstack
94+
}
95+
96+
override fun spawnParticles(x: Double, y: Double, z: Double) {
97+
val motion = this.deltaMovement
98+
val norm = motion.normalize().scale(0.05000000074505806)
99+
val lightSpecs: ParticleEffectSpawner =
100+
SpiritLightSpecs.spiritLightSpecs(this.level(), Vec3(x, y, z), SpiritTypeRegistry.AQUEOUS_SPIRIT)
101+
lightSpecs.builder.setMotion(norm)
102+
lightSpecs.bloomBuilder.setMotion(norm)
103+
lightSpecs.spawnParticles()
104+
}
105+
106+
companion object {
107+
var DATA_ITEM_STACK = SynchedEntityData.defineId(ItemCarrierItemEntity::class.java, EntityDataSerializers.ITEM_STACK)
108+
}
109+
}

src/main/kotlin/dev/sterner/common/item/equipment/TidecutterItem.kt

+35-8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package dev.sterner.common.item.equipment
22

33
import dev.sterner.api.util.VoidBoundBlockUtils
44
import dev.sterner.api.util.VoidBoundUtils
5+
import dev.sterner.common.entity.ItemCarrierItemEntity
56
import dev.sterner.networking.AxeOfTheStreamParticlePacket
6-
import dev.sterner.networking.BubbleParticlePacket
77
import dev.sterner.registry.VoidBoundItemRegistry
88
import dev.sterner.registry.VoidBoundPacketRegistry
99
import io.github.fabricators_of_create.porting_lib.event.common.BlockEvents
@@ -26,8 +26,8 @@ import net.minecraft.world.level.Level
2626
import net.minecraft.world.level.block.Block
2727
import net.minecraft.world.level.block.Blocks
2828
import net.minecraft.world.level.block.state.BlockState
29-
import net.minecraft.world.phys.Vec3
30-
import org.joml.Vector3f
29+
import team.lodestar.lodestone.helpers.ItemHelper
30+
import team.lodestar.lodestone.helpers.RandomHelper
3131
import team.lodestar.lodestone.systems.item.tools.magic.MagicAxeItem
3232
import java.awt.Color
3333

@@ -75,10 +75,27 @@ open class TidecutterItem(
7575
}
7676

7777
override fun onUseTick(level: Level, livingEntity: LivingEntity, stack: ItemStack, remainingUseDuration: Int) {
78-
val stuff = level.getEntitiesOfClass(ItemEntity::class.java, livingEntity.boundingBox.inflate(10.0))
79-
80-
if (stuff != null && stuff.isNotEmpty()) {
81-
//TODO
78+
val nearbyItems: MutableList<ItemEntity> = level.getEntitiesOfClass(ItemEntity::class.java, livingEntity.boundingBox.inflate(10.0))
79+
if (nearbyItems.isNotEmpty()) {
80+
for (item in nearbyItems) {
81+
82+
val newStack = item.item.copy()
83+
newStack.count = newStack.count
84+
newStack.tag = newStack.tag
85+
86+
val entity = ItemCarrierItemEntity(
87+
level, livingEntity.uuid, newStack,
88+
item.x,
89+
item.y,
90+
item.z,
91+
RandomHelper.randomBetween(level.random, -speed, speed).toDouble(),
92+
RandomHelper.randomBetween(level.random, 0.05f, 0.06f).toDouble(),
93+
RandomHelper.randomBetween(level.random, -speed, speed).toDouble()
94+
)
95+
entity.entityData.set(ItemCarrierItemEntity.DATA_ITEM_STACK, newStack)
96+
item.discard()
97+
level.addFreshEntity(entity)
98+
}
8299
}
83100

84101
super.onUseTick(level, livingEntity, stack, remainingUseDuration)
@@ -131,7 +148,17 @@ open class TidecutterItem(
131148
}
132149
}
133150

134-
//TODO break furthest block
151+
val theOneLog = VoidBoundBlockUtils.gatherConnectedLogs(level, pos, mutableListOf(), level.getBlockState(pos).block, true)
152+
153+
for (logPos in theOneLog) {
154+
155+
val logState = level.getBlockState(logPos)
156+
val be = level.getBlockEntity(logPos)
157+
158+
Block.dropResources(logState, level, logPos, be)
159+
level.setBlock(logPos, Blocks.AIR.defaultBlockState(), 3)
160+
}
161+
135162
breakEvent.isCanceled = true
136163
}
137164
}

0 commit comments

Comments
 (0)