Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_item": {
"conditions": {
"items": [
{
"items": "#hexcasting:staves"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "hexcasting:freeze/blue_ice"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_item"
]
],
"rewards": {
"recipes": [
"hexcasting:freeze/blue_ice"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_item": {
"conditions": {
"items": [
{
"items": "#hexcasting:staves"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "hexcasting:freeze/packed_ice"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_item"
]
],
"rewards": {
"recipes": [
"hexcasting:freeze/packed_ice"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_item": {
"conditions": {
"items": [
{
"items": "#hexcasting:staves"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "hexcasting:freeze/powder_snow_cauldron"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_item"
]
],
"rewards": {
"recipes": [
"hexcasting:freeze/powder_snow_cauldron"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"type": "hexcasting:freeze",
"blockIn": {
"type": "hexcasting:block",
"block": "minecraft:packed_ice"
},
"result": {
"Name": "minecraft:blue_ice"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"type": "hexcasting:freeze",
"blockIn": {
"type": "hexcasting:block",
"block": "minecraft:ice"
},
"result": {
"Name": "minecraft:packed_ice"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"type": "hexcasting:freeze",
"blockIn": {
"type": "hexcasting:block",
"block": "minecraft:water_cauldron"
},
"result": {
"Name": "minecraft:powder_snow_cauldron",
"Properties": {
"level": "1"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,25 @@ fun List<Iota>.getNumOrVec(idx: Int, argc: Int = 0): Either<Double, Vec3> {
}
}

fun List<Iota>.getVecOrVecList(idx: Int, argc: Int = 0): Either<Vec3, List<Vec3>> {
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
return when (x) {
is Vec3Iota -> Either.left(x.vec3)
is ListIota -> {
val out = mutableListOf<Vec3>()
for (v in x.list) {
if (v is Vec3Iota) {
out.add(v.vec3)
} else {
throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "vec_or_veclist")
}
}
Either.right(out)
}
else -> throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "vec_or_veclist")
}
}

fun List<Iota>.getLongOrList(idx: Int, argc: Int = 0): Either<Long, SpellList> {
val datum = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
if (datum is DoubleIota) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public interface Arithmetic {
HexPattern ARCTAN2 = HexPattern.fromAngles("deadeeeeewd", HexDir.WEST);
HexPattern LOG = HexPattern.fromAngles("eqaqe", HexDir.NORTH_WEST);
HexPattern MOD = HexPattern.fromAngles("addwaad", HexDir.NORTH_EAST);
HexPattern FACT = HexPattern.fromAngles("wawdedwaw", HexDir.SOUTH_EAST);


// Vecs
Expand Down
13 changes: 13 additions & 0 deletions Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import at.petrak.hexcasting.api.casting.iota.ListIota
import at.petrak.hexcasting.api.casting.iota.NullIota
import at.petrak.hexcasting.api.casting.math.HexCoord
import at.petrak.hexcasting.api.casting.validateSubIotas
import at.petrak.hexcasting.api.pigment.FrozenPigment
import net.minecraft.ChatFormatting
import net.minecraft.core.HolderLookup
import net.minecraft.core.Registry
Expand All @@ -19,6 +20,7 @@ import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.tags.TagKey
import net.minecraft.util.RandomSource
import net.minecraft.world.InteractionHand
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec2
Expand Down Expand Up @@ -64,6 +66,17 @@ fun vec2FromNBT(tag: LongArray): Vec2 = if (tag.size != 2) Vec2.ZERO else
Double.fromBits(tag[1]).toFloat(),
)

fun FrozenPigment.nextColor(random: RandomSource): Int {
return colorProvider.getColor(
random.nextFloat() * 16384,
Vec3(
random.nextFloat().toDouble(),
random.nextFloat().toDouble(),
random.nextFloat().toDouble()
).scale((random.nextFloat() * 3).toDouble())
)
}

fun otherHand(hand: InteractionHand) =
if (hand == InteractionHand.MAIN_HAND) InteractionHand.OFF_HAND else InteractionHand.MAIN_HAND

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package at.petrak.hexcasting.common.casting.actions.spells

import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.casting.*
import at.petrak.hexcasting.api.casting.castables.SpellAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.core.BlockPos
import net.minecraft.core.particles.BlockParticleOption
import net.minecraft.core.particles.ParticleTypes
import net.minecraft.core.registries.Registries
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.tags.BlockTags
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.item.FallingBlockEntity
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.Tier
import net.minecraft.world.item.Tiers
import net.minecraft.world.item.enchantment.Enchantments
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.FallingBlock
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.Vec3
import kotlin.math.roundToLong

// https://github.com/VazkiiMods/Botania/blob/1.21.1-porting/Xplat/src/main/java/vazkii/botania/common/item/lens/WeightLens.java
object OpFallingBlock : SpellAction {
override val argc = 1

override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result {
val pos = args.getVec3(0, argc)
env.assertVecInRange(pos)

val centered = Vec3.atCenterOf(BlockPos.containing(pos))
return SpellAction.Result(
Spell(pos),
(1.5 * MediaConstants.DUST_UNIT).roundToLong(),
listOf(ParticleSpray.burst(centered, 1.0))
)
}

private data class Spell(val v: Vec3) : RenderedSpell {
override fun cast(env: CastingEnvironment) {
val pos = BlockPos.containing(v)

val blockstate = env.world.getBlockState(pos)
if (!env.canEditBlockAt(pos) || !IXplatAbstractions.INSTANCE.isBreakingAllowed(env.world, pos, blockstate, env.caster))
return

val tier = HexConfig.server().opBreakHarvestLevel()

val stateBelow = env.world.getBlockState(pos.below())

if ((
FallingBlock.isFree(stateBelow)
|| !stateBelow.canOcclude()
|| stateBelow.`is`(BlockTags.SLABS)
)
&& !blockstate.isAir
&& blockstate.getDestroySpeed(env.world, pos) >= 0f // fix being able to break bedrock &c
&& env.world.getBlockEntity(pos) == null
&& IXplatAbstractions.INSTANCE.isCorrectTierForDrops(tier, blockstate)
&& canSilkTouch(env.world, pos, blockstate, tier, env.castingEntity as? ServerPlayer)
) {
val falling: FallingBlockEntity = FallingBlockEntity.fall(env.world, pos, blockstate)
falling.time = 1
env.world.sendParticles(
BlockParticleOption(ParticleTypes.FALLING_DUST, blockstate),
pos.x + 0.5,
pos.y + 0.5,
pos.z + 0.5,
10,
0.45,
0.45,
0.45,
5.0
)
}
}

fun canSilkTouch(level: ServerLevel, pos: BlockPos, state: BlockState, harvestTier: Tier, owner: Entity?): Boolean {
val harvestToolStack: ItemStack = getHarvestToolStack(harvestTier, state)
if (harvestToolStack.isEmpty) {
return false
}
harvestToolStack.enchant(level.holderLookup(Registries.ENCHANTMENT).getOrThrow(Enchantments.SILK_TOUCH), 1)
val drops: List<ItemStack> = Block.getDrops(state, level, pos, null, owner, harvestToolStack)
val blockItem: Item = state.block.asItem()
return drops.any { s -> s.item === blockItem }
}

companion object {
fun getHarvestToolStack(harvestTier: Tier, state: BlockState): ItemStack {
return getTool(harvestTier, state).copy()
}

private fun getTool(harvestTier: Tier, state: BlockState): ItemStack {
if (harvestTier !in HARVEST_TOOLS_BY_LEVEL.keys) return ItemStack.EMPTY
if (!state.requiresCorrectToolForDrops()) {
return HARVEST_TOOLS_BY_LEVEL[harvestTier]!![0]
}
for (tool in HARVEST_TOOLS_BY_LEVEL[harvestTier]!!) {
if (tool.isCorrectToolForDrops(state)) {
return tool
}
}
return ItemStack.EMPTY
}

private val HARVEST_TOOLS_BY_LEVEL: Map<Tier, List<ItemStack>> = mapOf(
Tiers.WOOD to stacks(Items.WOODEN_PICKAXE, Items.WOODEN_AXE, Items.WOODEN_HOE, Items.WOODEN_SHOVEL),
Tiers.STONE to stacks(Items.STONE_PICKAXE, Items.STONE_AXE, Items.STONE_HOE, Items.STONE_SHOVEL),
Tiers.IRON to stacks(Items.IRON_PICKAXE, Items.IRON_AXE, Items.IRON_HOE, Items.IRON_SHOVEL),
Tiers.DIAMOND to stacks(Items.DIAMOND_PICKAXE, Items.DIAMOND_AXE, Items.DIAMOND_HOE, Items.DIAMOND_SHOVEL),
Tiers.NETHERITE to stacks(Items.NETHERITE_PICKAXE, Items.NETHERITE_AXE, Items.NETHERITE_HOE, Items.NETHERITE_SHOVEL)
)

private fun stacks(vararg items: Item): List<ItemStack> {
return items.map { item -> ItemStack(item) }
}
}
}
}
Loading
Loading