Skip to content

Commit 4b9f946

Browse files
handheld drill and saw from arr and dee
1 parent b08edbc commit 4b9f946

File tree

31 files changed

+2465
-4
lines changed

31 files changed

+2465
-4
lines changed

common/src/main/java/org/valkyrienskies/clockwork/mixin/MixinLivingEntity.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package org.valkyrienskies.clockwork.mixin;
22

3+
import net.minecraft.world.InteractionHand;
34
import net.minecraft.world.entity.EquipmentSlot;
45
import net.minecraft.world.entity.LivingEntity;
56
import net.minecraft.world.item.ItemStack;
67
import org.spongepowered.asm.mixin.Mixin;
78
import org.spongepowered.asm.mixin.injection.At;
89
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
911
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1012
import org.valkyrienskies.clockwork.ClockworkItems;
13+
import org.valkyrienskies.clockwork.ClockworkTags;
1114

1215
@Mixin(LivingEntity.class)
1316
public class MixinLivingEntity {
@@ -17,4 +20,25 @@ public class MixinLivingEntity {
1720
if (item.is(ClockworkItems.GAS_BANKTANK.get())) cir.setReturnValue(EquipmentSlot.CHEST);
1821
else cir.setReturnValue(cir.getReturnValue());
1922
}
23+
24+
@Inject(method = "swing(Lnet/minecraft/world/InteractionHand;Z)V", at = @At("HEAD"), cancellable = true)
25+
private void vs_clockwork$$preSwing(InteractionHand hand, boolean updateSelf, CallbackInfo ci) {
26+
LivingEntity self = (LivingEntity) (Object) this;
27+
ItemStack itemInHand = self.getItemInHand(hand);
28+
//ts dont work imma manually do it
29+
if (itemInHand.is(ClockworkTags.AllItemTags.DISABLE_SWING_ANIMATION.getTag())) {
30+
ci.cancel();
31+
}
32+
33+
//temporary
34+
if (itemInHand.is(ClockworkItems.GRAVITRON.asItem()) || itemInHand.is(ClockworkItems.CREATIVE_GRAVITRON.asItem())) {
35+
ci.cancel();
36+
}
37+
if (itemInHand.is(ClockworkItems.HANDHELD_DRILL.asItem())) {
38+
ci.cancel();
39+
}
40+
if (itemInHand.is(ClockworkItems.HANDHELD_SAW.asItem())) {
41+
ci.cancel();
42+
}
43+
}
2044
}

common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkItems.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ import org.valkyrienskies.clockwork.content.curiosities.aeronaut.AeronautGoggles
2323
import org.valkyrienskies.clockwork.content.curiosities.aeronaut.AeronautGogglesRenderer
2424
import org.valkyrienskies.clockwork.content.curiosities.aeronaut.AeronautJacketItem
2525
import org.valkyrienskies.clockwork.content.curiosities.aeronaut.AeronautJumpersItem
26+
import org.valkyrienskies.clockwork.content.curiosities.tools.drill.HandheldDrillRenderer
27+
import org.valkyrienskies.clockwork.content.curiosities.tools.drill.HandheldMechanicalDrill
2628
import org.valkyrienskies.clockwork.content.curiosities.tools.wanderwand.WanderwandItemRenderer
2729
import org.valkyrienskies.clockwork.content.curiosities.tools.gravitron.CreativeGravitronItem
2830
import org.valkyrienskies.clockwork.content.curiosities.tools.gravitron.GravitronItem
2931
import org.valkyrienskies.clockwork.content.curiosities.tools.gravitron.GravitronItemRenderer
32+
import org.valkyrienskies.clockwork.content.curiosities.tools.saw.HandheldMechanicalSaw
33+
import org.valkyrienskies.clockwork.content.curiosities.tools.saw.HandheldSawRenderer
3034
import org.valkyrienskies.clockwork.content.curiosities.tools.wanderwand.WanderwandItem
3135
import org.valkyrienskies.clockwork.content.curiosities.tools.screwdriver.ScrewdriverItem
3236
import org.valkyrienskies.clockwork.content.kinetics.universal_shaft.UniversalShaftItem
@@ -232,6 +236,28 @@ object ClockworkItems {
232236
.tab(ClockworkMod.BASE_CREATIVE_TABINFO)
233237
.register()
234238

239+
@JvmField
240+
val HANDHELD_DRILL: ItemEntry<HandheldMechanicalDrill> =
241+
REGISTRATE.item<HandheldMechanicalDrill>("handheld_drill") { properties: Item.Properties? ->
242+
HandheldMechanicalDrill(Tiers.NETHERITE, 1, 1f, properties!!)
243+
}
244+
.tab(ClockworkMod.BASE_CREATIVE_TABINFO)
245+
.transform(ClockworkRegistrate.customRenderedItem { Supplier { HandheldDrillRenderer() } })
246+
.tag(ClockworkTags.AllItemTags.DISABLE_SWING_ANIMATION.tag)
247+
.model(AssetLookup.itemModelWithPartials())
248+
.register()
249+
250+
@JvmField
251+
val HANDHELD_SAW: ItemEntry<HandheldMechanicalSaw> =
252+
REGISTRATE.item<HandheldMechanicalSaw>("handheld_saw") { properties: Item.Properties? ->
253+
HandheldMechanicalSaw(Tiers.NETHERITE, 4f, 1f, properties!!)
254+
}
255+
.tab(ClockworkMod.BASE_CREATIVE_TABINFO)
256+
.transform(ClockworkRegistrate.customRenderedItem { Supplier { HandheldSawRenderer() } })
257+
.tag(ClockworkTags.AllItemTags.DISABLE_SWING_ANIMATION.tag)
258+
.model(AssetLookup.itemModelWithPartials())
259+
.register()
260+
235261
@JvmField
236262
val INCOMPLETE_COMPRESSIBLE_SHAFT: ItemEntry<SequencedAssemblyItem> = sequencedIngredient("incomplete_telescoping_mechanism")
237263

common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkPartials.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ object ClockworkPartials {
150150
val SMART_PROP_PISTON_SW: PartialModel = PartialModel.of(ClockworkMod.asResource("block/copter_bearing/piston_sw"))
151151
val SMART_PROP_PISTON_SE: PartialModel = PartialModel.of(ClockworkMod.asResource("block/copter_bearing/piston_se"))
152152
val SMART_PROP_WAFER: PartialModel = PartialModel.of(ClockworkMod.asResource("block/copter_bearing/wafer"))
153+
//endregion
154+
155+
val HANDHELD_DRILL_BIT: PartialModel = PartialModel.of(ClockworkMod.asResource("item/handheld_drill/head"))
156+
val HANDHELD_DRILL_COG: PartialModel = PartialModel.of(ClockworkMod.asResource("item/handheld_drill/cog"))
157+
158+
val HANDHELD_SAW_BUZZSAW: PartialModel = PartialModel.of(ClockworkMod.asResource("item/handheld_saw/saw"))
159+
val HANDHELD_SAW_COG: PartialModel = PartialModel.of(ClockworkMod.asResource("item/handheld_saw/cog"))
153160

154161
private fun block(path: String): PartialModel {
155162
return PartialModel.of(ClockworkMod.asResource("block/$path"))

common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkTags.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ object ClockworkTags {
8080
optional: Boolean = namespace.optionalDefault,
8181
alwaysDatagen: Boolean = namespace.alwaysDatagenDefault
8282
) {
83-
PROP_BLADE;
83+
PROP_BLADE,
84+
DISABLE_SWING_ANIMATION;
8485

8586
val tag: TagKey<Item>
8687
val alwaysDatagen: Boolean
@@ -114,4 +115,4 @@ object ClockworkTags {
114115
fun init() {}
115116
}
116117
}
117-
}
118+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.valkyrienskies.clockwork.content.curiosities.tools.drill
2+
3+
import com.mojang.blaze3d.vertex.PoseStack
4+
import com.mojang.math.Axis
5+
import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueHandler
6+
import com.simibubi.create.foundation.item.render.CustomRenderedItemModel
7+
import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer
8+
import com.simibubi.create.foundation.item.render.PartialItemModelRenderer
9+
import net.createmod.catnip.animation.AnimationTickHolder
10+
import net.minecraft.client.Minecraft
11+
import net.minecraft.client.renderer.MultiBufferSource
12+
import net.minecraft.world.item.ItemDisplayContext
13+
import net.minecraft.world.item.ItemStack
14+
import org.valkyrienskies.clockwork.ClockworkPartials
15+
16+
class HandheldDrillRenderer : CustomRenderedItemModelRenderer() {
17+
override fun render(
18+
stack: ItemStack,
19+
model: CustomRenderedItemModel,
20+
renderer: PartialItemModelRenderer,
21+
transformType: ItemDisplayContext,
22+
ms: PoseStack,
23+
buffer: MultiBufferSource,
24+
light: Int,
25+
overlay: Int
26+
) {
27+
renderer.render(model.getOriginalModel(), light);
28+
29+
val xOffset = -1/16f
30+
ms.pushPose()
31+
//ms.translate(-xOffset, 0f, 0f)
32+
ms.mulPose(Axis.ZP.rotationDegrees(ScrollValueHandler.getScroll(AnimationTickHolder.getPartialTicks())))
33+
//ms.translate(xOffset, 0f, 0f)
34+
renderer.render(ClockworkPartials.HANDHELD_DRILL_COG.get(), light)
35+
ms.popPose()
36+
//if holding left click, speen
37+
if (Minecraft.getInstance().options.keyAttack.isDown) {
38+
ms.mulPose(Axis.ZP.rotationDegrees(AnimationTickHolder.getTicks() * 40f % 360f))
39+
}
40+
41+
renderer.render(ClockworkPartials.HANDHELD_DRILL_BIT.get(), light)
42+
}
43+
}
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
package org.valkyrienskies.clockwork.content.curiosities.tools.drill
2+
3+
import com.google.common.collect.ImmutableMultimap
4+
import com.google.common.collect.Multimap
5+
import com.simibubi.create.content.equipment.armor.BacktankUtil
6+
import com.simibubi.create.foundation.item.CustomArmPoseItem
7+
import net.minecraft.client.model.HumanoidModel
8+
import net.minecraft.client.player.AbstractClientPlayer
9+
import net.minecraft.core.BlockPos
10+
import net.minecraft.core.Direction
11+
import net.minecraft.stats.Stats
12+
import net.minecraft.tags.BlockTags
13+
import net.minecraft.tags.TagKey
14+
import net.minecraft.world.InteractionHand
15+
import net.minecraft.world.entity.EquipmentSlot
16+
import net.minecraft.world.entity.LivingEntity
17+
import net.minecraft.world.entity.ai.attributes.Attribute
18+
import net.minecraft.world.entity.ai.attributes.AttributeModifier
19+
import net.minecraft.world.entity.player.Player
20+
import net.minecraft.world.item.ItemStack
21+
import net.minecraft.world.item.PickaxeItem
22+
import net.minecraft.world.item.Tier
23+
import net.minecraft.world.item.UseAnim
24+
import net.minecraft.world.level.Level
25+
import net.minecraft.world.level.block.Block
26+
import net.minecraft.world.level.block.state.BlockState
27+
import org.lwjgl.system.NonnullDefault
28+
import org.valkyrienskies.clockwork.ClockworkItems
29+
import org.valkyrienskies.clockwork.platform.PlatformUtils.getReachAttribute
30+
import org.valkyrienskies.clockwork.util.BoundingBoxHelper
31+
import java.util.function.Consumer
32+
import kotlin.math.ceil
33+
34+
@NonnullDefault
35+
class HandheldMechanicalDrill(tier: Tier?, attackBonus: Int, attackSpeedBonus: Float, properties: Properties?) :
36+
PickaxeItem(
37+
tier,
38+
attackBonus,
39+
attackSpeedBonus,
40+
properties
41+
), CustomArmPoseItem {
42+
override fun mineBlock(
43+
tool: ItemStack,
44+
level: Level,
45+
block: BlockState,
46+
pos: BlockPos,
47+
player: LivingEntity
48+
): Boolean {
49+
val success = super.mineBlock(tool, level, block, pos, player)
50+
51+
if (success && isCorrectToolForDrops(block) && !level!!.isClientSide) {
52+
if (player!!.isCrouching()) {
53+
mineTunnel(level, pos, player, CROUCH_MINE_DIAMETER, CROUCH_MINE_DEPTH)
54+
} else {
55+
mineTunnel(level, pos, player, MINE_DIAMETER, MINE_DEPTH)
56+
}
57+
}
58+
59+
return success
60+
}
61+
62+
override fun isCorrectToolForDrops(block: BlockState): Boolean {
63+
val ret = block.`is`(BlockTags.MINEABLE_WITH_PICKAXE) || block.`is`(BlockTags.MINEABLE_WITH_SHOVEL) || super.isCorrectToolForDrops(block)
64+
//println(ret)
65+
return ret
66+
}
67+
68+
override fun getDestroySpeed(stack: ItemStack, state: BlockState): Float {
69+
return if (isCorrectToolForDrops(state)) {
70+
this.speed
71+
} else {
72+
1.0f
73+
}
74+
}
75+
76+
/**
77+
* Mines a tunnel in the `direction` the player is facing at the given block.<br></br>
78+
* The tunnel is a rectangular prism of width and height `diameter`, and depth `depth`.
79+
*
80+
* @param level level to break the tunnel in
81+
* @param origin position to start the tunnel at
82+
* @param player player to simulate breaking the tunnel with
83+
* @param diameter diameter of the tunnel
84+
* @param depth depth of the tunnel
85+
*/
86+
private fun mineTunnel(level: Level, origin: BlockPos, player: LivingEntity, diameter: Int, depth: Int) {
87+
val direction = determineDirection(player!!)
88+
89+
val offsetX = ceil((-diameter / 2f).toDouble()).toInt()
90+
val offsetY = ceil((-diameter / 2f).toDouble()).toInt()
91+
val offsetZ = 0
92+
93+
val boundWidth = diameter
94+
val boundHeight = diameter
95+
val boundDepth = depth
96+
97+
val boundingBox = BoundingBoxHelper.orientBox(
98+
origin,
99+
offsetX,
100+
offsetY,
101+
offsetZ,
102+
boundWidth,
103+
boundHeight,
104+
boundDepth,
105+
direction
106+
)
107+
108+
BlockPos.betweenClosedStream(boundingBox).forEach { testPos: BlockPos? -> tryMine(level!!, testPos, player) }
109+
}
110+
111+
/**
112+
* Returns the player direction, with added logic for Up and Down based on `MINING_ANGLE_LIMIT`
113+
*
114+
* @param player player direction to check
115+
*
116+
* @return player direction
117+
*/
118+
private fun determineDirection(player: LivingEntity): Direction {
119+
val xRot = player.getXRot()
120+
if (xRot <= -MINING_ANGLE_LIMIT) {
121+
return Direction.UP
122+
} else if (xRot >= MINING_ANGLE_LIMIT) {
123+
return Direction.DOWN
124+
} else {
125+
return player.getDirection()
126+
}
127+
}
128+
129+
/**
130+
* Attempts to simulate mining a block. If a tool is specified, it must be breakable by that tool
131+
*
132+
* @param level level to break in
133+
* @param pos position to break at
134+
* @param livingEntity entity to simulate the break as (can be `null`)
135+
*/
136+
private fun tryMine(
137+
level: Level, pos: BlockPos?,
138+
livingEntity: LivingEntity?
139+
) {
140+
val minedBlockState = level.getBlockState(pos)
141+
142+
if (livingEntity != null) {
143+
val tool = livingEntity.getMainHandItem()
144+
145+
if (tool.`is`(ClockworkItems.HANDHELD_DRILL.get())) {
146+
val toolItem = tool.item as HandheldMechanicalDrill
147+
if (!toolItem.isCorrectToolForDrops(minedBlockState)) {
148+
return
149+
}
150+
}
151+
152+
if (livingEntity is Player && livingEntity.hasCorrectToolForDrops(minedBlockState)) {
153+
livingEntity.awardStat(Stats.BLOCK_MINED.get(minedBlockState.getBlock()))
154+
}
155+
}
156+
157+
if (level.removeBlock(pos, false)) {
158+
minedBlockState.getBlock().destroy(level, pos, minedBlockState)
159+
} else {
160+
return
161+
}
162+
163+
if (livingEntity == null) return
164+
Block.dropResources(minedBlockState, level, pos, null, livingEntity, livingEntity.getMainHandItem())
165+
}
166+
167+
override fun getDefaultAttributeModifiers(slot: EquipmentSlot?): Multimap<Attribute?, AttributeModifier?>? {
168+
val attributes = ImmutableMultimap.Builder<Attribute?, AttributeModifier?>()
169+
val distanceAttribute = getReachAttribute()
170+
attributes.putAll(super.getDefaultAttributeModifiers(slot))
171+
//attributes.put(distanceAttribute, AttributeModifier("Reach", -3.0, AttributeModifier.Operation.ADDITION))
172+
return attributes.build()
173+
}
174+
175+
override fun isBarVisible(stack: ItemStack?): Boolean {
176+
return BacktankUtil.isBarVisible(stack, MAX_BACKTANK_USES)
177+
}
178+
179+
override fun getBarWidth(stack: ItemStack?): Int {
180+
return BacktankUtil.getBarWidth(stack, MAX_BACKTANK_USES)
181+
}
182+
183+
override fun getBarColor(stack: ItemStack?): Int {
184+
return BacktankUtil.getBarColor(stack, MAX_BACKTANK_USES)
185+
}
186+
187+
override fun getUseAnimation(stack: ItemStack?): UseAnim? {
188+
return UseAnim.NONE
189+
}
190+
191+
fun <T : LivingEntity?> damageItem(stack: ItemStack?, amount: Int, entity: T?, onBroken: Consumer<T?>?): Int {
192+
if (BacktankUtil.canAbsorbDamage(entity, MAX_BACKTANK_USES)) {
193+
return 0
194+
}
195+
return amount
196+
}
197+
198+
override fun getArmPose(
199+
stack: ItemStack?,
200+
player: AbstractClientPlayer,
201+
hand: InteractionHand?
202+
): HumanoidModel.ArmPose? {
203+
return HumanoidModel.ArmPose.CROSSBOW_HOLD
204+
}
205+
206+
companion object {
207+
// Constants
208+
protected const val MAX_DAMAGE: Int = 2048
209+
protected const val MAX_BACKTANK_USES: Int = 1000
210+
211+
// Mining Constants
212+
private const val MINING_ANGLE_LIMIT = 55
213+
214+
private const val MINE_DIAMETER = 3
215+
private const val MINE_DEPTH = 1
216+
217+
private const val CROUCH_MINE_DIAMETER = 1
218+
private const val CROUCH_MINE_DEPTH = 3
219+
}
220+
}

0 commit comments

Comments
 (0)