Skip to content

Commit 132d434

Browse files
committed
build
1 parent 13d49f9 commit 132d434

35 files changed

+1577
-15
lines changed

src/main/kotlin/dev/sterner/VoidBound.kt

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ object VoidBound : ModInitializer {
3131
VoidBoundParticleTypeRegistry.PARTICLES.register()
3232
VoidBoundMemoryTypeRegistry.MEMORY_TYPES.register()
3333
VoidBoundSensorTypeRegistry.SENSOR_TYPES.register()
34+
VoidBoundWandFocusRegistry.WAND_FOCI.register()
3435
VoidBoundRiftTypeRegistry.RIFT_TYPES.register()
3536
VoidBoundMenuTypeRegistry.MENU_TYPES.register()
3637
VoidBoundStructureRegistry.STRUCTURES.register()

src/main/kotlin/dev/sterner/VoidBoundClient.kt

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import dev.sterner.VoidBound.id
66
import dev.sterner.client.VoidBoundModelLoaderPlugin
77
import dev.sterner.client.renderer.HallowedMonocleRenderer
88
import dev.sterner.client.renderer.IchoriumCircletRenderer
9+
import dev.sterner.client.renderer.WandItemRenderer
910
import dev.sterner.client.screen.OsmoticEnchanterScreen
1011
import dev.sterner.common.ItemAbilityHandler
1112
import dev.sterner.registry.*
@@ -46,6 +47,15 @@ object VoidBoundClient : ClientModInitializer {
4647
return@register v
4748
}
4849

50+
BuiltinItemRendererRegistry.INSTANCE.register(
51+
VoidBoundItemRegistry.HALLOWED_GOLD_CAPPED_RUNEWOOD_WAND.get(),
52+
WandItemRenderer("hallowed_gold_capped_runewood_wand")
53+
)
54+
BuiltinItemRendererRegistry.INSTANCE.register(
55+
VoidBoundItemRegistry.SOUL_STAINED_STEEL_CAPPED_SOULWOOD_WAND.get(),
56+
WandItemRenderer("soul_stained_steel_capped_soulwood_wand")
57+
)
58+
4959
BlockRenderLayerMap.INSTANCE.putBlocks(
5060
RenderType.cutout(),
5161
VoidBoundBlockRegistry.TEAR_OF_ENDER.get(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package dev.sterner.api
2+
3+
import com.sammy.malum.client.VoidRevelationHandler
4+
import com.sammy.malum.common.container.WeaversWorkbenchContainer.component
5+
import com.sammy.malum.core.systems.recipe.SpiritWithCount
6+
import dev.sterner.api.item.ItemAbility
7+
import dev.sterner.api.item.ItemAbilityWithLevel
8+
import dev.sterner.listener.EnchantSpiritDataReloadListener
9+
import dev.sterner.registry.VoidBoundComponentRegistry
10+
import dev.sterner.registry.VoidBoundItemRegistry
11+
import net.minecraft.client.Minecraft
12+
import net.minecraft.core.BlockPos
13+
import net.minecraft.core.GlobalPos
14+
import net.minecraft.core.registries.BuiltInRegistries
15+
import net.minecraft.network.chat.Component
16+
import net.minecraft.world.entity.EquipmentSlot
17+
import net.minecraft.world.entity.player.Player
18+
import net.minecraft.world.item.ItemStack
19+
import net.minecraft.world.item.enchantment.Enchantment
20+
import net.minecraft.world.level.Level
21+
import team.lodestar.lodestone.helpers.TrinketsHelper
22+
23+
object VoidBoundApi {
24+
25+
/**
26+
* Returns true if a client player has the hallowed goggles or monocle equipped
27+
*/
28+
fun hasGoggles(): Boolean {
29+
val player = Minecraft.getInstance().player
30+
if (player != null) {
31+
val bl = TrinketsHelper.hasTrinketEquipped(player, VoidBoundItemRegistry.HALLOWED_MONOCLE.get())
32+
val bl2 = Minecraft.getInstance().player!!.getItemBySlot(EquipmentSlot.HEAD)
33+
.`is`(
34+
VoidBoundItemRegistry.HALLOWED_GOGGLES.get()
35+
)
36+
return bl || bl2
37+
}
38+
return false
39+
}
40+
41+
/**
42+
* Returns true if a player has the hallowed goggles or monocle equipped
43+
*/
44+
fun hasGoggles(player: Player): Boolean {
45+
val bl = TrinketsHelper.hasTrinketEquipped(player, VoidBoundItemRegistry.HALLOWED_MONOCLE.get())
46+
val bl2 = Minecraft.getInstance().player!!.getItemBySlot(EquipmentSlot.HEAD)
47+
.`is`(
48+
VoidBoundItemRegistry.HALLOWED_GOGGLES.get()
49+
)
50+
return bl || bl2
51+
}
52+
53+
/**
54+
* Returns how many spirits of each kind a enchantment is worth for the osmotic enchanter
55+
*/
56+
fun getSpiritFromEnchant(enchantment: Enchantment, level: Int): List<SpiritWithCount> {
57+
58+
val reg = BuiltInRegistries.ENCHANTMENT.getKey(enchantment)
59+
val list = EnchantSpiritDataReloadListener.ENCHANTING_DATA[reg]
60+
val out = mutableListOf<SpiritWithCount>()
61+
if (list != null) {
62+
for (spiritIn in list.spirits) {
63+
out.add(SpiritWithCount(spiritIn.type, spiritIn.count * level))
64+
}
65+
}
66+
67+
return out
68+
}
69+
70+
/**
71+
* Returns false if the block being broken is warded by another player
72+
*/
73+
fun canPlayerBreakBlock(level: Level, player: Player, blockPos: BlockPos): Boolean {
74+
val comp = VoidBoundComponentRegistry.VOID_BOUND_WORLD_COMPONENT.get(level)
75+
if (comp.isEmpty()) {
76+
return true
77+
}
78+
79+
return !comp.isPosBoundToAnotherPlayer(player, GlobalPos.of(player.level().dimension(), blockPos))
80+
}
81+
82+
/**
83+
* Returns false if the block being broken is warded by any player
84+
*/
85+
fun canBlockBreak(level: Level, blockPos: BlockPos): Boolean {
86+
val comp = VoidBoundComponentRegistry.VOID_BOUND_WORLD_COMPONENT.get(level)
87+
if (comp.isEmpty()) {
88+
return true
89+
}
90+
91+
if (comp.hasBlockPos(GlobalPos.of(level.dimension(), blockPos))) {
92+
return false
93+
}
94+
return true
95+
}
96+
97+
fun hasTearKnowledgeClient(): Boolean {
98+
val player = Minecraft.getInstance().player
99+
if (player != null) {
100+
val comp = VoidBoundComponentRegistry.VOID_BOUND_REVELATION_COMPONENT.get(player)
101+
return comp.isTearKnowledgeComplete()
102+
}
103+
return false
104+
}
105+
106+
fun addThought(player: Player, text: Component, duration: Int = 20 * 5){
107+
VoidBoundComponentRegistry.VOID_BOUND_REVELATION_COMPONENT.maybeGet(player).ifPresent {
108+
it.addThought(text, duration, 20 * 5)
109+
}
110+
}
111+
112+
fun getItemAbility(stack: ItemStack): List<ItemAbilityWithLevel> {
113+
val abilities = mutableListOf<ItemAbilityWithLevel>()
114+
val tag = stack.tag ?: return abilities // Return empty if no NBT
115+
116+
val abilitiesTag = tag.getList("Abilities", 10) // 10 is the NBT type for CompoundTag
117+
for (i in 0 until abilitiesTag.size) {
118+
val abilityTag = abilitiesTag.getCompound(i)
119+
val ability = ItemAbilityWithLevel.readNbt(abilityTag)
120+
abilities.add(ability)
121+
}
122+
return abilities
123+
}
124+
125+
// Function to add an ItemAbilityWithLevel to an ItemStack's NBT
126+
fun addItemAbility(stack: ItemStack, abilityWithLevel: ItemAbilityWithLevel) {
127+
val tag = stack.orCreateTag // Ensures the stack has NBT
128+
val abilitiesTag = tag.getList("Abilities", 10) // Fetch or create list
129+
130+
// Check if ability already exists, if so, skip adding a duplicate
131+
for (i in 0 until abilitiesTag.size) {
132+
val abilityTag = abilitiesTag.getCompound(i)
133+
val existingAbility = ItemAbilityWithLevel.readNbt(abilityTag)
134+
if (existingAbility.itemAbility == abilityWithLevel.itemAbility) {
135+
return // Ability already exists, exit without adding
136+
}
137+
}
138+
139+
// Add new ability
140+
abilitiesTag.add(abilityWithLevel.writeNbt())
141+
tag.put("Abilities", abilitiesTag)
142+
}
143+
144+
// Function to modify the level of an existing ItemAbility in NBT
145+
fun modifyItemAbilityLevel(stack: ItemStack, itemAbility: ItemAbility, newLevel: Int) {
146+
val tag = stack.tag ?: return // No NBT, nothing to modify
147+
val abilitiesTag = tag.getList("Abilities", 10)
148+
149+
// Find the ability and modify its level
150+
for (i in 0 until abilitiesTag.size) {
151+
val abilityTag = abilitiesTag.getCompound(i)
152+
val ability = ItemAbilityWithLevel.readNbt(abilityTag)
153+
if (ability.itemAbility == itemAbility) {
154+
// Modify the level and update the NBT
155+
abilityTag.putInt("Level", newLevel)
156+
abilitiesTag[i] = abilityTag // Replace the modified ability in the list
157+
tag.put("Abilities", abilitiesTag)
158+
return
159+
}
160+
}
161+
}
162+
163+
fun hasItemAbility(stack: ItemStack, ability: ItemAbility): Boolean {
164+
return !getItemAbility(stack).none { it.itemAbility == ability }
165+
}
166+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dev.sterner.api.item
2+
3+
import net.minecraft.nbt.CompoundTag
4+
5+
data class ItemAbilityWithLevel(val itemAbility: ItemAbility, val level: Int) {
6+
7+
fun writeNbt(): CompoundTag {
8+
val compoundTag = CompoundTag()
9+
compoundTag.putString("ItemAbility", itemAbility.name)
10+
compoundTag.putInt("Level", level)
11+
return compoundTag
12+
}
13+
14+
companion object {
15+
fun readNbt(nbt: CompoundTag): ItemAbilityWithLevel {
16+
val ability = ItemAbility.valueOf(nbt.getString("ItemAbility"))
17+
val level = nbt.getInt("Level")
18+
19+
return ItemAbilityWithLevel(ability, level)
20+
}
21+
}
22+
23+
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package dev.sterner.api.wand
2+
3+
import net.minecraft.world.entity.player.Player
4+
import net.minecraft.world.item.ItemStack
5+
import net.minecraft.world.level.Level
6+
import net.minecraft.world.phys.HitResult
7+
8+
interface IWandFocus {
9+
10+
fun onFocusRightClick(stack: ItemStack, level: Level, player: Player, hitResult: HitResult) {
11+
12+
}
13+
14+
fun onUsingFocusTick(stack: ItemStack, level: Level, player: Player) {
15+
16+
}
17+
18+
fun onPlayerStopUsingFocus(stack: ItemStack, level: Level, player: Player) {
19+
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package dev.sterner.client.renderer
2+
3+
import com.mojang.blaze3d.vertex.PoseStack
4+
import dev.sterner.VoidBound
5+
import dev.sterner.client.model.FocusModel
6+
import dev.sterner.client.model.WandItemModel
7+
import dev.sterner.registry.VoidBoundWandFocusRegistry
8+
import net.fabricmc.fabric.api.client.rendering.v1.BuiltinItemRendererRegistry.DynamicItemRenderer
9+
import net.minecraft.client.Minecraft
10+
import net.minecraft.client.renderer.MultiBufferSource
11+
import net.minecraft.client.renderer.RenderType
12+
import net.minecraft.resources.ResourceLocation
13+
import net.minecraft.world.item.ItemDisplayContext
14+
import net.minecraft.world.item.ItemStack
15+
16+
17+
class WandItemRenderer(val texture: String) : DynamicItemRenderer {
18+
19+
var model: WandItemModel? = null
20+
21+
var focusModel: FocusModel? = null
22+
23+
24+
override fun render(
25+
stack: ItemStack,
26+
mode: ItemDisplayContext,
27+
poseStack: PoseStack,
28+
vertexConsumers: MultiBufferSource,
29+
light: Int,
30+
overlay: Int
31+
) {
32+
33+
if (model == null) {
34+
model = WandItemModel(Minecraft.getInstance().entityModels.bakeLayer(WandItemModel.LAYER_LOCATION))
35+
}
36+
if (focusModel == null) {
37+
focusModel = FocusModel(Minecraft.getInstance().entityModels.bakeLayer(FocusModel.LAYER_LOCATION))
38+
}
39+
40+
poseStack.pushPose()
41+
42+
poseStack.translate(0f, 0.75f, 0f)
43+
44+
poseStack.translate(0.5, 0.65, 0.5)
45+
46+
poseStack.scale(1f, -1f, -1f)
47+
model?.renderToBuffer(
48+
poseStack,
49+
vertexConsumers.getBuffer(RenderType.entityTranslucent(VoidBound.id("textures/item/$texture.png"))),
50+
light,
51+
overlay,
52+
1f,
53+
1f,
54+
1f,
55+
1f
56+
)
57+
58+
val focusName = stack.tag?.getString("FocusName")
59+
val focus = VoidBoundWandFocusRegistry.WAND_FOCUS.getOptional(focusName?.let { ResourceLocation.tryParse(it) })
60+
if (focus.isPresent) {
61+
62+
focusModel?.renderToBuffer(
63+
poseStack,
64+
vertexConsumers.getBuffer(
65+
RenderType.entityTranslucent(
66+
VoidBound.id(
67+
"textures/models/${
68+
ResourceLocation.tryParse(
69+
focusName!!
70+
)!!.path
71+
}.png"
72+
)
73+
)
74+
),
75+
light,
76+
overlay,
77+
1f,
78+
1f,
79+
1f,
80+
1f
81+
)
82+
}
83+
84+
poseStack.popPose()
85+
}
86+
}

0 commit comments

Comments
 (0)