fix conflicts
This commit is contained in:
commit
aecf017b06
20 changed files with 396 additions and 205 deletions
0
Common/logs/latest.log
Normal file
0
Common/logs/latest.log
Normal file
|
@ -34,7 +34,7 @@ public class PatternRegistry {
|
|||
new ConcurrentHashMap<>();
|
||||
|
||||
public static void mapPattern(HexPattern pattern, ResourceLocation id,
|
||||
Action action) throws RegisterPatternException {
|
||||
Action action) throws RegisterPatternException {
|
||||
mapPattern(pattern, id, action, false);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class PatternRegistry {
|
|||
* Associate a given angle signature with a SpellOperator.
|
||||
*/
|
||||
public static void mapPattern(HexPattern pattern, ResourceLocation id, Action action,
|
||||
boolean isPerWorld) throws RegisterPatternException {
|
||||
boolean isPerWorld) throws RegisterPatternException {
|
||||
if (actionLookup.containsKey(id)) {
|
||||
throw new RegisterPatternException("The operator with id `%s` was already registered to: %s", id,
|
||||
actionLookup.get(id));
|
||||
|
@ -83,7 +83,7 @@ public class PatternRegistry {
|
|||
* Internal use only.
|
||||
*/
|
||||
public static Pair<Action, ResourceLocation> matchPatternAndID(HexPattern pat,
|
||||
ServerLevel overworld) throws MishapInvalidPattern {
|
||||
ServerLevel overworld) throws MishapInvalidPattern {
|
||||
// Pipeline:
|
||||
// patterns are registered here every time the game boots
|
||||
// when we try to look
|
||||
|
@ -232,13 +232,13 @@ public class PatternRegistry {
|
|||
|
||||
/**
|
||||
* Maps angle sigs to resource locations and their preferred start dir so we can look them up in the main registry
|
||||
* Save this on the world in case the random algorithm changes.
|
||||
*/
|
||||
public static class Save extends SavedData {
|
||||
private static final String TAG_OP_ID = "op_id";
|
||||
private static final String TAG_START_DIR = "start_dir";
|
||||
|
||||
// TODO: this is slightly weird that we save it *on* the world
|
||||
// might it be better to recalculate it every time the world loads?
|
||||
// Maps hex signatures to (op ids, canonical start dir)
|
||||
private Map<String, Pair<ResourceLocation, HexDir>> lookup;
|
||||
private boolean missingEntries;
|
||||
|
||||
|
@ -279,7 +279,7 @@ public class PatternRegistry {
|
|||
public CompoundTag save(CompoundTag tag) {
|
||||
this.lookup.forEach((sig, rhs) -> {
|
||||
var entry = new CompoundTag();
|
||||
entry.putString(TAG_OP_ID, sig.toString());
|
||||
entry.putString(TAG_OP_ID, rhs.getFirst().toString());
|
||||
entry.putInt(TAG_START_DIR, rhs.getSecond().ordinal());
|
||||
tag.put(sig, entry);
|
||||
});
|
||||
|
|
|
@ -86,12 +86,18 @@ public interface IotaHolderItem {
|
|||
return HexIotaTypes.getColor(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write {@code null} to indicate erasing
|
||||
*/
|
||||
boolean canWrite(ItemStack stack, @Nullable Iota iota);
|
||||
|
||||
/**
|
||||
* Write {@code null} to indicate erasing
|
||||
*/
|
||||
void writeDatum(ItemStack stack, @Nullable Iota iota);
|
||||
|
||||
static void appendHoverText(IotaHolderItem self, ItemStack stack, List<Component> components,
|
||||
TooltipFlag flag) {
|
||||
TooltipFlag flag) {
|
||||
var datumTag = self.readIotaTag(stack);
|
||||
if (datumTag != null) {
|
||||
var cmp = HexIotaTypes.getDisplay(datumTag);
|
||||
|
|
|
@ -8,7 +8,6 @@ import at.petrak.hexcasting.api.utils.TAU
|
|||
import at.petrak.hexcasting.api.utils.getValue
|
||||
import at.petrak.hexcasting.api.utils.setValue
|
||||
import at.petrak.hexcasting.api.utils.weakMapped
|
||||
import at.petrak.hexcasting.client.gui.GuiSpellcasting
|
||||
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepIngredient
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
|
@ -31,19 +30,25 @@ import net.minecraft.world.entity.npc.VillagerProfession
|
|||
import net.minecraft.world.entity.npc.VillagerType
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.levelgen.XoroshiroRandomSource
|
||||
import net.minecraft.world.level.levelgen.synth.PerlinNoise
|
||||
import net.minecraft.world.level.levelgen.SingleThreadedRandomSource
|
||||
import net.minecraft.world.level.levelgen.synth.SimplexNoise
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* Source of perlin noise
|
||||
*/
|
||||
val NOISE: PerlinNoise = PerlinNoise.create(XoroshiroRandomSource(9001L), listOf(0, 1, 2, 3, 4))
|
||||
val NOISE: SimplexNoise = SimplexNoise(SingleThreadedRandomSource(9001L))
|
||||
|
||||
val CAP_THETA: Float = 18f
|
||||
// see the test; perlin noise seems to output almost exclusively between -0.5 and 0.5
|
||||
// i could probably impl this "properly" with some kind of exponent but it's faster and easier to divide
|
||||
fun getNoise(x: Double, y: Double, z: Double): Double =
|
||||
NOISE.getValue(x * 0.6, y * 0.6, z * 0.6) / 2.0
|
||||
|
||||
// how many degrees are between each triangle on the smooth caps of the lines
|
||||
const val CAP_THETA = 180f / 10f
|
||||
const val DEFAULT_READABILITY_OFFSET = 0.2f
|
||||
const val DEFAULT_LAST_SEGMENT_LEN_PROP = 0.8f
|
||||
|
||||
/**
|
||||
* Draw a sequence of linePoints spanning the given points.
|
||||
|
@ -51,12 +56,12 @@ val CAP_THETA: Float = 18f
|
|||
* Please make sure to enable the right asinine shaders; see [GuiSpellcasting]
|
||||
*/
|
||||
fun drawLineSeq(
|
||||
mat: Matrix4f,
|
||||
points: List<Vec2>,
|
||||
width: Float,
|
||||
z: Float,
|
||||
tail: Int,
|
||||
head: Int,
|
||||
mat: Matrix4f,
|
||||
points: List<Vec2>,
|
||||
width: Float,
|
||||
z: Float,
|
||||
tail: Int,
|
||||
head: Int,
|
||||
) {
|
||||
if (points.size <= 1) return
|
||||
|
||||
|
@ -79,24 +84,27 @@ fun drawLineSeq(
|
|||
val n = points.size
|
||||
val joinAngles = FloatArray(n)
|
||||
val joinOffsets = FloatArray(n)
|
||||
for (i in 2..n - 1) {
|
||||
for (i in 2 until n) {
|
||||
val p0 = points[i - 2];
|
||||
val p1 = points[i - 1];
|
||||
val p2 = points[i];
|
||||
val prev = p1.add(p0.negated())
|
||||
val next = p2.add(p1.negated())
|
||||
val angle =
|
||||
Mth.atan2((prev.x * next.y - prev.y * next.x).toDouble(), (prev.x * next.x + prev.y * next.y).toDouble())
|
||||
.toFloat()
|
||||
Mth.atan2((prev.x * next.y - prev.y * next.x).toDouble(), (prev.x * next.x + prev.y * next.y).toDouble())
|
||||
.toFloat()
|
||||
joinAngles[i - 1] = angle
|
||||
val clamp = Math.min(prev.length(), next.length()) / (width * 0.5f);
|
||||
joinOffsets[i - 1] = Mth.clamp(Mth.sin(angle) / (1 + Mth.cos(angle)), -clamp, clamp)
|
||||
}
|
||||
|
||||
fun vertex(color: BlockPos, pos: Vec2) =
|
||||
buf.vertex(mat, pos.x, pos.y, z).color(color.x, color.y, color.z, a).endVertex()
|
||||
for ((i, pair) in points.zipWithNext().withIndex()) {
|
||||
val (p1, p2) = pair
|
||||
buf.vertex(mat, pos.x, pos.y, z).color(color.x, color.y, color.z, a).endVertex()
|
||||
|
||||
buf.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION_COLOR)
|
||||
for (i in 0 until points.size - 1) {
|
||||
val p1 = points[i]
|
||||
val p2 = points[i + 1]
|
||||
// https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L163
|
||||
// GuiComponent::innerFill line 52
|
||||
// fedor have useful variable names challenge (99% can't beat)
|
||||
|
@ -104,22 +112,38 @@ fun drawLineSeq(
|
|||
val normal = Vec2(-tangent.y, tangent.x)
|
||||
|
||||
fun color(time: Float): BlockPos =
|
||||
BlockPos(Mth.lerp(time, r1, r2).toInt(), Mth.lerp(time, g1, g2).toInt(), Mth.lerp(time, b1, b2).toInt())
|
||||
BlockPos(Mth.lerp(time, r1, r2).toInt(), Mth.lerp(time, g1, g2).toInt(), Mth.lerp(time, b1, b2).toInt())
|
||||
|
||||
val color1 = color(i.toFloat() / n)
|
||||
val color2 = color((i + 1f) / n)
|
||||
val jlow = joinOffsets[i]
|
||||
val jhigh = joinOffsets[i + 1]
|
||||
buf.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR)
|
||||
vertex(color1, p1.add(tangent.scale(Math.max(0f, jlow))).add(normal))
|
||||
// Draw the line segment as a hexagon, sort of
|
||||
// I can't imagine what the hell alwinfy is up to but this is implementing what TRIANGLE_FAN does
|
||||
// using normal triangles so we can send the entire segment to the buffer at once
|
||||
val p1Down = p1.add(tangent.scale(Math.max(0f, jlow))).add(normal)
|
||||
val p1Up = p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated())
|
||||
val p2Down = p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal)
|
||||
val p2Up = p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated())
|
||||
|
||||
vertex(color1, p1Down)
|
||||
vertex(color1, p1)
|
||||
vertex(color1, p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated()))
|
||||
vertex(color2, p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated()))
|
||||
vertex(color1, p1Up)
|
||||
|
||||
vertex(color1, p1Down)
|
||||
vertex(color1, p1Up)
|
||||
vertex(color2, p2Up)
|
||||
|
||||
vertex(color1, p1Down)
|
||||
vertex(color2, p2Up)
|
||||
vertex(color2, p2)
|
||||
vertex(color2, p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal))
|
||||
tess.end()
|
||||
|
||||
vertex(color1, p1Down)
|
||||
vertex(color2, p2)
|
||||
vertex(color2, p2Down)
|
||||
|
||||
if (i > 0) {
|
||||
// Draw the connector to the next line segment
|
||||
val sangle = joinAngles[i]
|
||||
val angle = Math.abs(sangle)
|
||||
val rnormal = normal.negated()
|
||||
|
@ -127,22 +151,35 @@ fun drawLineSeq(
|
|||
if (joinSteps < 1) {
|
||||
continue
|
||||
}
|
||||
buf.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR)
|
||||
buf.vertex(mat, p1.x, p1.y, z).color(color1.x, color1.y, color1.z, a).endVertex()
|
||||
|
||||
if (sangle < 0) {
|
||||
for (j in 0..joinSteps) {
|
||||
var prevVert = Vec2(p1.x - rnormal.x, p1.y - rnormal.y)
|
||||
for (j in 1..joinSteps) {
|
||||
val fan = rotate(rnormal, -sangle * (j.toFloat() / joinSteps))
|
||||
buf.vertex(mat, p1.x - fan.x, p1.y - fan.y, z).color(color1.x, color1.y, color1.z, a).endVertex()
|
||||
val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y)
|
||||
|
||||
vertex(color1, p1)
|
||||
vertex(color1, prevVert)
|
||||
vertex(color1, fanShift)
|
||||
prevVert = fanShift
|
||||
}
|
||||
} else {
|
||||
for (j in joinSteps downTo 0) {
|
||||
val startFan = rotate(normal, -sangle)
|
||||
var prevVert = Vec2(p1.x - startFan.x, p1.y - startFan.y)
|
||||
for (j in joinSteps - 1 downTo 0) {
|
||||
val fan = rotate(normal, -sangle * (j.toFloat() / joinSteps))
|
||||
buf.vertex(mat, p1.x - fan.x, p1.y - fan.y, z).color(color1.x, color1.y, color1.z, a).endVertex()
|
||||
val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y)
|
||||
|
||||
vertex(color1, p1)
|
||||
vertex(color1, prevVert)
|
||||
vertex(color1, fanShift)
|
||||
prevVert = fanShift
|
||||
}
|
||||
}
|
||||
tess.end()
|
||||
}
|
||||
}
|
||||
tess.end()
|
||||
|
||||
fun drawCaps(color: BlockPos, point: Vec2, prev: Vec2) {
|
||||
val tangent = point.add(prev.negated()).normalized().scale(0.5f * width)
|
||||
val normal = Vec2(-tangent.y, tangent.x)
|
||||
|
@ -166,19 +203,22 @@ fun rotate(vec: Vec2, theta: Float): Vec2 {
|
|||
}
|
||||
|
||||
/**
|
||||
* * Draw a hex pattern from the given list of non-zappy points (as in, do the *style* of drawing it,
|
||||
* * you have to do the conversion yourself.)
|
||||
* */
|
||||
* Draw a hex pattern from the given list of non-zappy points (as in, do the *style* of drawing it,
|
||||
* you have to do the conversion yourself.)
|
||||
*/
|
||||
fun drawPatternFromPoints(
|
||||
mat: Matrix4f,
|
||||
points: List<Vec2>,
|
||||
dupIndices: Set<Int>?,
|
||||
drawLast: Boolean,
|
||||
tail: Int,
|
||||
head: Int,
|
||||
flowIrregular: Float,
|
||||
mat: Matrix4f,
|
||||
points: List<Vec2>,
|
||||
dupIndices: Set<Int>?,
|
||||
drawLast: Boolean,
|
||||
tail: Int,
|
||||
head: Int,
|
||||
flowIrregular: Float,
|
||||
readabilityOffset: Float,
|
||||
lastSegmentLenProportion: Float,
|
||||
seed: Double
|
||||
) {
|
||||
val zappyPts = makeZappy(points, dupIndices, 10f, 2.5f, 0.1f, flowIrregular)
|
||||
val zappyPts = makeZappy(points, dupIndices, 10, 2.5f, 0.1f, flowIrregular, readabilityOffset, lastSegmentLenProportion, seed)
|
||||
val nodes = if (drawLast) {
|
||||
points
|
||||
} else {
|
||||
|
@ -188,45 +228,36 @@ fun drawPatternFromPoints(
|
|||
drawLineSeq(mat, zappyPts, 2f, 1f, screenCol(tail), screenCol(head))
|
||||
for (node in nodes) {
|
||||
drawSpot(
|
||||
mat,
|
||||
node,
|
||||
2f,
|
||||
dodge(FastColor.ARGB32.red(head)) / 255f,
|
||||
dodge(FastColor.ARGB32.green(head)) / 255f,
|
||||
dodge(FastColor.ARGB32.blue(head)) / 255f,
|
||||
FastColor.ARGB32.alpha(head) / 255f
|
||||
mat,
|
||||
node,
|
||||
2f,
|
||||
dodge(FastColor.ARGB32.red(head)) / 255f,
|
||||
dodge(FastColor.ARGB32.green(head)) / 255f,
|
||||
dodge(FastColor.ARGB32.blue(head)) / 255f,
|
||||
FastColor.ARGB32.alpha(head) / 255f
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fun makeZappy(
|
||||
points: List<Vec2>,
|
||||
dupIndices: Set<Int>?,
|
||||
hops: Float,
|
||||
variance: Float,
|
||||
speed: Float,
|
||||
flowIrregular: Float
|
||||
) =
|
||||
makeZappy(points, dupIndices, hops.toInt(), variance, speed, flowIrregular, 0.2f)
|
||||
|
||||
/**
|
||||
* Split up a sequence of linePoints with a lightning effect
|
||||
* @param hops: rough number of points to subdivide each segment into
|
||||
* @param speed: rate at which the lightning effect should move/shake/etc
|
||||
*/
|
||||
fun makeZappy(
|
||||
barePoints: List<Vec2>, dupIndices: Set<Int>?, hops: Int, variance: Float, speed: Float, flowIrregular: Float,
|
||||
readabilityOffset: Float
|
||||
barePoints: List<Vec2>, dupIndices: Set<Int>?, hops: Int, variance: Float, speed: Float, flowIrregular: Float,
|
||||
readabilityOffset: Float, lastSegmentLenProportion: Float, seed: Double
|
||||
): List<Vec2> {
|
||||
// Nothing in, nothing out
|
||||
if (barePoints.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
fun zappify(points: List<Vec2>): List<Vec2> {
|
||||
fun zappify(points: List<Vec2>, truncateLast: Boolean): List<Vec2> {
|
||||
val scaleVariance = { it: Double -> 1.0.coerceAtMost(8 * (0.5 - abs(0.5 - it))) }
|
||||
val zSeed = ClientTickCounter.getTotal().toDouble() * speed
|
||||
// Create our output list of zap points
|
||||
val zappyPts = mutableListOf(points[0])
|
||||
val zappyPts = ArrayList<Vec2>(points.size * hops)
|
||||
zappyPts.add(points[0])
|
||||
// For each segment in the original...
|
||||
for ((i, pair) in points.zipWithNext().withIndex()) {
|
||||
val (src, target) = pair
|
||||
|
@ -236,30 +267,40 @@ fun makeZappy(
|
|||
// Compute how big the radius of variance should be
|
||||
val maxVariance = hopDist * variance
|
||||
|
||||
for (j in 1..hops) {
|
||||
// for a list of length n, there will be n-1 pairs,
|
||||
// and so the last index will be (n-1)-1
|
||||
val maxJ = if (truncateLast && i == points.size - 2) {
|
||||
(lastSegmentLenProportion * hops.toFloat()).roundToInt()
|
||||
} else hops
|
||||
|
||||
for (j in 1..maxJ) {
|
||||
val progress = j.toDouble() / (hops + 1)
|
||||
// Add the next hop...
|
||||
val pos = src.add(delta.scale(progress.toFloat()))
|
||||
// as well as some random variance...
|
||||
// (We use i, j (segment #, subsegment #) as seeds for the Perlin noise,
|
||||
// and zSeed (i.e. time elapsed) to perturb the shape gradually over time)
|
||||
val minorPerturb = NOISE.getValue(i.toDouble(), j.toDouble(), sin(zSeed)) * flowIrregular
|
||||
val theta = (3 * NOISE.getValue(
|
||||
i.toDouble() + j.toDouble() / (hops + 1) + minorPerturb - zSeed,
|
||||
1337.0,
|
||||
0.0
|
||||
val minorPerturb = getNoise(i.toDouble(), j.toDouble(), sin(zSeed)) * flowIrregular
|
||||
val theta = (3 * getNoise(
|
||||
i + progress + minorPerturb - zSeed,
|
||||
1337.0,
|
||||
seed
|
||||
) * TAU).toFloat()
|
||||
val r = (NOISE.getValue(
|
||||
i.toDouble() + j.toDouble() / (hops + 1) - zSeed,
|
||||
69420.0,
|
||||
0.0
|
||||
val r = (getNoise(
|
||||
i + progress - zSeed,
|
||||
69420.0,
|
||||
seed
|
||||
) * maxVariance * scaleVariance(progress)).toFloat()
|
||||
val randomHop = Vec2(r * Mth.cos(theta), r * Mth.sin(theta))
|
||||
// Then record the new location.
|
||||
zappyPts.add(pos.add(randomHop))
|
||||
|
||||
if (j == hops) {
|
||||
// Finally, we hit the destination, add that too
|
||||
// but we might not hit the destination if we want to stop short
|
||||
zappyPts.add(target)
|
||||
}
|
||||
}
|
||||
// Finally, we hit the destination, add that too
|
||||
zappyPts.add(target)
|
||||
}
|
||||
return zappyPts
|
||||
}
|
||||
|
@ -277,16 +318,16 @@ fun makeZappy(
|
|||
}
|
||||
if (i == barePoints.size - 2) {
|
||||
daisyChain.add(tail)
|
||||
points.addAll(zappify(daisyChain))
|
||||
points.addAll(zappify(daisyChain, true))
|
||||
} else if (dupIndices.contains(i + 1)) {
|
||||
daisyChain.add(tail.add(tangent.negated()))
|
||||
points.addAll(zappify(daisyChain))
|
||||
points.addAll(zappify(daisyChain, false))
|
||||
daisyChain.clear()
|
||||
}
|
||||
}
|
||||
points
|
||||
} else {
|
||||
zappify(barePoints)
|
||||
zappify(barePoints, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,10 +374,10 @@ fun drawSpot(mat: Matrix4f, point: Vec2, radius: Float, r: Float, g: Float, b: F
|
|||
|
||||
fun screenCol(n: Int): Int {
|
||||
return FastColor.ARGB32.color(
|
||||
FastColor.ARGB32.alpha(n),
|
||||
screen(FastColor.ARGB32.red(n)),
|
||||
screen(FastColor.ARGB32.green(n)),
|
||||
screen(FastColor.ARGB32.blue(n)),
|
||||
FastColor.ARGB32.alpha(n),
|
||||
screen(FastColor.ARGB32.red(n)),
|
||||
screen(FastColor.ARGB32.green(n)),
|
||||
screen(FastColor.ARGB32.blue(n)),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -363,7 +404,7 @@ fun getCenteredPattern(pattern: HexPattern, width: Float, height: Float, minSize
|
|||
}
|
||||
}
|
||||
val scale =
|
||||
min(minSize, min(width / 3f / maxDx, height / 3f / maxDy))
|
||||
min(minSize, min(width / 3f / maxDx, height / 3f / maxDy))
|
||||
val com2: Vec2 = pattern.getCenter(scale)
|
||||
val lines2: List<Vec2> = pattern.toLines(scale, com2.negated())
|
||||
return scale to lines2
|
||||
|
@ -388,9 +429,9 @@ private var villager: Villager? by weakMapped(Villager::level)
|
|||
fun prepareVillagerForRendering(ingredient: BrainsweepIngredient, level: Level): Villager {
|
||||
val minLevel: Int = ingredient.minLevel()
|
||||
val profession: VillagerProfession = Registry.VILLAGER_PROFESSION.getOptional(ingredient.profession())
|
||||
.orElse(VillagerProfession.NONE)
|
||||
.orElse(VillagerProfession.NONE)
|
||||
val biome: VillagerType = Registry.VILLAGER_TYPE.getOptional(ingredient.biome())
|
||||
.orElse(VillagerType.PLAINS)
|
||||
.orElse(VillagerType.PLAINS)
|
||||
|
||||
val instantiatedVillager = villager ?: run {
|
||||
val newVillager = Villager(EntityType.VILLAGER, level)
|
||||
|
@ -399,18 +440,18 @@ fun prepareVillagerForRendering(ingredient: BrainsweepIngredient, level: Level):
|
|||
}
|
||||
|
||||
instantiatedVillager.villagerData = instantiatedVillager.villagerData
|
||||
.setProfession(profession)
|
||||
.setType(biome)
|
||||
.setLevel(minLevel)
|
||||
.setProfession(profession)
|
||||
.setType(biome)
|
||||
.setLevel(minLevel)
|
||||
|
||||
return instantiatedVillager
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun renderEntity(
|
||||
ms: PoseStack, entity: Entity, world: Level, x: Float, y: Float, rotation: Float,
|
||||
renderScale: Float, offset: Float,
|
||||
bufferTransformer: (MultiBufferSource) -> MultiBufferSource = { it -> it }
|
||||
ms: PoseStack, entity: Entity, world: Level, x: Float, y: Float, rotation: Float,
|
||||
renderScale: Float, offset: Float,
|
||||
bufferTransformer: (MultiBufferSource) -> MultiBufferSource = { it -> it }
|
||||
) {
|
||||
entity.level = world
|
||||
ms.pushPose()
|
||||
|
@ -432,23 +473,23 @@ fun renderEntity(
|
|||
* Make sure you have the `PositionColorShader` set
|
||||
*/
|
||||
fun renderQuad(
|
||||
ps: PoseStack, x: Float, y: Float, w: Float, h: Float, color: Int
|
||||
ps: PoseStack, x: Float, y: Float, w: Float, h: Float, color: Int
|
||||
) {
|
||||
val mat = ps.last().pose()
|
||||
val tess = Tesselator.getInstance()
|
||||
val buf = tess.builder
|
||||
buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR)
|
||||
buf.vertex(mat, x, y, 0f)
|
||||
.color(color)
|
||||
.endVertex()
|
||||
.color(color)
|
||||
.endVertex()
|
||||
buf.vertex(mat, x, y + h, 0f)
|
||||
.color(color)
|
||||
.endVertex()
|
||||
.color(color)
|
||||
.endVertex()
|
||||
buf.vertex(mat, x + w, y + h, 0f)
|
||||
.color(color)
|
||||
.endVertex()
|
||||
.color(color)
|
||||
.endVertex()
|
||||
buf.vertex(mat, x + w, y, 0f)
|
||||
.color(color)
|
||||
.endVertex()
|
||||
.color(color)
|
||||
.endVertex()
|
||||
tess.end()
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ public class BlockEntityAkashicBookshelfRenderer implements BlockEntityRenderer<
|
|||
|
||||
@Override
|
||||
public void render(BlockEntityAkashicBookshelf tile, float pPartialTick, PoseStack ps,
|
||||
MultiBufferSource buffer, int light, int overlay) {
|
||||
MultiBufferSource buffer, int light, int overlay) {
|
||||
HexPattern pattern = tile.getPattern();
|
||||
if (pattern == null) {
|
||||
return;
|
||||
|
@ -73,7 +73,9 @@ public class BlockEntityAkashicBookshelfRenderer implements BlockEntityRenderer<
|
|||
lines2.set(j, new Vec2(-v.x, v.y));
|
||||
}
|
||||
|
||||
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(pattern.positions()), 10f, 0.5f, 0f, 0f);
|
||||
var stupidHash = tile.getBlockPos().hashCode();
|
||||
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(pattern.positions()), 10, 0.5f, 0f, 0f, 0f,
|
||||
1f, stupidHash);
|
||||
|
||||
int outer = 0xff_d2c8c8;
|
||||
int inner = 0xc8_322b33;
|
||||
|
|
|
@ -22,7 +22,7 @@ public class BlockEntitySlateRenderer implements BlockEntityRenderer<BlockEntity
|
|||
|
||||
@Override
|
||||
public void render(BlockEntitySlate tile, float pPartialTick, PoseStack ps,
|
||||
MultiBufferSource buffer, int light, int overlay) {
|
||||
MultiBufferSource buffer, int light, int overlay) {
|
||||
if (tile.pattern == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -84,7 +84,11 @@ public class BlockEntitySlateRenderer implements BlockEntityRenderer<BlockEntity
|
|||
}
|
||||
|
||||
var isLit = bs.getValue(BlockSlate.ENERGIZED);
|
||||
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(tile.pattern.positions()), 10f, isLit ? 2.5f : 0.5f, isLit ? 0.1f : 0f, 0.2f);
|
||||
var variance = isLit ? 2.5f : 0.5f;
|
||||
var speed = isLit ? 0.1f : 0f;
|
||||
var stupidHash = tile.getBlockPos().hashCode();
|
||||
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(tile.pattern.positions()),
|
||||
10, variance, speed, 0.2f, 0f, 1f, stupidHash);
|
||||
|
||||
int outer = isLit ? 0xff_64c8ff : 0xff_d2c8c8;
|
||||
int inner = isLit ? RenderLib.screenCol(outer) : 0xc8_322b33;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package at.petrak.hexcasting.client.entity;
|
||||
|
||||
import at.petrak.hexcasting.client.RenderLib;
|
||||
import at.petrak.hexcasting.common.entities.EntityWallScroll;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@ -38,7 +39,7 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
|
|||
// I do as the PaintingRenderer guides
|
||||
@Override
|
||||
public void render(EntityWallScroll wallScroll, float yaw, float partialTicks, PoseStack ps,
|
||||
MultiBufferSource bufSource, int packedLight) {
|
||||
MultiBufferSource bufSource, int packedLight) {
|
||||
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
|
||||
|
@ -157,8 +158,8 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
|
|||
}
|
||||
|
||||
private static void vertex(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, float x, float y,
|
||||
float z, float u,
|
||||
float v, float nx, float ny, float nz) {
|
||||
float z, float u,
|
||||
float v, float nx, float ny, float nz) {
|
||||
verts.vertex(mat, x, y, z)
|
||||
.color(0xffffffff)
|
||||
.uv(u, v).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(light)
|
||||
|
@ -166,82 +167,136 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
|
|||
.endVertex();
|
||||
}
|
||||
|
||||
private static void vertexCol(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, int col, float x,
|
||||
float y) {
|
||||
verts.vertex(mat, -x, y, 0)
|
||||
private static void vertexCol(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, int col, Vec2 pos) {
|
||||
verts.vertex(mat, -pos.x, pos.y, 0)
|
||||
.color(col)
|
||||
.uv(0, 0).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(light)
|
||||
.normal(normal, 0, 0, 1)
|
||||
.endVertex();
|
||||
}
|
||||
|
||||
private static void theCoolerDrawLineSeq(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts,
|
||||
List<Vec2> points, float width, int color
|
||||
private static void theCoolerDrawLineSeq(Matrix4f mat, Matrix3f normalMat, int light, VertexConsumer verts,
|
||||
List<Vec2> points, float width, int color
|
||||
) {
|
||||
if (points.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
float prevXHi, prevYHi, prevXLo, prevYLo;
|
||||
{
|
||||
var p1 = points.get(0);
|
||||
var p2 = points.get(1);
|
||||
|
||||
var dx = p2.x - p1.x;
|
||||
var dy = p2.y - p1.y;
|
||||
var nx = -dy;
|
||||
var ny = dx;
|
||||
var tlen = Mth.sqrt(nx * nx + ny * ny) / (width * 0.5f);
|
||||
var tx = nx / tlen;
|
||||
var ty = ny / tlen;
|
||||
|
||||
prevXHi = p1.x - tx;
|
||||
prevYHi = p1.y - ty;
|
||||
prevXLo = p1.x + tx;
|
||||
prevYLo = p1.y + ty;
|
||||
// TODO: abstract some of this out with RenderLib to stop WET code
|
||||
var joinAngles = new float[points.size()];
|
||||
var joinOffsets = new float[points.size()];
|
||||
for (int i = 2; i < points.size(); i++) {
|
||||
var p0 = points.get(i - 2);
|
||||
var p1 = points.get(i - 1);
|
||||
var p2 = points.get(i);
|
||||
var prev = p1.add(p0.negated());
|
||||
var next = p2.add(p1.negated());
|
||||
var angle = (float) Mth.atan2(
|
||||
prev.x * next.y - prev.y * next.x,
|
||||
prev.x * next.x + prev.y * next.y);
|
||||
joinAngles[i - 1] = angle;
|
||||
var clamp = Math.min(prev.length(), next.length()) / (width * 0.5f);
|
||||
joinOffsets[i - 1] = Mth.clamp(Mth.sin(angle) / (1 + Mth.cos(angle)), -clamp, clamp);
|
||||
}
|
||||
|
||||
for (var i = 0; i < points.size() - 1; i++) {
|
||||
var p1 = points.get(i);
|
||||
var p2 = points.get(i + 1);
|
||||
|
||||
var dx = p2.x - p1.x;
|
||||
var dy = p2.y - p1.y;
|
||||
var nx = -dy;
|
||||
var ny = dx;
|
||||
var tlen = Mth.sqrt(nx * nx + ny * ny) / (width * 0.5f);
|
||||
var tx = nx / tlen;
|
||||
var ty = ny / tlen;
|
||||
var tangent = p2.add(p1.negated()).normalized().scale(width * 0.5f);
|
||||
var normal = new Vec2(-tangent.y, tangent.x);
|
||||
|
||||
var xHi = p2.x - tx;
|
||||
var yHi = p2.y - ty;
|
||||
var xLo = p2.x + tx;
|
||||
var yLo = p2.y + ty;
|
||||
vertexCol(mat, normal, light, verts, color, prevXHi, prevYHi);
|
||||
vertexCol(mat, normal, light, verts, color, prevXLo, prevYLo);
|
||||
vertexCol(mat, normal, light, verts, color, xLo, yLo);
|
||||
vertexCol(mat, normal, light, verts, color, xHi, yHi);
|
||||
var jlow = joinOffsets[i];
|
||||
var jhigh = joinOffsets[i + 1];
|
||||
|
||||
prevXHi = xHi;
|
||||
prevYHi = yHi;
|
||||
prevXLo = xLo;
|
||||
prevYLo = yLo;
|
||||
var p1Down = p1.add(tangent.scale(Math.max(0f, jlow))).add(normal);
|
||||
var p1Up = p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated());
|
||||
var p2Down = p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal);
|
||||
var p2Up = p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated());
|
||||
|
||||
// Draw the chamfer hexagon as two trapezoids
|
||||
// the points are in different orders to keep clockwise
|
||||
vertexCol(mat, normalMat, light, verts, color, p1);
|
||||
vertexCol(mat, normalMat, light, verts, color, p2);
|
||||
vertexCol(mat, normalMat, light, verts, color, p2Up);
|
||||
vertexCol(mat, normalMat, light, verts, color, p1Up);
|
||||
|
||||
vertexCol(mat, normalMat, light, verts, color, p1);
|
||||
vertexCol(mat, normalMat, light, verts, color, p1Down);
|
||||
vertexCol(mat, normalMat, light, verts, color, p2Down);
|
||||
vertexCol(mat, normalMat, light, verts, color, p2);
|
||||
|
||||
if (i > 0) {
|
||||
var sangle = joinAngles[i];
|
||||
var angle = Math.abs(sangle);
|
||||
var rnormal = normal.negated();
|
||||
var joinSteps = Mth.ceil(angle * 180 / (RenderLib.CAP_THETA * Mth.PI));
|
||||
if (joinSteps < 1) continue;
|
||||
|
||||
if (sangle < 0) {
|
||||
var prevVert = new Vec2(p1.x - rnormal.x, p1.y - rnormal.y);
|
||||
for (var j = 1; j <= joinSteps; j++) {
|
||||
var fan = RenderLib.rotate(rnormal, -sangle * ((float) j / joinSteps));
|
||||
var fanShift = new Vec2(p1.x - fan.x, p1.y - fan.y);
|
||||
|
||||
vertexCol(mat, normalMat, light, verts, color, p1);
|
||||
vertexCol(mat, normalMat, light, verts, color, p1);
|
||||
vertexCol(mat, normalMat, light, verts, color, fanShift);
|
||||
vertexCol(mat, normalMat, light, verts, color, prevVert);
|
||||
prevVert = fanShift;
|
||||
}
|
||||
} else {
|
||||
var startFan = RenderLib.rotate(normal, -sangle);
|
||||
var prevVert = new Vec2(p1.x - startFan.x, p1.y - startFan.y);
|
||||
for (var j = joinSteps - 1; j >= 0; j--) {
|
||||
var fan = RenderLib.rotate(normal, -sangle * ((float) j / joinSteps));
|
||||
var fanShift = new Vec2(p1.x - fan.x, p1.y - fan.y);
|
||||
|
||||
vertexCol(mat, normalMat, light, verts, color, p1);
|
||||
vertexCol(mat, normalMat, light, verts, color, p1);
|
||||
vertexCol(mat, normalMat, light, verts, color, fanShift);
|
||||
vertexCol(mat, normalMat, light, verts, color, prevVert);
|
||||
prevVert = fanShift;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var pair : new Vec2[][]{
|
||||
{points.get(0), points.get(1)},
|
||||
{points.get(points.size() - 1), points.get(points.size() - 2)}
|
||||
}) {
|
||||
var point = pair[0];
|
||||
var prev = pair[1];
|
||||
|
||||
var tangent = point.add(prev.negated()).normalized().scale(0.5f * width);
|
||||
var normal = new Vec2(-tangent.y, tangent.x);
|
||||
var joinSteps = Mth.ceil(180f / RenderLib.CAP_THETA);
|
||||
for (int j = joinSteps; j > 0; j--) {
|
||||
var fan0 = RenderLib.rotate(normal, -Mth.PI * ((float) j / joinSteps));
|
||||
var fan1 = RenderLib.rotate(normal, -Mth.PI * ((float) (j - 1) / joinSteps));
|
||||
|
||||
vertexCol(mat, normalMat, light, verts, color, point);
|
||||
vertexCol(mat, normalMat, light, verts, color, point);
|
||||
vertexCol(mat, normalMat, light, verts, color, point.add(fan1));
|
||||
vertexCol(mat, normalMat, light, verts, color, point.add(fan0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void theCoolerDrawSpot(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts,
|
||||
Vec2 point, float radius, int color) {
|
||||
Vec2 point, float radius, int color) {
|
||||
var fracOfCircle = 6;
|
||||
for (int i = 0; i < fracOfCircle; i++) {
|
||||
// We do need rects, irritatingly
|
||||
// so we do fake triangles
|
||||
vertexCol(mat, normal, light, verts, color, point.x, point.y);
|
||||
vertexCol(mat, normal, light, verts, color, point.x, point.y);
|
||||
vertexCol(mat, normal, light, verts, color, point);
|
||||
vertexCol(mat, normal, light, verts, color, point);
|
||||
for (int j = 0; j <= 1; j++) {
|
||||
var theta = (i - j) / (float) fracOfCircle * Mth.TWO_PI;
|
||||
var rx = Mth.cos(theta) * radius + point.x;
|
||||
var ry = Mth.sin(theta) * radius + point.y;
|
||||
vertexCol(mat, normal, light, verts, color, rx, ry);
|
||||
vertexCol(mat, normal, light, verts, color, new Vec2(rx, ry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ class GuiSpellcasting constructor(
|
|||
// Well, we never managed to get anything on the stack this go-around.
|
||||
this.drawState = PatternDrawState.BetweenPatterns
|
||||
}
|
||||
|
||||
is PatternDrawState.Drawing -> {
|
||||
val (start, _, pat) = this.drawState as PatternDrawState.Drawing
|
||||
this.drawState = PatternDrawState.BetweenPatterns
|
||||
|
@ -325,7 +326,8 @@ class GuiSpellcasting constructor(
|
|||
}
|
||||
RenderSystem.defaultBlendFunc()
|
||||
|
||||
for ((pat, origin, valid) in this.patterns) {
|
||||
for ((idx, elts) in this.patterns.withIndex()) {
|
||||
val (pat, origin, valid) = elts
|
||||
drawPatternFromPoints(
|
||||
mat,
|
||||
pat.toLines(
|
||||
|
@ -336,7 +338,10 @@ class GuiSpellcasting constructor(
|
|||
true,
|
||||
valid.color or (0xC8 shl 24),
|
||||
valid.fadeColor or (0xC8 shl 24),
|
||||
if (valid.success) 0.2f else 0.9f
|
||||
if (valid.success) 0.2f else 0.9f,
|
||||
DEFAULT_READABILITY_OFFSET,
|
||||
1f,
|
||||
idx.toDouble()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -358,7 +363,17 @@ class GuiSpellcasting constructor(
|
|||
}
|
||||
|
||||
points.add(mousePos)
|
||||
drawPatternFromPoints(mat, points, dupIndices, false, 0xff_64c8ff_u.toInt(), 0xff_fecbe6_u.toInt(), 0.1f)
|
||||
// Use the size of the patterns as the seed so that way when this one is added the zappies don't jump
|
||||
drawPatternFromPoints(mat,
|
||||
points,
|
||||
dupIndices,
|
||||
false,
|
||||
0xff_64c8ff_u.toInt(),
|
||||
0xff_fecbe6_u.toInt(),
|
||||
0.1f,
|
||||
DEFAULT_READABILITY_OFFSET,
|
||||
1f,
|
||||
this.patterns.size.toDouble())
|
||||
}
|
||||
|
||||
RenderSystem.enableDepthTest()
|
||||
|
|
|
@ -32,8 +32,7 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
|
|||
public static final ResourceLocation ANCIENT_BG = modLoc("textures/gui/scroll_ancient.png");
|
||||
public static final ResourceLocation SLATE_BG = modLoc("textures/gui/slate.png");
|
||||
|
||||
private static final float RENDER_SIZE = 72f;
|
||||
private static final float TEXTURE_SIZE = 48f;
|
||||
private static final float RENDER_SIZE = 128f;
|
||||
|
||||
private final HexPattern pattern;
|
||||
private final List<Vec2> zappyPoints;
|
||||
|
@ -45,10 +44,13 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
|
|||
this.pattern = tt.pattern();
|
||||
this.background = tt.background();
|
||||
|
||||
var pair = RenderLib.getCenteredPattern(pattern, RENDER_SIZE, RENDER_SIZE, 8f);
|
||||
var pair = RenderLib.getCenteredPattern(pattern, RENDER_SIZE, RENDER_SIZE, 16f);
|
||||
this.scale = pair.getFirst();
|
||||
var dots = pair.getSecond();
|
||||
this.zappyPoints = RenderLib.makeZappy(dots, RenderLib.findDupIndices(pattern.positions()), 10f, 0.8f, 0f, 0f);
|
||||
this.zappyPoints = RenderLib.makeZappy(
|
||||
dots, RenderLib.findDupIndices(pattern.positions()),
|
||||
10, 0.8f, 0f, 0f, RenderLib.DEFAULT_READABILITY_OFFSET, RenderLib.DEFAULT_LAST_SEGMENT_LEN_PROP,
|
||||
0.0);
|
||||
this.pathfinderDots = dots.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
@ -79,17 +81,17 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
|
|||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
RenderSystem.disableCull();
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA,
|
||||
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
ps.translate(width / 2f, height / 2f, 1);
|
||||
|
||||
var mat = ps.last().pose();
|
||||
var outer = 0xff_d2c8c8;
|
||||
var innerLight = 0xc8_aba2a2;
|
||||
var innerDark = 0xc8_322b33;
|
||||
RenderLib.drawLineSeq(mat, this.zappyPoints, 5f, 0,
|
||||
outer, outer);
|
||||
RenderLib.drawLineSeq(mat, this.zappyPoints, 2f, 0,
|
||||
innerDark, innerLight);
|
||||
RenderLib.drawLineSeq(mat, this.zappyPoints, 6f, 0,
|
||||
outer, outer);
|
||||
RenderLib.drawLineSeq(mat, this.zappyPoints, 6f * 0.4f, 0,
|
||||
innerDark, innerLight);
|
||||
RenderLib.drawSpot(mat, this.zappyPoints.get(0), 2.5f, 1f, 0.1f, 0.15f, 0.6f);
|
||||
|
||||
for (var dot : this.pathfinderDots) {
|
||||
|
@ -104,7 +106,8 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
|
|||
RenderSystem.setShaderTexture(0, background);
|
||||
// x y blitoffset sw sh w h ... ?
|
||||
// parchment doesn't have this mapped
|
||||
GuiComponent.blit(ps, 0, 0, blitOffset, 0f, 0f, (int) RENDER_SIZE, (int) RENDER_SIZE, (int) RENDER_SIZE, (int) RENDER_SIZE);
|
||||
GuiComponent.blit(ps, 0, 0, blitOffset, 0f, 0f, (int) RENDER_SIZE, (int) RENDER_SIZE, (int) RENDER_SIZE,
|
||||
(int) RENDER_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -53,7 +53,7 @@ public class EntityWallScroll extends HangingEntity {
|
|||
}
|
||||
|
||||
public EntityWallScroll(Level world, BlockPos pos, Direction dir, ItemStack scroll, boolean showStrokeOrder,
|
||||
int blockSize) {
|
||||
int blockSize) {
|
||||
super(HexEntities.WALL_SCROLL, world, pos);
|
||||
this.setDirection(dir);
|
||||
this.blockSize = blockSize;
|
||||
|
@ -72,8 +72,10 @@ public class EntityWallScroll extends HangingEntity {
|
|||
var pair = RenderLib.getCenteredPattern(pattern, 128f / 3 * blockSize, 128f / 3 * blockSize,
|
||||
16f / 3 * blockSize);
|
||||
var dots = pair.getSecond();
|
||||
var readOffset = this.getShowsStrokeOrder() ? RenderLib.DEFAULT_READABILITY_OFFSET : 0f;
|
||||
var lastProp = this.getShowsStrokeOrder() ? RenderLib.DEFAULT_LAST_SEGMENT_LEN_PROP : 1f;
|
||||
this.zappyPoints = RenderLib.makeZappy(dots, RenderLib.findDupIndices(pattern.positions()), 10, 0.4f,
|
||||
0f, 0f, this.getShowsStrokeOrder() ? 0.2f : 0f);
|
||||
0f, 0f, readOffset, lastProp, this.getId());
|
||||
}
|
||||
|
||||
this.isAncient = NBTHelper.hasString(scroll, ItemScroll.TAG_OP_ID);
|
||||
|
@ -158,7 +160,7 @@ public class EntityWallScroll extends HangingEntity {
|
|||
}
|
||||
|
||||
public void readSpawnData(BlockPos pos, Direction dir, ItemStack scrollItem,
|
||||
boolean showsStrokeOrder, int blockSize) {
|
||||
boolean showsStrokeOrder, int blockSize) {
|
||||
this.pos = pos;
|
||||
this.scroll = scrollItem;
|
||||
this.blockSize = blockSize;
|
||||
|
@ -201,7 +203,7 @@ public class EntityWallScroll extends HangingEntity {
|
|||
|
||||
@Override
|
||||
public void lerpTo(double pX, double pY, double pZ, float pYaw, float pPitch, int pPosRotationIncrements,
|
||||
boolean pTeleport) {
|
||||
boolean pTeleport) {
|
||||
BlockPos blockpos = this.pos.offset(pX - this.getX(), pY - this.getY(), pZ - this.getZ());
|
||||
this.setPos(blockpos.getX(), blockpos.getY(), blockpos.getZ());
|
||||
}
|
||||
|
|
|
@ -86,7 +86,10 @@ public class ItemSlate extends BlockItem implements IotaHolderItem {
|
|||
|
||||
@Override
|
||||
public boolean canWrite(ItemStack stack, Iota datum) {
|
||||
return datum instanceof PatternIota && !NBTHelper.hasCompound(stack, BlockEntitySlate.TAG_PATTERN);
|
||||
var isWritten = NBTHelper.hasCompound(stack, "BlockEntityTag")
|
||||
&& stack.getTag().getCompound("BlockEntityTag").contains(BlockEntitySlate.TAG_PATTERN);
|
||||
return (datum instanceof PatternIota && !isWritten)
|
||||
|| (datum == null && isWritten);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,6 +2,7 @@ package at.petrak.hexcasting.interop.patchouli;
|
|||
|
||||
import at.petrak.hexcasting.api.spell.math.HexCoord;
|
||||
import at.petrak.hexcasting.api.spell.math.HexPattern;
|
||||
import at.petrak.hexcasting.client.RenderLib;
|
||||
import at.petrak.hexcasting.interop.utils.PatternDrawingUtil;
|
||||
import at.petrak.hexcasting.interop.utils.PatternEntry;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@ -22,7 +23,7 @@ abstract public class AbstractPatternComponent implements ICustomComponent {
|
|||
protected transient float hexSize;
|
||||
|
||||
private transient List<PatternEntry> patterns;
|
||||
private transient List<Vec2> pathfinderDots;
|
||||
private transient List<Vec2> zappyPoints;
|
||||
|
||||
/**
|
||||
* Pass -1, -1 to center it.
|
||||
|
@ -39,17 +40,20 @@ abstract public class AbstractPatternComponent implements ICustomComponent {
|
|||
|
||||
@Override
|
||||
public void render(PoseStack poseStack, IComponentRenderContext ctx, float partialTicks, int mouseX, int mouseY) {
|
||||
PatternDrawingUtil.drawPattern(poseStack, this.x, this.y, this.patterns, this.pathfinderDots,
|
||||
this.showStrokeOrder(), ctx.getTicksInBook(),
|
||||
PatternDrawingUtil.drawPattern(poseStack, this.x, this.y, this.patterns, this.zappyPoints,
|
||||
this.showStrokeOrder(),
|
||||
0xff_d2c8c8, 0xc8_aba2a2, 0xc8_322b33, 0x80_d1cccc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVariablesAvailable(UnaryOperator<IVariable> lookup) {
|
||||
var data = PatternDrawingUtil.loadPatterns(this.getPatterns(lookup));
|
||||
var data = PatternDrawingUtil.loadPatterns(
|
||||
this.getPatterns(lookup),
|
||||
this.showStrokeOrder() ? RenderLib.DEFAULT_READABILITY_OFFSET : 0f,
|
||||
this.showStrokeOrder() ? RenderLib.DEFAULT_LAST_SEGMENT_LEN_PROP : 1f);
|
||||
this.hexSize = data.hexSize();
|
||||
this.patterns = data.patterns();
|
||||
this.pathfinderDots = data.pathfinderDots();
|
||||
this.zappyPoints = data.pathfinderDots();
|
||||
}
|
||||
|
||||
protected static class RawPattern {
|
||||
|
|
|
@ -19,7 +19,8 @@ import java.util.List;
|
|||
|
||||
public final class PatternDrawingUtil {
|
||||
public static void drawPattern(PoseStack poseStack, int x, int y, List<PatternEntry> patterns, List<Vec2> dots,
|
||||
boolean strokeOrder, long animTicks, int outer, int innerLight, int innerDark, int dotColor) {
|
||||
boolean strokeOrder, int outer, int innerLight, int innerDark,
|
||||
int dotColor) {
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(x, y, 1);
|
||||
var mat = poseStack.last().pose();
|
||||
|
@ -59,7 +60,8 @@ public final class PatternDrawingUtil {
|
|||
poseStack.popPose();
|
||||
}
|
||||
|
||||
public static PatternRenderingData loadPatterns(List<Pair<HexPattern, HexCoord>> patterns) {
|
||||
public static PatternRenderingData loadPatterns(List<Pair<HexPattern, HexCoord>> patterns,
|
||||
float readabilityOffset, float lastLineLenProp) {
|
||||
var patternEntries = new ArrayList<PatternEntry>(patterns.size());
|
||||
|
||||
var fakeScale = 1;
|
||||
|
@ -103,12 +105,13 @@ public final class PatternDrawingUtil {
|
|||
var realCom = HexUtils.findCenter(seenRealPoints);
|
||||
|
||||
// and NOW for real!
|
||||
for (var pat : patternEntries) {
|
||||
for (int i = 0; i < patternEntries.size(); i++) {
|
||||
PatternEntry pat = patternEntries.get(i);
|
||||
var localOrigin = HexUtils.coordToPx(pat.origin(), hexSize, realCom.negated());
|
||||
var points = pat.pattern().toLines(hexSize, localOrigin);
|
||||
pat.zappyPoints()
|
||||
.addAll(RenderLib.makeZappy(points, RenderLib.findDupIndices(pat.pattern().positions()), 10f, 0.8f, 0f,
|
||||
0f));
|
||||
.addAll(RenderLib.makeZappy(points, RenderLib.findDupIndices(pat.pattern().positions()), 10, 0.8f, 0f,
|
||||
0f, readabilityOffset, lastLineLenProp, i));
|
||||
}
|
||||
|
||||
var pathfinderDots = seenCoords.stream()
|
||||
|
|
|
@ -270,7 +270,7 @@
|
|||
"hexcasting.spell.book.hexcasting:const/vec/x": "Vector Rfln. +X/-X",
|
||||
"hexcasting.spell.book.hexcasting:const/vec/y": "Vector Rfln. +Y/-Y",
|
||||
"hexcasting.spell.book.hexcasting:const/vec/z": "Vector Rfln. +Z/-Z",
|
||||
"hexcasting.spell.book.hexcasting:write/entity": "Chronicler's Prfn.",
|
||||
"hexcasting.spell.book.hexcasting:read/entity": "Chronicler's Prfn.",
|
||||
"hexcasting.spell.book.hexcasting:number": "Numerical Reflection",
|
||||
"hexcasting.spell.book.hexcasting:mask": "Bookkeeper's Gambit",
|
||||
|
||||
|
@ -340,7 +340,7 @@
|
|||
"hexcasting.spell.hexcasting:rotate": "Rotation Gambit",
|
||||
"hexcasting.spell.hexcasting:rotate_reverse": "Rotation Gambit II",
|
||||
"hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition",
|
||||
"hexcasting.spell.hexcasting:over": "Prospecter's Gambit",
|
||||
"hexcasting.spell.hexcasting:over": "Prospector's Gambit",
|
||||
"hexcasting.spell.hexcasting:tuck": "Undertaker's Gambit",
|
||||
"hexcasting.spell.hexcasting:2dup": "Dioscuri Gambit",
|
||||
"hexcasting.spell.hexcasting:duplicate_n": "Gemini Gambit",
|
||||
|
|
|
@ -270,7 +270,7 @@
|
|||
"hexcasting.spell.book.hexcasting:const/vec/x": "向量之精思,+X/-X型",
|
||||
"hexcasting.spell.book.hexcasting:const/vec/y": "向量之精思,+Y/-Y型",
|
||||
"hexcasting.spell.book.hexcasting:const/vec/z": "向量之精思,+Z/-Z型",
|
||||
"hexcasting.spell.book.hexcasting:write/entity": "编年史家之策略",
|
||||
"hexcasting.spell.book.hexcasting:read/entity": "编年史家之纯化",
|
||||
"hexcasting.spell.book.hexcasting:number": "数字之精思",
|
||||
"hexcasting.spell.book.hexcasting:mask": "簿记员之策略",
|
||||
|
||||
|
@ -336,12 +336,17 @@
|
|||
"hexcasting.spell.hexcasting:zone_entity/not_player": "区域之馏化:非玩家",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_living": "区域之馏化:非生物",
|
||||
|
||||
"hexcasting.spell.hexcasting:duplicate": "双子之分解",
|
||||
"hexcasting.spell.hexcasting:duplicate_n": "双子之策略",
|
||||
"hexcasting.spell.hexcasting:over": "狄俄斯库里之策略",
|
||||
"hexcasting.spell.hexcasting:stack_len": "群体之精思",
|
||||
"hexcasting.spell.hexcasting:swap": "弄臣之策略",
|
||||
"hexcasting.spell.hexcasting:rotate": "轮换之策略",
|
||||
"hexcasting.spell.hexcasting:rotate_reverse": "轮换之策略,第二型",
|
||||
"hexcasting.spell.hexcasting:duplicate": "双子之分解",
|
||||
"hexcasting.spell.hexcasting:over": "勘探者之策略",
|
||||
"hexcasting.spell.hexcasting:tuck": "送葬者之策略",
|
||||
"hexcasting.spell.hexcasting:2dup": "狄俄斯库里之策略",
|
||||
"hexcasting.spell.hexcasting:duplicate_n": "双子之策略",
|
||||
"hexcasting.spell.hexcasting:stack_len": "群体之精思",
|
||||
"hexcasting.spell.hexcasting:fisherman": "渔夫之策略",
|
||||
"hexcasting.spell.hexcasting:fisherman/copy": "渔夫之策略,第二型",
|
||||
"hexcasting.spell.hexcasting:swizzle": "骗徒之策略",
|
||||
|
||||
"hexcasting.spell.hexcasting:and_bit": "交叉之馏化",
|
||||
|
@ -897,10 +902,15 @@
|
|||
"hexcasting.page.stackmanip.pseudo-novice": "移除栈顶的 iota。",
|
||||
"hexcasting.page.stackmanip.duplicate": "复制栈顶的 iota。",
|
||||
"hexcasting.page.stackmanip.swap": "交换栈顶两个 iota 的位置。",
|
||||
"hexcasting.page.stackmanip.rotate": "将栈顶往下第三元素拉至栈顶。[0, 1, 2] 变为 [1, 2, 0]。",
|
||||
"hexcasting.page.stackmanip.over": "将栈顶往下第二元素复制至栈顶。[0, 1] 变为 [0, 1, 0]。",
|
||||
"hexcasting.page.stackmanip.rotate": "将栈顶往下第三元素拉至栈顶。[0, 1, 2] 变为 [1, 2, 0]。",
|
||||
"hexcasting.page.stackmanip.rotate_reverse": "将栈顶元素沉至栈顶往下第三位处。[0, 1, 2] 变为 [2, 0, 1]。",
|
||||
"hexcasting.page.stackmanip.over": "将栈顶往下第二元素复制至栈顶。[0, 1] 变为 [0, 1, 0]。",
|
||||
"hexcasting.page.stackmanip.tuck": "将栈底元素复制至栈顶往下第二元素下方。[0, 1] 变为 [1, 0, 1]。",
|
||||
"hexcasting.page.stackmanip.2dup": "复制栈顶的两个 iota。[0, 1] 变为 [0, 1, 0, 1]。",
|
||||
"hexcasting.page.stackmanip.duplicate_n": "移除栈顶的数,然后将现在的栈顶元素复制该数次。(若所给数为 2,则栈顶会有两个同一元素。)",
|
||||
"hexcasting.page.stackmanip.fisherman": "提出下标为所给数的元素并将其置于栈顶。",
|
||||
"hexcasting.page.stackmanip.fisherman/copy": "与$(action)渔夫之策略/$类似,但会复制 iota 而非将其提出。",
|
||||
"hexcasting.page.stackmanip.stack_len": "以数的形式压入栈中元素的个数。(例如,一个形如 [0, 1] 的栈会变为 [0, 1, 2]。)",
|
||||
"hexcasting.page.stackmanip.last_n_list": "移除$(italic)所给数/$个元素,然后压入一个由其组成的列表。",
|
||||
"hexcasting.page.stackmanip.splat": "移除栈顶的列表,然后依次压入其元素。",
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:write/entity",
|
||||
"anchor": "hexcasting:write/entity",
|
||||
"input": "any, entity",
|
||||
"input": "entity, any",
|
||||
"output": "",
|
||||
"text": "hexcasting.page.readwrite.write/entity"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import net.minecraft.world.level.levelgen.SingleThreadedRandomSource;
|
||||
import net.minecraft.world.level.levelgen.synth.PerlinNoise;
|
||||
import net.minecraft.world.level.levelgen.synth.SimplexNoise;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WhatRangeDoTheNoisesOutputAnywaysTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4));
|
||||
var simplex = new SimplexNoise(new SingleThreadedRandomSource(12345));
|
||||
|
||||
System.out.println("Perlin:");
|
||||
for (int i = 0; i < 20; i++) {
|
||||
System.out.printf(" %f%n", perlin.getValue(i / 10.0, 69420.0, 1337.0));
|
||||
}
|
||||
|
||||
System.out.println("Simplex:");
|
||||
for (int i = 0; i < 20; i++) {
|
||||
System.out.printf(" %f%n", simplex.getValue(i / 10.0, 69420.0, 1337.0));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void perlinBounds() {
|
||||
var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4));
|
||||
var min = Double.POSITIVE_INFINITY;
|
||||
var max = Double.NEGATIVE_INFINITY;
|
||||
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
var it = perlin.getValue(i / 10.0, 12345.0, 7604.0);
|
||||
min = Math.min(min, it);
|
||||
max = Math.max(max, it);
|
||||
}
|
||||
|
||||
System.out.printf("Min: %f\nMax: %f\n", min, max);
|
||||
}
|
||||
}
|
|
@ -30,7 +30,8 @@ public class PatternRendererEMI implements EmiRenderable {
|
|||
public PatternRendererEMI(ResourceLocation pattern, int w, int h) {
|
||||
var entry = PatternRegistry.lookupPattern(pattern);
|
||||
this.strokeOrder = !entry.isPerWorld();
|
||||
var data = PatternDrawingUtil.loadPatterns(List.of(new Pair<>(entry.prototype(), HexCoord.getOrigin())));
|
||||
var data = PatternDrawingUtil.loadPatterns(List.of(new Pair<>(entry.prototype(), HexCoord.getOrigin())), 0f,
|
||||
1f);
|
||||
this.patterns = data.patterns();
|
||||
this.pathfinderDots = data.pathfinderDots();
|
||||
this.width = w;
|
||||
|
@ -54,7 +55,7 @@ public class PatternRendererEMI implements EmiRenderable {
|
|||
poseStack.pushPose();
|
||||
poseStack.translate(xOffset + x - 0.5f + width / 2f, yOffset + y + 1 + height / 2f, 0);
|
||||
poseStack.scale(width / 64f, height / 64f, 1f);
|
||||
PatternDrawingUtil.drawPattern(poseStack, 0, 0, this.patterns, this.pathfinderDots, this.strokeOrder, time,
|
||||
PatternDrawingUtil.drawPattern(poseStack, 0, 0, this.patterns, this.pathfinderDots, this.strokeOrder,
|
||||
0xff_333030, 0xff_191818, 0xc8_0c0a0c, 0x80_666363);
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ public class ForgeHexInitializer {
|
|||
|
||||
// https://github.com/VazkiiMods/Botania/blob/1.18.x/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java
|
||||
private static <T> void bind(ResourceKey<Registry<T>> registry,
|
||||
Consumer<BiConsumer<T, ResourceLocation>> source) {
|
||||
Consumer<BiConsumer<T, ResourceLocation>> source) {
|
||||
getModEventBus().addListener((RegisterEvent event) -> {
|
||||
if (registry.equals(event.getRegistryKey())) {
|
||||
source.accept((t, rl) -> event.register(registry, rl, () -> t));
|
||||
|
@ -123,7 +123,7 @@ public class ForgeHexInitializer {
|
|||
var modBus = getModEventBus();
|
||||
var evBus = MinecraftForge.EVENT_BUS;
|
||||
|
||||
modBus.register(ForgeHexClientInitializer.class);
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> modBus.register(ForgeHexClientInitializer.class));
|
||||
|
||||
modBus.addListener((FMLCommonSetupEvent evt) ->
|
||||
evt.enqueueWork(() -> {
|
||||
|
|
|
@ -26,7 +26,10 @@ public class PatternDrawable implements IDrawable {
|
|||
public PatternDrawable(ResourceLocation pattern, int w, int h) {
|
||||
var entry = PatternRegistry.lookupPattern(pattern);
|
||||
this.strokeOrder = !entry.isPerWorld();
|
||||
var data = PatternDrawingUtil.loadPatterns(List.of(new Pair<>(entry.prototype(), HexCoord.getOrigin())));
|
||||
var data = PatternDrawingUtil.loadPatterns(
|
||||
List.of(new Pair<>(entry.prototype(), HexCoord.getOrigin())),
|
||||
0f,
|
||||
1f);
|
||||
this.patterns = data.patterns();
|
||||
this.pathfinderDots = data.pathfinderDots();
|
||||
this.width = w;
|
||||
|
@ -54,7 +57,7 @@ public class PatternDrawable implements IDrawable {
|
|||
poseStack.pushPose();
|
||||
poseStack.translate(xOffset - 0.5f + width / 2f, yOffset + height / 2f, 0);
|
||||
poseStack.scale(width / 64f, height / 64f, 1f);
|
||||
PatternDrawingUtil.drawPattern(poseStack, 0, 0, this.patterns, this.pathfinderDots, this.strokeOrder, time,
|
||||
PatternDrawingUtil.drawPattern(poseStack, 0, 0, this.patterns, this.pathfinderDots, this.strokeOrder,
|
||||
0xff_333030, 0xff_191818, 0xc8_0c0a0c, 0x80_666363);
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue