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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Added

- Updated to Minecraft 1.21.1 ([#985](https://github.com/FallingColors/HexMod/pull/985)) @SuperKnux @slava110
- Added Neural Fiber, a new endgame material harvested from villagers using a modified mindflaying process ([#1296](https://github.com/FallingColors/HexMod/pull/1296)) @Robotgiggle @Falkory220
- Added Grand Caster Robes, a hex-based armor set with a variety of abilities ([#1296](https://github.com/FallingColors/HexMod/pull/1296)) @Robotgiggle @Falkory220
- Provides defense values midway between iron and diamond
- Provides the scrying lens effect, increased ambit, and a casting cost discount
- Allows you to pan the hex grid to fit in significantly more patterns
- Added Simulate, which causes the next pattern drawn to be simulated (to check for mishaps) rather than executed ([#1194](https://github.com/FallingColors/HexMod/pull/1194)) @Robotgiggle
- Added the `hex_unbreakable` tag for blocks that should be immune to Break Block regardless of the configured mining tier ([#1186](https://github.com/FallingColors/HexMod/pull/1186)) @Robotgiggle @slava110
- Added a new Ancient Cypher hex that impulses nearby items towards the caster ([#1106](https://github.com/FallingColors/HexMod/pull/1106)) @IridescentVoid
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"exhaustion": 0.0,
"message_id": "hexcasting.forgot_to_breathe",
"scaling": "when_caused_by_living_non_player"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"values": [
"hexcasting:overcast"
"hexcasting:overcast",
"hexcasting:forgot_to_breathe"
]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"values": [
"hexcasting:overcast"
"hexcasting:overcast",
"hexcasting:forgot_to_breathe"
]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"values": [
"hexcasting:overcast"
"hexcasting:overcast",
"hexcasting:forgot_to_breathe"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public interface ClientConfigAccess {

boolean clickingTogglesDrawing();

int gridPanMouseButton();

boolean advancedTooltipsShowsIotaNBT();

boolean staticActiveSlates();
Expand All @@ -61,6 +63,7 @@ public interface ClientConfigAccess {
boolean DEFAULT_INVERT_ABACUS_SCROLL = false;
double DEFAULT_GRID_SNAP_THRESHOLD = 0.5;
boolean DEFAULT_CLICKING_TOGGLES_DRAWING = false;
int DEFAULT_GRID_PAN_MOUSE_BUTTON = 1;
boolean DEFAULT_ADVANCED_TOOLTIPS_SHOWS_IOTA_NBT = false;
boolean DEFAULT_STATIC_ACTIVE_SLATES = false;
}
Expand Down
32 changes: 30 additions & 2 deletions Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import at.petrak.hexcasting.api.casting.math.HexCoord
import at.petrak.hexcasting.api.casting.validateSubIotas
import at.petrak.hexcasting.api.mod.HexTags
import com.mojang.datafixers.util.Function6
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.ChatFormatting
import net.minecraft.core.HolderLookup
import net.minecraft.core.Registry
import net.minecraft.nbt.*
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.Style
import net.minecraft.network.codec.ByteBufCodecs
import net.minecraft.network.codec.StreamCodec
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
Expand Down Expand Up @@ -61,14 +65,24 @@ fun vecFromNBT(tag: CompoundTag): Vec3 {
Vec3(tag.getDouble("x"), tag.getDouble("y"), tag.getDouble("z"))
}

fun Vec2.serializeToNBT(): LongArrayTag =
LongArrayTag(longArrayOf(this.x.toDouble().toRawBits(), this.y.toDouble().toRawBits()))
fun Vec2.serializeToNBT(): CompoundTag {
val tag = CompoundTag()
tag.putFloat("x", this.x)
tag.putFloat("y", this.y)
return tag
}

fun vec2FromNBT(tag: LongArray): Vec2 = if (tag.size != 2) Vec2.ZERO else
Vec2(
Double.fromBits(tag[0]).toFloat(),
Double.fromBits(tag[1]).toFloat(),
)
fun vec2FromNBT(tag: CompoundTag): Vec2 {
return if (!tag.contains("x") || !tag.contains("y"))
Vec2.ZERO
else
Vec2(tag.getFloat("x"), tag.getFloat("y"))
}

fun otherHand(hand: InteractionHand) =
if (hand == InteractionHand.MAIN_HAND) InteractionHand.OFF_HAND else InteractionHand.MAIN_HAND
Expand Down Expand Up @@ -333,6 +347,20 @@ fun <T : Iota> validateIotaList(iotaList: TreeList<T>, serverLevel: ServerLevel)
return iotaList.map { validateIota(it, serverLevel) }
}

// why is there not already a codec defined for vec2
@JvmField
val VEC2_CODEC: Codec<Vec2> = RecordCodecBuilder.create<Vec2>({ instance ->
instance.group(
Codec.FLOAT.fieldOf("x").forGetter { it.x },
Codec.FLOAT.fieldOf("y").forGetter { it.y }
).apply(instance, ::Vec2)
}).orElseGet({ Vec2.ZERO })
@JvmField
val VEC2_STREAM_CODEC: StreamCodec<RegistryFriendlyByteBuf, Vec2> = StreamCodec.composite(
ByteBufCodecs.FLOAT, Vec2::x,
ByteBufCodecs.FLOAT, Vec2::y,
::Vec2
)

// vanilla's StreamCodec.composite() only supports up to six fields in 1.21
fun <B, C, T1, T2, T3, T4, T5, T6, T7> compositeCodecSeven(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ public class Keybinds {
CATEGORY
);

public static List<KeyMapping> ALL_BINDS = List.of(spellbookPrev, spellbookNext);
public static KeyMapping gridPanOverride = new KeyMapping(
"key.hexcasting.grid_pan_override",
InputConstants.UNKNOWN.getValue(),
CATEGORY
);

public static List<KeyMapping> ALL_BINDS = List.of(spellbookPrev, spellbookNext, gridPanOverride);

public static void clientTickEnd() {
// because of how mouse scrolling works (scrolling upward moves the page down), a positive
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package at.petrak.hexcasting.client.gui

import at.petrak.hexcasting.api.HexAPI
import at.petrak.hexcasting.api.casting.eval.ExecutionClientView
import at.petrak.hexcasting.api.casting.eval.ResolvedPattern
import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
Expand All @@ -18,16 +19,19 @@ import at.petrak.hexcasting.client.ShiftScrollListener
import at.petrak.hexcasting.client.ktxt.accumulatedScroll
import at.petrak.hexcasting.client.render.*
import at.petrak.hexcasting.client.sound.GridSoundInstance
import at.petrak.hexcasting.common.items.armor.ItemRobes
import at.petrak.hexcasting.common.lib.HexAttributes
import at.petrak.hexcasting.common.lib.HexSounds
import at.petrak.hexcasting.common.lib.hex.HexActions
import at.petrak.hexcasting.common.msgs.MsgNewSpellPatternC2S
import at.petrak.hexcasting.common.msgs.MsgPannedGridC2S
import at.petrak.hexcasting.xplat.IClientXplatAbstractions
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.player.LocalPlayer
import net.minecraft.client.renderer.GameRenderer
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.client.resources.sounds.SoundInstance
Expand All @@ -45,6 +49,7 @@ class GuiSpellcasting constructor(
private var cachedStack: List<Iota>,
private var cachedRavenmind: Iota?,
private var parenCount: Int,
private var panOffset: Vec2,
) : Screen("gui.hexcasting.spellcasting".asTranslatedComponent) {
private var stackDescs: List<FormattedCharSequence> = listOf()
private var parenDescs: List<FormattedCharSequence> = listOf()
Expand All @@ -53,6 +58,11 @@ class GuiSpellcasting constructor(
private var drawState: PatternDrawState = PatternDrawState.BetweenPatterns
private val usedSpots: MutableSet<HexCoord> = HashSet()

private var panningAllowed = false
private var forcePanning = false
private var prevPanOffset = panOffset
private val bgLocation = HexAPI.modLoc("textures/gui/casting_bg.png")

private var ambianceSoundInstance: GridSoundInstance? = null

private val randSrc = SoundInstance.createUnseededRandom()
Expand All @@ -64,6 +74,29 @@ class GuiSpellcasting constructor(
this.calculateIotaDisplays()
}

fun getPanDistance(): Float {
return panOffset.length() / 20
}

fun syncPanOffset() {
if (panOffset != prevPanOffset || ClientTickCounter.ticksInGame % 10 == 0L) {
IClientXplatAbstractions.INSTANCE.sendPacketToServer(MsgPannedGridC2S(panOffset))
prevPanOffset = panOffset
}
}

fun validatePanAbility(player: LocalPlayer) {
panningAllowed = ItemRobes.isWearingFullSet(player)
if (!panningAllowed && panOffset != Vec2.ZERO) {
panOffset = Vec2.ZERO
syncPanOffset()
}
}

fun matchesPanInput(pButton: Int): Boolean {
return forcePanning || pButton == HexConfig.client().gridPanMouseButton()
}

fun recvServerUpdate(info: ExecutionClientView, index: Int) {
if (info.isStackClear) {
this.minecraft?.setScreen(null)
Expand Down Expand Up @@ -129,6 +162,7 @@ class GuiSpellcasting constructor(
if (player != null) {
this.ambianceSoundInstance = GridSoundInstance(player)
soundManager.play(this.ambianceSoundInstance!!)
this.validatePanAbility(player)
}

this.calculateIotaDisplays()
Expand All @@ -141,13 +175,19 @@ class GuiSpellcasting constructor(
val heldItem = player.getItemInHand(handOpenedWith)
if (heldItem.isEmpty || !heldItem.`is`(HexTags.Items.STAVES) || player.getAttributeValue(HexAttributes.FEEBLE_MIND) > 0)
closeForReal()
validatePanAbility(player)
if (this.panningAllowed) {
syncPanOffset()
}
}
}

override fun mouseClicked(mxOut: Double, myOut: Double, pButton: Int): Boolean {
if (super.mouseClicked(mxOut, myOut, pButton)) {
return true
}
if (matchesPanInput(pButton) && this.panningAllowed)
return false
if (HexConfig.client().clickingTogglesDrawing()) {
return if (this.drawState is PatternDrawState.BetweenPatterns)
drawStart(mxOut, myOut)
Expand Down Expand Up @@ -190,14 +230,27 @@ class GuiSpellcasting constructor(
}

override fun mouseDragged(mxOut: Double, myOut: Double, pButton: Int, pDragX: Double, pDragY: Double): Boolean {
if (super.mouseDragged(mxOut, myOut, pButton, pDragX, pDragY)) {
if (super.mouseDragged(mxOut, myOut, pButton, pDragX, pDragY))
return true
if (matchesPanInput(pButton) && this.panningAllowed
&& this.drawState is PatternDrawState.BetweenPatterns) {
return panGrid(pDragX, pDragY)
}
if (HexConfig.client().clickingTogglesDrawing())
return false
return drawMove(mxOut, myOut)
}

private fun panGrid(pDragX: Double, pDragY: Double): Boolean {
val shift = Vec2(pDragX.toFloat(), pDragY.toFloat())
val newOffset = this.panOffset.add(shift)
if (newOffset.lengthSquared() < 900*900)
this.panOffset = newOffset
else
this.panOffset = newOffset.normalized().scale(900f);
return false;
}

private fun drawMove(mxOut: Double, myOut: Double): Boolean {
val mx = Mth.clamp(mxOut, 0.0, this.width.toDouble())
val my = Mth.clamp(myOut, 0.0, this.height.toDouble())
Expand Down Expand Up @@ -270,6 +323,8 @@ class GuiSpellcasting constructor(
}
if (HexConfig.client().clickingTogglesDrawing())
return false
if (matchesPanInput(pButton) && this.panningAllowed)
return false
return drawEnd()
}

Expand Down Expand Up @@ -335,6 +390,18 @@ class GuiSpellcasting constructor(
} else if (Keybinds.spellbookNext.matches(key, scancode)) {
ShiftScrollListener.onScroll(-1.0, false, false)
return true
} else if (Keybinds.gridPanOverride.matches(key, scancode)) {
forcePanning = true
return true
}

return false
}

override fun keyReleased(key: Int, scancode: Int, modifiers: Int): Boolean {
if (Keybinds.gridPanOverride.matches(key, scancode)) {
forcePanning = false
return true
}

return false
Expand All @@ -353,6 +420,12 @@ class GuiSpellcasting constructor(
super.onClose()
}

override fun renderBackground(guiGraphics: GuiGraphics, i: Int, j: Int, f: Float) {
guiGraphics.setColor(1f,1f,1f, (getPanDistance() / 15).coerceAtMost(1f))
renderMenuBackgroundTexture(guiGraphics, bgLocation, 0, 0, 0f, 0f, this.width, this.height)
guiGraphics.setColor(1f, 1f, 1f, 1f)
this.renderBlurredBackground(f)
}

override fun render(graphics: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTick: Float) {
super.render(graphics, pMouseX, pMouseY, pPartialTick)
Expand Down Expand Up @@ -400,12 +473,13 @@ class GuiSpellcasting constructor(

for ((idx, elts) in this.patterns.withIndex()) {
val (pat, origin, valid) = elts
val points = pat.toLines(this.hexSize(), this.coordToPx(origin))
val center = Vec2(graphics.guiWidth() / 2f, graphics.guiHeight() / 2f)
if (points.all{ point -> point.distanceToSqr(center) > center.lengthSquared()+2500 })
continue // don't render the pattern if it's completely offscreen
drawPatternFromPoints(
mat,
pat.toLines(
this.hexSize(),
this.coordToPx(origin)
),
points,
findDupIndices(pat.positions()),
true,
valid.color or (0xC8 shl 24),
Expand Down Expand Up @@ -527,7 +601,7 @@ class GuiSpellcasting constructor(
return (baseScale / scaleModifier).toFloat()
}

fun coordsOffset(): Vec2 = Vec2(this.width.toFloat() * 0.5f, this.height.toFloat() * 0.5f)
fun coordsOffset(): Vec2 = Vec2(this.width.toFloat() * 0.5f, this.height.toFloat() * 0.5f).add(this.panOffset)

fun coordToPx(coord: HexCoord) =
at.petrak.hexcasting.api.utils.coordToPx(coord, this.hexSize(), this.coordsOffset())
Expand All @@ -536,7 +610,7 @@ class GuiSpellcasting constructor(


private sealed class PatternDrawState {
/** We're waiting on the player to right-click again */
/** We're waiting on the player to left-click again */
object BetweenPatterns : PatternDrawState()

/** We just started drawing and haven't drawn the first line yet. */
Expand Down
Loading
Loading