WIP: Port some 1.21.5 things

This commit is contained in:
Linnea Gräf
2025-04-01 01:37:55 +02:00
parent 9501ca2e34
commit bb02aa6ddd
43 changed files with 249 additions and 615 deletions

View File

@@ -226,12 +226,12 @@ val citResewnSourceSet = createIsolatedSourceSet("citresewn", isEnabled = false)
val yaclSourceSet = createIsolatedSourceSet("yacl") val yaclSourceSet = createIsolatedSourceSet("yacl")
val explosiveEnhancementSourceSet = val explosiveEnhancementSourceSet =
createIsolatedSourceSet("explosiveEnhancement", isEnabled = false) // TODO: wait for their port createIsolatedSourceSet("explosiveEnhancement", isEnabled = false) // TODO: wait for their port
val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender") val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender", isEnabled = false)
val jadeSourceSet = createIsolatedSourceSet("jade") val jadeSourceSet = createIsolatedSourceSet("jade")
val modmenuSourceSet = createIsolatedSourceSet("modmenu") val modmenuSourceSet = createIsolatedSourceSet("modmenu")
val reiSourceSet = createIsolatedSourceSet("rei") val reiSourceSet = createIsolatedSourceSet("rei", isEnabled = false)
val moulconfigSourceSet = createIsolatedSourceSet("moulconfig") val moulconfigSourceSet = createIsolatedSourceSet("moulconfig")
val customTexturesSourceSet = createIsolatedSourceSet("texturePacks", "texturePacks") val customTexturesSourceSet = createIsolatedSourceSet("texturePacks", "texturePacks", isEnabled = false)
dependencies { dependencies {
// Minecraft dependencies // Minecraft dependencies

View File

@@ -15,7 +15,7 @@ fabric_loader = "0.16.10"
fabric_api = "0.119.5+1.21.5" fabric_api = "0.119.5+1.21.5"
yarn = "1.21.5+build.1" yarn = "1.21.5+build.1"
modmenu = "14.0.0-rc.2" modmenu = "14.0.0-rc.2"
architectury = "16.0.2" architectury = "16.0.3"
rei = "18.0.796" rei = "18.0.796"
# Update from https://maven.fabricmc.net/net/fabricmc/fabric-language-kotlin/ # Update from https://maven.fabricmc.net/net/fabricmc/fabric-language-kotlin/

View File

@@ -19,6 +19,7 @@ import me.shedaniel.rei.api.common.entry.EntryIngredient
import me.shedaniel.rei.api.common.entry.EntryStack import me.shedaniel.rei.api.common.entry.EntryStack
import net.minecraft.entity.EntityType import net.minecraft.entity.EntityType
import net.minecraft.entity.SpawnReason import net.minecraft.entity.SpawnReason
import net.minecraft.registry.entry.RegistryEntry
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.village.VillagerProfession import net.minecraft.village.VillagerProfession
@@ -33,6 +34,7 @@ import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.AprilFoolsUtil import moe.nea.firmament.util.AprilFoolsUtil
import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.gold import moe.nea.firmament.util.gold
import moe.nea.firmament.util.grey import moe.nea.firmament.util.grey
@@ -92,7 +94,7 @@ class SBReforgeRecipe(
list.add(Widgets.withTooltip( list.add(Widgets.withTooltip(
EntityWidget( EntityWidget(
EntityType.VILLAGER.create(EntityRenderer.fakeWorld, SpawnReason.COMMAND) EntityType.VILLAGER.create(EntityRenderer.fakeWorld, SpawnReason.COMMAND)
?.also { it.villagerData = it.villagerData.withProfession(VillagerProfession.WEAPONSMITH) }, ?.also { it.villagerData = it.villagerData.withProfession(MC.currentOrDefaultRegistries.getEntryOrThrow(VillagerProfession.WEAPONSMITH)) },
Point(bounds.minX + 10 + 24 + 8 - dimension.width / 2, bounds.centerY - dimension.height / 2), Point(bounds.minX + 10 + 24 + 8 - dimension.width / 2, bounds.centerY - dimension.height / 2),
dimension dimension
), ),

View File

@@ -3,10 +3,8 @@ package moe.nea.firmament.init;
import me.shedaniel.mm.api.ClassTinkerers; import me.shedaniel.mm.api.ClassTinkerers;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.block.BlockModels;
import net.minecraft.client.render.block.BlockRenderManager; import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.chunk.SectionBuilder; import net.minecraft.client.render.chunk.SectionBuilder;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -28,8 +26,8 @@ public class SectionBuilderRiser extends RiserUtils {
String BlockRenderManager; String BlockRenderManager;
@IntermediaryName(BlockState.class) @IntermediaryName(BlockState.class)
String BlockState; String BlockState;
@IntermediaryName(BakedModel.class) // @IntermediaryName(BakedModel.class)
String BakedModel; // String BakedModel;
String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures"; String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures";
Type getModelDesc = Type.getMethodType( Type getModelDesc = Type.getMethodType(
@@ -41,7 +39,8 @@ public class SectionBuilderRiser extends RiserUtils {
Intermediary.<BlockRenderManager>className(), Intermediary.<BlockRenderManager>className(),
Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel), Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel),
Type.getMethodDescriptor( Type.getMethodDescriptor(
getTypeForClassName(Intermediary.<BakedModel>className()), // TODO: fix this riser
// getTypeForClassName(Intermediary.<BakedModel>className()),
getTypeForClassName(Intermediary.<BlockState>className()) getTypeForClassName(Intermediary.<BlockState>className())
) )
); );
@@ -105,8 +104,9 @@ public class SectionBuilderRiser extends RiserUtils {
Opcodes.INVOKESTATIC, Opcodes.INVOKESTATIC,
getTypeForClassName(CustomBlockTextures).getInternalName(), getTypeForClassName(CustomBlockTextures).getInternalName(),
"patchIndigo", "patchIndigo",
Type.getMethodDescriptor(getTypeForClassName(BakedModel), Type.getMethodDescriptor(
getTypeForClassName(BakedModel), // getTypeForClassName(BakedModel),
// getTypeForClassName(BakedModel),
getTypeForClassName(BlockPos), getTypeForClassName(BlockPos),
getTypeForClassName(BlockState)), getTypeForClassName(BlockState)),
false false

View File

@@ -20,7 +20,7 @@ public abstract class PlayerDropEventPatch extends PlayerEntity {
@Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true)
public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) { public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) {
Slot fakeSlot = new Slot(getInventory(), getInventory().selectedSlot, 0, 0); Slot fakeSlot = new Slot(getInventory(), getInventory().getSelectedSlot(), 0, 0);
if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW, IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR)) { if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW, IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR)) {
cir.setReturnValue(false); cir.setReturnValue(false);
} }

View File

@@ -43,11 +43,11 @@ public abstract class SlotUpdateListener extends ClientCommonNetworkHandler {
private void onMultiSlotUpdate(InventoryS2CPacket packet, CallbackInfo ci) { private void onMultiSlotUpdate(InventoryS2CPacket packet, CallbackInfo ci) {
var player = this.client.player; var player = this.client.player;
assert player != null; assert player != null;
if (packet.getSyncId() == 0) { if (packet.syncId() == 0) {
PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Multi(packet.getContents())); PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Multi(packet.contents()));
} else if (packet.getSyncId() == player.currentScreenHandler.syncId) { } else if (packet.syncId() == player.currentScreenHandler.syncId) {
ChestInventoryUpdateEvent.Companion.publish( ChestInventoryUpdateEvent.Companion.publish(
new ChestInventoryUpdateEvent.Multi(packet.getContents()) new ChestInventoryUpdateEvent.Multi(packet.contents())
); );
} }
} }

View File

@@ -1,30 +1,32 @@
package moe.nea.firmament.mixins; package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import moe.nea.firmament.events.SoundReceiveEvent; import moe.nea.firmament.events.SoundReceiveEvent;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPlayNetworkHandler.class) @Mixin(ClientPlayNetworkHandler.class)
public class SoundReceiveEventPatch { public class SoundReceiveEventPatch {
@Inject(method = "onPlaySound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;playSound(Lnet/minecraft/entity/player/PlayerEntity;DDDLnet/minecraft/registry/entry/RegistryEntry;Lnet/minecraft/sound/SoundCategory;FFJ)V"), cancellable = true) @WrapWithCondition(method = "onPlaySound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;playSound(Lnet/minecraft/entity/Entity;DDDLnet/minecraft/registry/entry/RegistryEntry;Lnet/minecraft/sound/SoundCategory;FFJ)V"))
private void postEventWhenSoundIsPlayed(PlaySoundS2CPacket packet, CallbackInfo ci) { private boolean postEventWhenSoundIsPlayed(ClientWorld instance, @Nullable Entity source, double x, double y, double z, RegistryEntry<SoundEvent> sound, SoundCategory category, float volume, float pitch, long seed) {
var event = new SoundReceiveEvent( var event = new SoundReceiveEvent(
packet.getSound(), sound,
packet.getCategory(), category,
new Vec3d(packet.getX(), packet.getY(), packet.getZ()), new Vec3d(x,y,z),
packet.getPitch(), pitch,
packet.getVolume(), volume,
packet.getSeed() seed
); );
SoundReceiveEvent.Companion.publish(event); SoundReceiveEvent.Companion.publish(event);
if (event.getCancelled()) { return !event.getCancelled();
ci.cancel();
}
} }
} }

View File

@@ -3,6 +3,7 @@ package moe.nea.firmament.features.chat
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsChannel import io.ktor.client.statement.bodyAsChannel
import io.ktor.utils.io.jvm.javaio.toInputStream import io.ktor.utils.io.jvm.javaio.toInputStream
import java.net.URI
import java.net.URL import java.net.URL
import java.util.Collections import java.util.Collections
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
@@ -78,7 +79,7 @@ object ChatLinks : FirmamentFeature {
val texId = Firmament.identifier("dynamic_image_preview${nextTexId.getAndIncrement()}") val texId = Firmament.identifier("dynamic_image_preview${nextTexId.getAndIncrement()}")
MC.textureManager.registerTexture( MC.textureManager.registerTexture(
texId, texId,
NativeImageBackedTexture(image) NativeImageBackedTexture({ texId.path }, image)
) )
Image(texId, image.width, image.height) Image(texId, image.width, image.height)
} else } else
@@ -102,8 +103,8 @@ object ChatLinks : FirmamentFeature {
if (it.screen !is ChatScreen) return if (it.screen !is ChatScreen) return
val hoveredComponent = val hoveredComponent =
MC.inGameHud.chatHud.getTextStyleAt(it.mouseX.toDouble(), it.mouseY.toDouble()) ?: return MC.inGameHud.chatHud.getTextStyleAt(it.mouseX.toDouble(), it.mouseY.toDouble()) ?: return
val hoverEvent = hoveredComponent.hoverEvent ?: return val hoverEvent = hoveredComponent.hoverEvent as? HoverEvent.ShowText ?: return
val value = hoverEvent.getValue(HoverEvent.Action.SHOW_TEXT) ?: return val value = hoverEvent.value
val url = urlRegex.matchEntire(value.unformattedString)?.groupValues?.get(0) ?: return val url = urlRegex.matchEntire(value.unformattedString)?.groupValues?.get(0) ?: return
if (!isImageUrl(url)) return if (!isImageUrl(url)) return
val imageFuture = imageCache[url] ?: return val imageFuture = imageCache[url] ?: return
@@ -149,8 +150,8 @@ object ChatLinks : FirmamentFeature {
Text.literal(url).setStyle( Text.literal(url).setStyle(
Style.EMPTY.withUnderline(true).withColor( Style.EMPTY.withUnderline(true).withColor(
Formatting.AQUA Formatting.AQUA
).withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal(url))) ).withHoverEvent(HoverEvent.ShowText(Text.literal(url)))
.withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url)) .withClickEvent(ClickEvent.OpenUrl(URI(url)))
) )
) )
if (isImageUrl(url)) if (isImageUrl(url))

View File

@@ -43,6 +43,7 @@ import moe.nea.firmament.util.mc.IntrospectableItemModelManager
import moe.nea.firmament.util.mc.SNbtFormatter import moe.nea.firmament.util.mc.SNbtFormatter
import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString
import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.iterableArmorItems
import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt
import moe.nea.firmament.util.skyBlockId import moe.nea.firmament.util.skyBlockId
@@ -108,7 +109,7 @@ object PowerUserTools : FirmamentFeature {
MC.sendChat(Text.stringifiedTranslatable("firmament.poweruser.entity.position", target.pos)) MC.sendChat(Text.stringifiedTranslatable("firmament.poweruser.entity.position", target.pos))
if (target is LivingEntity) { if (target is LivingEntity) {
MC.sendChat(Text.translatable("firmament.poweruser.entity.armor")) MC.sendChat(Text.translatable("firmament.poweruser.entity.armor"))
for (armorItem in target.armorItems) { for ((slot, armorItem) in target.iterableArmorItems) {
MC.sendChat(Text.translatable("firmament.poweruser.entity.armor.item", debugFormat(armorItem))) MC.sendChat(Text.translatable("firmament.poweruser.entity.armor.item", debugFormat(armorItem)))
} }
} }

View File

@@ -222,7 +222,7 @@ object MinesweeperHelper {
fun onChat(event: ProcessChatEvent) { fun onChat(event: ProcessChatEvent) {
if (CarnivalFeatures.TConfig.displayTutorials && event.unformattedString == startGameQuestion) { if (CarnivalFeatures.TConfig.displayTutorials && event.unformattedString == startGameQuestion) {
MC.sendChat(Text.translatable("firmament.carnival.tutorial.minesweeper").styled { MC.sendChat(Text.translatable("firmament.carnival.tutorial.minesweeper").styled {
it.withClickEvent(ClickEvent(ClickEvent.Action.RUN_COMMAND, "/firm minesweepertutorial")) it.withClickEvent(ClickEvent.RunCommand("/firm minesweepertutorial"))
}) })
} }
if (!CarnivalFeatures.TConfig.enableBombSolver) { if (!CarnivalFeatures.TConfig.enableBombSolver) {
@@ -259,7 +259,7 @@ object MinesweeperHelper {
val boardPosition = BoardPosition.fromBlockPos(event.blockPos) val boardPosition = BoardPosition.fromBlockPos(event.blockPos)
log.log { "Breaking block at ${event.blockPos} ($boardPosition)" } log.log { "Breaking block at ${event.blockPos} ($boardPosition)" }
gs.lastClickedPosition = boardPosition gs.lastClickedPosition = boardPosition
gs.lastDowsingMode = DowsingMode.fromItem(event.player.inventory.mainHandStack) gs.lastDowsingMode = DowsingMode.fromItem(event.player.mainHandStack)
} }
@Subscribe @Subscribe

View File

@@ -1,5 +1,6 @@
package moe.nea.firmament.features.inventory package moe.nea.firmament.features.inventory
import java.net.URI
import net.fabricmc.loader.api.FabricLoader import net.fabricmc.loader.api.FabricLoader
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -38,7 +39,7 @@ object REIDependencyWarner {
.white() .white()
.append(Text.literal("[").aqua()) .append(Text.literal("[").aqua())
.append(Text.translatable("firmament.download", modName) .append(Text.translatable("firmament.download", modName)
.styled { it.withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, modrinthLink(slug))) } .styled { it.withClickEvent(ClickEvent.OpenUrl(URI (modrinthLink(slug)))) }
.yellow() .yellow()
.also { .also {
if (alreadyDownloaded) if (alreadyDownloaded)

View File

@@ -4,6 +4,7 @@ package moe.nea.firmament.features.inventory
import java.util.UUID import java.util.UUID
import org.lwjgl.glfw.GLFW import org.lwjgl.glfw.GLFW
import util.render.CustomRenderLayers
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@@ -17,6 +18,9 @@ import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.int import kotlinx.serialization.json.int
import kotlinx.serialization.serializer import kotlinx.serialization.serializer
import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.RenderLayers
import net.minecraft.client.render.TexturedRenderLayers
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.screen.GenericContainerScreenHandler import net.minecraft.screen.GenericContainerScreenHandler
import net.minecraft.screen.slot.Slot import net.minecraft.screen.slot.Slot
@@ -45,7 +49,6 @@ import moe.nea.firmament.util.mc.ScreenUtil.getSlotByIndex
import moe.nea.firmament.util.mc.SlotUtils.swapWithHotBar import moe.nea.firmament.util.mc.SlotUtils.swapWithHotBar
import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt
import moe.nea.firmament.util.render.GuiRenderLayers
import moe.nea.firmament.util.render.drawLine import moe.nea.firmament.util.render.drawLine
import moe.nea.firmament.util.skyblock.DungeonUtil import moe.nea.firmament.util.skyblock.DungeonUtil
import moe.nea.firmament.util.skyblockUUID import moe.nea.firmament.util.skyblockUUID
@@ -445,7 +448,7 @@ object SlotLocking : FirmamentFeature {
val isUUIDLocked = (it.slot.stack?.skyblockUUID) in (lockedUUIDs ?: setOf()) val isUUIDLocked = (it.slot.stack?.skyblockUUID) in (lockedUUIDs ?: setOf())
if (isSlotLocked || isUUIDLocked) { if (isSlotLocked || isUUIDLocked) {
it.context.drawGuiTexture( it.context.drawGuiTexture(
GuiRenderLayers.GUI_TEXTURED_NO_DEPTH, RenderLayer::getGuiTexturedOverlay,
when { when {
isSlotLocked -> isSlotLocked ->
(Identifier.of("firmament:slot_locked")) (Identifier.of("firmament:slot_locked"))

View File

@@ -218,7 +218,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
} }
fun drawPlayerInventory(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { fun drawPlayerInventory(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
val items = MC.player?.inventory?.main ?: return val items = MC.player?.inventory?.mainStacks ?: return
items.withIndex().forEach { (index, item) -> items.withIndex().forEach { (index, item) ->
val (x, y) = getPlayerInventorySlotPosition(index) val (x, y) = getPlayerInventorySlotPosition(index)
context.drawItem(item, x, y, 0) context.drawItem(item, x, y, 0)

View File

@@ -11,6 +11,7 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlin.jvm.optionals.getOrNull
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtIo import net.minecraft.nbt.NbtIo
@@ -42,15 +43,15 @@ data class VirtualInventory(
override fun deserialize(decoder: Decoder): VirtualInventory { override fun deserialize(decoder: Decoder): VirtualInventory {
val s = decoder.decodeString() val s = decoder.decodeString()
val n = NbtIo.readCompressed(ByteArrayInputStream(s.decodeBase64Bytes()), NbtSizeTracker.of(100_000_000)) val n = NbtIo.readCompressed(ByteArrayInputStream(s.decodeBase64Bytes()), NbtSizeTracker.of(100_000_000))
val items = n.getList(INVENTORY, NbtCompound.COMPOUND_TYPE.toInt()) val items = n.getList(INVENTORY).getOrNull()
val ops = getOps() val ops = getOps()
return VirtualInventory(items.map { return VirtualInventory(items?.map {
it as NbtCompound it as NbtCompound
if (it.isEmpty) ItemStack.EMPTY if (it.isEmpty) ItemStack.EMPTY
else ErrorUtil.catch("Could not deserialize item") { else ErrorUtil.catch("Could not deserialize item") {
ItemStack.CODEC.parse(ops, it).orThrow ItemStack.CODEC.parse(ops, it).orThrow
}.or { ItemStack.EMPTY } }.or { ItemStack.EMPTY }
}) } ?: listOf())
} }
fun getOps() = TolerantRegistriesOps(NbtOps.INSTANCE, MC.currentOrDefaultRegistries) fun getOps() = TolerantRegistriesOps(NbtOps.INSTANCE, MC.currentOrDefaultRegistries)

View File

@@ -1,6 +1,7 @@
package moe.nea.firmament.features.mining package moe.nea.firmament.features.mining
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.jvm.optionals.getOrNull
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
@@ -144,8 +145,7 @@ object PickaxeAbility : FirmamentFeature {
} }
} ?: return } ?: return
val extra = it.item.extraAttributes val extra = it.item.extraAttributes
if (!extra.contains("drill_fuel")) return val fuel = extra.getInt("drill_fuel").getOrNull() ?: return
val fuel = extra.getInt("drill_fuel")
val percentage = fuel / maxFuel.toFloat() val percentage = fuel / maxFuel.toFloat()
it.barOverride = DurabilityBarEvent.DurabilityBar( it.barOverride = DurabilityBarEvent.DurabilityBar(
lerp( lerp(

View File

@@ -169,13 +169,13 @@ object EntityRenderer {
val oldBodyYaw = entity.bodyYaw val oldBodyYaw = entity.bodyYaw
val oldYaw = entity.yaw val oldYaw = entity.yaw
val oldPitch = entity.pitch val oldPitch = entity.pitch
val oldPrevHeadYaw = entity.prevHeadYaw val oldPrevHeadYaw = entity.lastHeadYaw
val oldHeadYaw = entity.headYaw val oldHeadYaw = entity.headYaw
entity.bodyYaw = 180.0f + targetYaw * 20.0f entity.bodyYaw = 180.0f + targetYaw * 20.0f
entity.yaw = 180.0f + targetYaw * 40.0f entity.yaw = 180.0f + targetYaw * 40.0f
entity.pitch = -targetPitch * 20.0f entity.pitch = -targetPitch * 20.0f
entity.headYaw = entity.yaw entity.headYaw = entity.yaw
entity.prevHeadYaw = entity.yaw entity.lastHeadYaw = entity.yaw
val vector3f = Vector3f(0.0f, (entity.height / 2.0f + bottomOffset).toFloat(), 0.0f) val vector3f = Vector3f(0.0f, (entity.height / 2.0f + bottomOffset).toFloat(), 0.0f)
InventoryScreen.drawEntity( InventoryScreen.drawEntity(
context, context,
@@ -190,7 +190,7 @@ object EntityRenderer {
entity.bodyYaw = oldBodyYaw entity.bodyYaw = oldBodyYaw
entity.yaw = oldYaw entity.yaw = oldYaw
entity.pitch = oldPitch entity.pitch = oldPitch
entity.prevHeadYaw = oldPrevHeadYaw entity.lastHeadYaw = oldPrevHeadYaw
entity.headYaw = oldHeadYaw entity.headYaw = oldHeadYaw
context.disableScissor() context.disableScissor()
} }

View File

@@ -1,343 +0,0 @@
package moe.nea.firmament.gui.entity
import java.util.UUID
import java.util.function.BooleanSupplier
import java.util.function.Consumer
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.client.gui.screen.world.SelectWorldScreen
import net.minecraft.component.type.MapIdComponent
import net.minecraft.entity.Entity
import net.minecraft.entity.boss.dragon.EnderDragonPart
import net.minecraft.entity.damage.DamageSource
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.fluid.Fluid
import net.minecraft.item.FuelRegistry
import net.minecraft.item.map.MapState
import net.minecraft.particle.ParticleEffect
import net.minecraft.recipe.BrewingRecipeRegistry
import net.minecraft.recipe.RecipeManager
import net.minecraft.recipe.RecipePropertySet
import net.minecraft.recipe.StonecuttingRecipe
import net.minecraft.recipe.display.CuttingRecipeDisplay
import net.minecraft.registry.DynamicRegistryManager
import net.minecraft.registry.Registries
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.ServerDynamicRegistryType
import net.minecraft.registry.entry.RegistryEntry
import net.minecraft.resource.DataConfiguration
import net.minecraft.resource.ResourcePackManager
import net.minecraft.resource.featuretoggle.FeatureFlags
import net.minecraft.resource.featuretoggle.FeatureSet
import net.minecraft.scoreboard.Scoreboard
import net.minecraft.server.SaveLoading
import net.minecraft.server.command.CommandManager
import net.minecraft.sound.SoundCategory
import net.minecraft.sound.SoundEvent
import net.minecraft.util.Identifier
import net.minecraft.util.TypeFilter
import net.minecraft.util.function.LazyIterationConsumer
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Box
import net.minecraft.util.math.ChunkPos
import net.minecraft.util.math.Direction
import net.minecraft.util.math.Vec3d
import net.minecraft.world.BlockView
import net.minecraft.world.Difficulty
import net.minecraft.world.MutableWorldProperties
import net.minecraft.world.World
import net.minecraft.world.biome.Biome
import net.minecraft.world.biome.BiomeKeys
import net.minecraft.world.chunk.Chunk
import net.minecraft.world.chunk.ChunkManager
import net.minecraft.world.chunk.ChunkStatus
import net.minecraft.world.chunk.EmptyChunk
import net.minecraft.world.chunk.light.LightingProvider
import net.minecraft.world.entity.EntityLookup
import net.minecraft.world.event.GameEvent
import net.minecraft.world.explosion.ExplosionBehavior
import net.minecraft.world.tick.OrderedTick
import net.minecraft.world.tick.QueryableTickScheduler
import net.minecraft.world.tick.TickManager
import moe.nea.firmament.util.MC
fun createDynamicRegistry(): DynamicRegistryManager.Immutable {
// TODO: use SaveLoading.load() to properly load a full registry
return DynamicRegistryManager.of(Registries.REGISTRIES)
}
class FakeWorld(
registries: DynamicRegistryManager.Immutable = createDynamicRegistry(),
) : World(
Properties,
RegistryKey.of(RegistryKeys.WORLD, Identifier.of("firmament", "fakeworld")),
registries,
MC.defaultRegistries.getOrThrow(RegistryKeys.DIMENSION_TYPE)
.getOrThrow(RegistryKey.of(RegistryKeys.DIMENSION_TYPE, Identifier.of("minecraft", "overworld"))),
true,
false,
0L,
0
) {
object Properties : MutableWorldProperties {
override fun getSpawnPos(): BlockPos {
return BlockPos.ORIGIN
}
override fun getSpawnAngle(): Float {
return 0F
}
override fun getTime(): Long {
return 0
}
override fun getTimeOfDay(): Long {
return 0
}
override fun isThundering(): Boolean {
return false
}
override fun isRaining(): Boolean {
return false
}
override fun setRaining(raining: Boolean) {
}
override fun isHardcore(): Boolean {
return false
}
override fun getDifficulty(): Difficulty {
return Difficulty.HARD
}
override fun isDifficultyLocked(): Boolean {
return false
}
override fun setSpawnPos(pos: BlockPos?, angle: Float) {}
}
override fun getPlayers(): List<PlayerEntity> {
return emptyList()
}
override fun getBrightness(direction: Direction?, shaded: Boolean): Float {
return 1f
}
override fun getGeneratorStoredBiome(biomeX: Int, biomeY: Int, biomeZ: Int): RegistryEntry<Biome> {
return registryManager.getOptionalEntry(BiomeKeys.PLAINS).get()
}
override fun getSeaLevel(): Int {
return 0
}
override fun getEnabledFeatures(): FeatureSet {
return FeatureFlags.VANILLA_FEATURES
}
class FakeTickScheduler<T> : QueryableTickScheduler<T> {
override fun scheduleTick(orderedTick: OrderedTick<T>?) {
}
override fun isQueued(pos: BlockPos?, type: T): Boolean {
return true
}
override fun getTickCount(): Int {
return 0
}
override fun isTicking(pos: BlockPos?, type: T): Boolean {
return true
}
}
override fun getBlockTickScheduler(): QueryableTickScheduler<Block> {
return FakeTickScheduler()
}
override fun getFluidTickScheduler(): QueryableTickScheduler<Fluid> {
return FakeTickScheduler()
}
class FakeChunkManager(val world: FakeWorld) : ChunkManager() {
override fun getChunk(x: Int, z: Int, leastStatus: ChunkStatus?, create: Boolean): Chunk {
return EmptyChunk(
world,
ChunkPos(x, z),
world.registryManager.getOptionalEntry(BiomeKeys.PLAINS).get()
)
}
override fun getWorld(): BlockView {
return world
}
override fun tick(shouldKeepTicking: BooleanSupplier?, tickChunks: Boolean) {
}
override fun getDebugString(): String {
return "FakeChunkManager"
}
override fun getLoadedChunkCount(): Int {
return 0
}
override fun getLightingProvider(): LightingProvider {
return FakeLightingProvider(this)
}
}
class FakeLightingProvider(chunkManager: FakeChunkManager) : LightingProvider(chunkManager, false, false)
override fun getChunkManager(): ChunkManager {
return FakeChunkManager(this)
}
override fun playSound(
source: PlayerEntity?,
x: Double,
y: Double,
z: Double,
sound: RegistryEntry<SoundEvent>?,
category: SoundCategory?,
volume: Float,
pitch: Float,
seed: Long
) {
}
override fun syncWorldEvent(player: PlayerEntity?, eventId: Int, pos: BlockPos?, data: Int) {
}
override fun emitGameEvent(event: RegistryEntry<GameEvent>?, emitterPos: Vec3d?, emitter: GameEvent.Emitter?) {
}
override fun updateListeners(pos: BlockPos?, oldState: BlockState?, newState: BlockState?, flags: Int) {
}
override fun playSoundFromEntity(
source: PlayerEntity?,
entity: Entity?,
sound: RegistryEntry<SoundEvent>?,
category: SoundCategory?,
volume: Float,
pitch: Float,
seed: Long
) {
}
override fun createExplosion(
entity: Entity?,
damageSource: DamageSource?,
behavior: ExplosionBehavior?,
x: Double,
y: Double,
z: Double,
power: Float,
createFire: Boolean,
explosionSourceType: ExplosionSourceType?,
smallParticle: ParticleEffect?,
largeParticle: ParticleEffect?,
soundEvent: RegistryEntry<SoundEvent>?
) {
TODO("Not yet implemented")
}
override fun asString(): String {
return "FakeWorld"
}
override fun getEntityById(id: Int): Entity? {
return null
}
override fun getEnderDragonParts(): MutableCollection<EnderDragonPart> {
return mutableListOf()
}
override fun getTickManager(): TickManager {
return TickManager()
}
override fun getMapState(id: MapIdComponent?): MapState? {
return null
}
override fun putMapState(id: MapIdComponent?, state: MapState?) {
}
override fun increaseAndGetMapId(): MapIdComponent {
return MapIdComponent(0)
}
override fun setBlockBreakingInfo(entityId: Int, pos: BlockPos?, progress: Int) {
}
override fun getScoreboard(): Scoreboard {
return Scoreboard()
}
override fun getRecipeManager(): RecipeManager {
return object : RecipeManager {
override fun getPropertySet(key: RegistryKey<RecipePropertySet>?): RecipePropertySet {
return RecipePropertySet.EMPTY
}
override fun getStonecutterRecipes(): CuttingRecipeDisplay.Grouping<StonecuttingRecipe> {
return CuttingRecipeDisplay.Grouping.empty()
}
}
}
object FakeEntityLookup : EntityLookup<Entity> {
override fun get(id: Int): Entity? {
return null
}
override fun get(uuid: UUID?): Entity? {
return null
}
override fun iterate(): MutableIterable<Entity> {
return mutableListOf()
}
override fun <U : Entity?> forEachIntersects(
filter: TypeFilter<Entity, U>?,
box: Box?,
consumer: LazyIterationConsumer<U>?
) {
}
override fun forEachIntersects(box: Box?, action: Consumer<Entity>?) {
}
override fun <U : Entity?> forEach(filter: TypeFilter<Entity, U>?, consumer: LazyIterationConsumer<U>?) {
}
}
override fun getEntityLookup(): EntityLookup<Entity> {
return FakeEntityLookup
}
override fun getBrewingRecipeRegistry(): BrewingRecipeRegistry {
return BrewingRecipeRegistry.EMPTY
}
override fun getFuelRegistry(): FuelRegistry {
TODO("Not yet implemented")
}
}

View File

@@ -47,7 +47,7 @@ object ModifyEquipment : EntityModifier {
private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack { private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack {
val stack = ItemStack(leatherArmor) val stack = ItemStack(leatherArmor)
stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false)) stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16)))
return stack return stack
} }
} }

View File

@@ -1,4 +1,3 @@
package moe.nea.firmament.gui.entity package moe.nea.firmament.gui.entity
import com.google.gson.JsonNull import com.google.gson.JsonNull
@@ -7,6 +6,7 @@ import kotlin.experimental.and
import kotlin.experimental.inv import kotlin.experimental.inv
import kotlin.experimental.or import kotlin.experimental.or
import net.minecraft.entity.EntityType import net.minecraft.entity.EntityType
import net.minecraft.entity.EquipmentSlot
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.entity.SpawnReason import net.minecraft.entity.SpawnReason
import net.minecraft.entity.passive.AbstractHorseEntity import net.minecraft.entity.passive.AbstractHorseEntity
@@ -49,14 +49,11 @@ object ModifyHorse : EntityModifier {
} }
fun AbstractHorseEntity.setIsSaddled(shouldBeSaddled: Boolean) { fun AbstractHorseEntity.setIsSaddled(shouldBeSaddled: Boolean) {
val oldFlag = dataTracker.get(AbstractHorseEntity.HORSE_FLAGS) this.equipStack(EquipmentSlot.SADDLE,
dataTracker.set( if (shouldBeSaddled) ItemStack(Items.SADDLE)
AbstractHorseEntity.HORSE_FLAGS, else ItemStack.EMPTY)
if (shouldBeSaddled) oldFlag or AbstractHorseEntity.SADDLED_FLAG.toByte()
else oldFlag and AbstractHorseEntity.SADDLED_FLAG.toByte().inv()
)
} }
fun AbstractHorseEntity.setHorseArmor(itemStack: ItemStack) { fun AbstractHorseEntity.setHorseArmor(itemStack: ItemStack) {
items.setStack(1, itemStack) this.equipBodyArmor(itemStack)
} }

View File

@@ -4,7 +4,6 @@ import com.mojang.serialization.Dynamic
import io.github.moulberry.repo.IReloadable import io.github.moulberry.repo.IReloadable
import io.github.moulberry.repo.NEURepository import io.github.moulberry.repo.NEURepository
import io.github.moulberry.repo.data.NEUItem import io.github.moulberry.repo.data.NEUItem
import io.github.notenoughupdates.moulconfig.xml.Bind
import java.text.NumberFormat import java.text.NumberFormat
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@@ -13,7 +12,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.jvm.optionals.getOrNull import kotlin.jvm.optionals.getOrNull
import net.minecraft.SharedConstants import net.minecraft.SharedConstants
import net.minecraft.client.resource.language.I18n
import net.minecraft.component.DataComponentTypes import net.minecraft.component.DataComponentTypes
import net.minecraft.component.type.NbtComponent import net.minecraft.component.type.NbtComponent
import net.minecraft.datafixer.Schemas import net.minecraft.datafixer.Schemas
@@ -28,9 +26,6 @@ import net.minecraft.text.MutableText
import net.minecraft.text.Style import net.minecraft.text.Style
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.config.HudMeta
import moe.nea.firmament.gui.config.HudPosition
import moe.nea.firmament.gui.hud.MoulConfigHud
import moe.nea.firmament.repo.RepoManager.initialize import moe.nea.firmament.repo.RepoManager.initialize
import moe.nea.firmament.util.LegacyFormattingCode import moe.nea.firmament.util.LegacyFormattingCode
import moe.nea.firmament.util.LegacyTagParser import moe.nea.firmament.util.LegacyTagParser
@@ -140,7 +135,8 @@ object ItemCache : IReloadable {
ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this) ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this)
itemInstance.loreAccordingToNbt = lore.map { un189Lore(it) } itemInstance.loreAccordingToNbt = lore.map { un189Lore(it) }
itemInstance.displayNameAccordingToNbt = un189Lore(displayName) itemInstance.displayNameAccordingToNbt = un189Lore(displayName)
val extraAttributes = oldItemTag.getCompound("tag").getCompound("ExtraAttributes") val extraAttributes = oldItemTag.getCompound("tag").flatMap { it.getCompound("ExtraAttributes") }
.getOrNull()
if (extraAttributes != null) if (extraAttributes != null)
itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes)) itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes))
return itemInstance return itemInstance

View File

@@ -24,7 +24,7 @@ import net.minecraft.resource.metadata.ResourceMetadata
import net.minecraft.resource.metadata.ResourceMetadataSerializer import net.minecraft.resource.metadata.ResourceMetadataSerializer
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.PathUtil import net.minecraft.util.path.PathUtil
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
class RepoModResourcePack(val basePath: Path) : ModResourcePack { class RepoModResourcePack(val basePath: Path) : ModResourcePack {

View File

@@ -99,7 +99,7 @@ object MC {
inline val soundManager get() = instance.soundManager inline val soundManager get() = instance.soundManager
inline val player: ClientPlayerEntity? get() = TestUtil.unlessTesting { instance.player } inline val player: ClientPlayerEntity? get() = TestUtil.unlessTesting { instance.player }
inline val camera: Entity? get() = instance.cameraEntity inline val camera: Entity? get() = instance.cameraEntity
inline val stackInHand: ItemStack get() = player?.inventory?.mainHandStack ?: ItemStack.EMPTY inline val stackInHand: ItemStack get() = player?.mainHandStack ?: ItemStack.EMPTY
inline val guiAtlasManager get() = instance.guiAtlasManager inline val guiAtlasManager get() = instance.guiAtlasManager
inline val world: ClientWorld? get() = TestUtil.unlessTesting { instance.world } inline val world: ClientWorld? get() = TestUtil.unlessTesting { instance.world }
inline val playerName: String? get() = player?.name?.unformattedString inline val playerName: String? get() = player?.name?.unformattedString

View File

@@ -130,13 +130,14 @@ fun ItemStack.modifyExtraAttributes(block: (NbtCompound) -> Unit) {
} }
val ItemStack.skyblockUUIDString: String? val ItemStack.skyblockUUIDString: String?
get() = extraAttributes.getString("uuid")?.takeIf { it.isNotBlank() } get() = extraAttributes.getString("uuid").getOrNull()?.takeIf { it.isNotBlank() }
val ItemStack.skyblockUUID: UUID? val ItemStack.skyblockUUID: UUID?
get() = skyblockUUIDString?.let { UUID.fromString(it) } get() = skyblockUUIDString?.let { UUID.fromString(it) }
private val petDataCache = WeakCache.memoize<ItemStack, Optional<HypixelPetInfo>>("PetInfo") { private val petDataCache = WeakCache.memoize<ItemStack, Optional<HypixelPetInfo>>("PetInfo") {
val jsonString = it.extraAttributes.getString("petInfo") val jsonString = it.extraAttributes.getString("petInfo")
.getOrNull()
if (jsonString.isNullOrBlank()) return@memoize Optional.empty() if (jsonString.isNullOrBlank()) return@memoize Optional.empty()
ErrorUtil.catch<HypixelPetInfo?>("Could not decode hypixel pet info") { ErrorUtil.catch<HypixelPetInfo?>("Could not decode hypixel pet info") {
jsonparser.decodeFromString<HypixelPetInfo>(jsonString) jsonparser.decodeFromString<HypixelPetInfo>(jsonString)
@@ -145,8 +146,8 @@ private val petDataCache = WeakCache.memoize<ItemStack, Optional<HypixelPetInfo>
} }
fun ItemStack.getUpgradeStars(): Int { fun ItemStack.getUpgradeStars(): Int {
return extraAttributes.getInt("upgrade_level").takeIf { it > 0 } return extraAttributes.getInt("upgrade_level").getOrNull()?.takeIf { it > 0 }
?: extraAttributes.getInt("dungeon_item_level").takeIf { it > 0 } ?: extraAttributes.getInt("dungeon_item_level").getOrNull()?.takeIf { it > 0 }
?: 0 ?: 0
} }
@@ -155,7 +156,7 @@ fun ItemStack.getUpgradeStars(): Int {
value class ReforgeId(val id: String) value class ReforgeId(val id: String)
fun ItemStack.getReforgeId(): ReforgeId? { fun ItemStack.getReforgeId(): ReforgeId? {
return extraAttributes.getString("modifier").takeIf { it.isNotBlank() }?.let(::ReforgeId) return extraAttributes.getString("modifier").getOrNull()?.takeIf { it.isNotBlank() }?.let(::ReforgeId)
} }
val ItemStack.petData: HypixelPetInfo? val ItemStack.petData: HypixelPetInfo?
@@ -169,8 +170,8 @@ fun ItemStack.setSkyBlockId(skyblockId: SkyblockId): ItemStack {
val ItemStack.skyBlockId: SkyblockId? val ItemStack.skyBlockId: SkyblockId?
get() { get() {
return when (val id = extraAttributes.getString("id")) { return when (val id = extraAttributes.getString("id").getOrNull()) {
"" -> { "", null -> {
null null
} }
@@ -180,20 +181,22 @@ val ItemStack.skyBlockId: SkyblockId?
"RUNE", "UNIQUE_RUNE" -> { "RUNE", "UNIQUE_RUNE" -> {
val runeData = extraAttributes.getCompound("runes") val runeData = extraAttributes.getCompound("runes")
val runeKind = runeData.keys.singleOrNull() .getOrNull()
val runeKind = runeData?.keys?.singleOrNull()
if (runeKind == null) SkyblockId("RUNE") if (runeKind == null) SkyblockId("RUNE")
else SkyblockId("${runeKind.uppercase()}_RUNE;${runeData.getInt(runeKind)}") else SkyblockId("${runeKind.uppercase()}_RUNE;${runeData.getInt(runeKind).getOrNull()}")
} }
"ABICASE" -> { "ABICASE" -> {
SkyblockId("ABICASE_${extraAttributes.getString("model").uppercase()}") SkyblockId("ABICASE_${extraAttributes.getString("model").getOrNull()?.uppercase()}")
} }
"ENCHANTED_BOOK" -> { "ENCHANTED_BOOK" -> {
val enchantmentData = extraAttributes.getCompound("enchantments") val enchantmentData = extraAttributes.getCompound("enchantments")
val enchantName = enchantmentData.keys.singleOrNull() .getOrNull()
val enchantName = enchantmentData?.keys?.singleOrNull()
if (enchantName == null) SkyblockId("ENCHANTED_BOOK") if (enchantName == null) SkyblockId("ENCHANTED_BOOK")
else SkyblockId("${enchantName.uppercase()};${enchantmentData.getInt(enchantName)}") else SkyblockId("${enchantName.uppercase()};${enchantmentData.getInt(enchantName).getOrNull()}")
} }
// TODO: PARTY_HAT_CRAB{,_ANIMATED,_SLOTH},POTION // TODO: PARTY_HAT_CRAB{,_ANIMATED,_SLOTH},POTION

View File

@@ -0,0 +1,8 @@
package moe.nea.firmament.util.mc
import net.minecraft.entity.EquipmentSlot
import net.minecraft.entity.LivingEntity
val LivingEntity.iterableArmorItems
get() = EquipmentSlot.entries.asSequence()
.map { it to getEquippedStack(it) }

View File

@@ -0,0 +1,7 @@
package moe.nea.firmament.util.mc
import net.minecraft.entity.EquipmentSlot
import net.minecraft.entity.player.PlayerEntity
val PlayerEntity.mainHandStack get() = this.getEquippedStack(EquipmentSlot.MAINHAND)

View File

@@ -1,5 +1,6 @@
package moe.nea.firmament.util.mc package moe.nea.firmament.util.mc
import net.minecraft.nbt.AbstractNbtList
import net.minecraft.nbt.NbtByte import net.minecraft.nbt.NbtByte
import net.minecraft.nbt.NbtByteArray import net.minecraft.nbt.NbtByteArray
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
@@ -38,7 +39,7 @@ class SNbtFormatter private constructor() : NbtElementVisitor {
override fun visitString(element: NbtString) { override fun visitString(element: NbtString) {
result.append(NbtString.escape(element.asString())) result.append(NbtString.escape(element.value))
} }
override fun visitByte(element: NbtByte) { override fun visitByte(element: NbtByte) {
@@ -65,18 +66,18 @@ class SNbtFormatter private constructor() : NbtElementVisitor {
result.append(element.doubleValue()).append("d") result.append(element.doubleValue()).append("d")
} }
private fun visitArrayContents(array: List<NbtElement>) { private fun visitArrayContents(array: AbstractNbtList) {
array.forEachIndexed { index, element -> array.forEachIndexed { index, element ->
writeIndent() writeIndent()
element.accept(this) element.accept(this)
if (array.size != index + 1) { if (array.size() != index + 1) {
result.append(",") result.append(",")
} }
result.append("\n") result.append("\n")
} }
} }
private fun writeArray(arrayTypeTag: String, array: List<NbtElement>) { private fun writeArray(arrayTypeTag: String, array: AbstractNbtList) {
result.append("[").append(arrayTypeTag).append("\n") result.append("[").append(arrayTypeTag).append("\n")
pushIndent() pushIndent()
visitArrayContents(array) visitArrayContents(array)

View File

@@ -0,0 +1,62 @@
package util.render
import com.mojang.blaze3d.pipeline.RenderPipeline
import com.mojang.blaze3d.platform.DepthTestFunction
import com.mojang.blaze3d.vertex.VertexFormat.DrawMode
import java.util.function.Function
import net.minecraft.client.gl.RenderPipelines
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.RenderPhase
import net.minecraft.client.render.VertexFormats
import net.minecraft.util.Identifier
import net.minecraft.util.TriState
import net.minecraft.util.Util
import moe.nea.firmament.Firmament
object CustomRenderPipelines {
val GUI_TEXTURED_NO_DEPTH_TRIS =
RenderPipeline.builder(RenderPipelines.POSITION_TEX_COLOR_SNIPPET)
.withVertexFormat(VertexFormats.POSITION_TEXTURE_COLOR, DrawMode.TRIANGLES)
.withLocation(Firmament.identifier("gui_textured_overlay_tris"))
.withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
.withCull(false)
.withDepthWrite(false)
.build()
val COLORED_OMNIPRESENT_QUADS = RenderPipeline.builder(RenderPipelines.ENTITY_SNIPPET)// TODO: split this up to support better transparent ordering.
.withLocation(Firmament.identifier("colored_omnipresent_quads"))
.withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
.withDepthWrite(false)
.build()
}
object CustomRenderLayers {
inline fun memoizeTextured(crossinline func: (Identifier) -> RenderLayer) = memoize(func)
inline fun <T, R> memoize(crossinline func: (T) -> R): Function<T, R> {
return Util.memoize { it: T -> func(it) }
}
val GUI_TEXTURED_NO_DEPTH_TRIS = memoizeTextured { texture ->
RenderLayer.of("firmament_gui_textured_overlay_tris",
RenderLayer.DEFAULT_BUFFER_SIZE,
CustomRenderPipelines.GUI_TEXTURED_NO_DEPTH_TRIS,
RenderLayer.MultiPhaseParameters.builder().texture(
RenderPhase.Texture(texture, TriState.DEFAULT, false))
.build(false))
}
val LINES = RenderLayer.of(
"firmament_lines",
RenderLayer.DEFAULT_BUFFER_SIZE,
RenderPipelines.LINES,
RenderLayer.MultiPhaseParameters.builder()
.build(false)
)
val COLORED_QUADS = RenderLayer.of(
"firmament_quads",
RenderLayer.DEFAULT_BUFFER_SIZE,
CustomRenderPipelines.COLORED_OMNIPRESENT_QUADS,
RenderLayer.MultiPhaseParameters.builder()
.build(false)
)
}

View File

@@ -1,52 +1,24 @@
package moe.nea.firmament.util.render package moe.nea.firmament.util.render
import com.mojang.blaze3d.pipeline.RenderPipeline
import com.mojang.blaze3d.platform.DepthTestFunction
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.VertexFormat.DrawMode
import me.shedaniel.math.Color import me.shedaniel.math.Color
import org.joml.Matrix4f import org.joml.Matrix4f
import util.render.CustomRenderLayers
import net.minecraft.client.gl.RenderPipelines
import net.minecraft.client.gui.DrawContext import net.minecraft.client.gui.DrawContext
import net.minecraft.client.render.RenderLayer import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.RenderLayer.MultiPhaseParameters
import net.minecraft.client.render.RenderPhase
import net.minecraft.client.render.VertexFormat
import net.minecraft.client.render.VertexFormat.DrawMode
import net.minecraft.client.render.VertexFormats import net.minecraft.client.render.VertexFormats
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.TriState import moe.nea.firmament.Firmament
import net.minecraft.util.Util
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
fun DrawContext.isUntranslatedGuiDrawContext(): Boolean { fun DrawContext.isUntranslatedGuiDrawContext(): Boolean {
return (matrices.peek().positionMatrix.properties() and Matrix4f.PROPERTY_IDENTITY.toInt()) != 0 return (matrices.peek().positionMatrix.properties() and Matrix4f.PROPERTY_IDENTITY.toInt()) != 0
} }
object GuiRenderLayers {
val GUI_TEXTURED_NO_DEPTH = Util.memoize<Identifier, RenderLayer> { texture: Identifier ->
RenderLayer.of("firmament_gui_textured_no_depth",
VertexFormats.POSITION_TEXTURE_COLOR,
DrawMode.QUADS,
DEFAULT_BUFFER_SIZE,
MultiPhaseParameters.builder()
.texture(RenderPhase.Texture(texture, TriState.FALSE, false))
.program(RenderPhase.POSITION_TEXTURE_COLOR_PROGRAM)
.transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
.depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
.build(false))
}
val GUI_TEXTURED_TRIS = Util.memoize { texture: Identifier ->
RenderLayer.of("firmament_gui_textured_overlay_tris",
VertexFormats.POSITION_TEXTURE_COLOR,
DrawMode.TRIANGLES,
DEFAULT_BUFFER_SIZE,
MultiPhaseParameters.builder()
.texture(RenderPhase.Texture(texture, TriState.DEFAULT, false))
.program(RenderPhase.POSITION_TEXTURE_COLOR_PROGRAM)
.transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
.depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
.writeMaskState(RenderPhase.COLOR_MASK)
.build(false))
}
}
@Deprecated("Use the other drawGuiTexture") @Deprecated("Use the other drawGuiTexture")
fun DrawContext.drawGuiTexture( fun DrawContext.drawGuiTexture(
x: Int, y: Int, z: Int, width: Int, height: Int, sprite: Identifier x: Int, y: Int, z: Int, width: Int, height: Int, sprite: Identifier
@@ -91,7 +63,7 @@ fun DrawContext.drawLine(fromX: Int, fromY: Int, toX: Int, toY: Int, color: Colo
} }
RenderSystem.lineWidth(MC.window.scaleFactor.toFloat()) RenderSystem.lineWidth(MC.window.scaleFactor.toFloat())
draw { vertexConsumers -> draw { vertexConsumers ->
val buf = vertexConsumers.getBuffer(RenderInWorldContext.RenderLayers.LINES) val buf = vertexConsumers.getBuffer(CustomRenderLayers.LINES)
buf.vertex(fromX.toFloat(), fromY.toFloat(), 0F).color(color.color) buf.vertex(fromX.toFloat(), fromY.toFloat(), 0F).color(color.color)
.normal(toX - fromX.toFloat(), toY - fromY.toFloat(), 0F) .normal(toX - fromX.toFloat(), toY - fromY.toFloat(), 0F)
buf.vertex(toX.toFloat(), toY.toFloat(), 0F).color(color.color) buf.vertex(toX.toFloat(), toY.toFloat(), 0F).color(color.color)

View File

@@ -1,18 +1,12 @@
package moe.nea.firmament.util.render package moe.nea.firmament.util.render
import com.mojang.blaze3d.systems.RenderSystem
import io.github.notenoughupdates.moulconfig.platform.next import io.github.notenoughupdates.moulconfig.platform.next
import org.joml.Matrix4f import org.joml.Matrix4f
import net.minecraft.client.font.TextRenderer import net.minecraft.client.font.TextRenderer
import net.minecraft.client.render.BufferRenderer
import net.minecraft.client.render.GameRenderer
import net.minecraft.client.render.LightmapTextureManager import net.minecraft.client.render.LightmapTextureManager
import net.minecraft.client.render.RenderLayer import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexConsumer import net.minecraft.client.render.VertexConsumer
import net.minecraft.client.render.VertexFormat
import net.minecraft.client.render.VertexFormats
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos

View File

@@ -1,9 +1,10 @@
package moe.nea.firmament.util.render package moe.nea.firmament.util.render
import com.mojang.blaze3d.vertex.VertexFormat
import net.minecraft.client.gl.CompiledShader
import net.minecraft.client.gl.Defines import net.minecraft.client.gl.Defines
import net.minecraft.client.gl.ShaderProgramKey import net.minecraft.client.gl.ShaderProgram
import net.minecraft.client.render.RenderPhase import net.minecraft.client.render.RenderPhase
import net.minecraft.client.render.VertexFormat
import net.minecraft.client.render.VertexFormats import net.minecraft.client.render.VertexFormats
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.annotations.Subscribe
@@ -11,20 +12,9 @@ import moe.nea.firmament.events.DebugInstantiateEvent
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
object FirmamentShaders { object FirmamentShaders {
val shaders = mutableListOf<ShaderProgramKey>()
private fun shader(name: String, format: VertexFormat, defines: Defines): ShaderProgramKey {
val key = ShaderProgramKey(Firmament.identifier(name), format, defines)
shaders.add(key)
return key
}
val LINES = RenderPhase.ShaderProgram(shader("core/rendertype_lines", VertexFormats.LINES, Defines.EMPTY))
@Subscribe @Subscribe
fun debugLoad(event: DebugInstantiateEvent) { fun debugLoad(event: DebugInstantiateEvent) {
shaders.forEach { // TODO: do i still need to work with shaders like this?
MC.instance.shaderLoader.getOrCreateProgram(it)
}
} }
} }

View File

@@ -1,18 +1,12 @@
package moe.nea.firmament.util.render package moe.nea.firmament.util.render
import com.mojang.blaze3d.systems.RenderSystem
import io.github.notenoughupdates.moulconfig.platform.next import io.github.notenoughupdates.moulconfig.platform.next
import org.joml.Matrix4f import org.joml.Matrix4f
import org.joml.Vector2f import org.joml.Vector2f
import util.render.CustomRenderLayers
import kotlin.math.atan2 import kotlin.math.atan2
import kotlin.math.tan import kotlin.math.tan
import net.minecraft.client.gui.DrawContext import net.minecraft.client.gui.DrawContext
import net.minecraft.client.render.BufferRenderer
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.RenderPhase
import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexFormat.DrawMode
import net.minecraft.client.render.VertexFormats
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
object RenderCircleProgress { object RenderCircleProgress {
@@ -26,9 +20,8 @@ object RenderCircleProgress {
v1: Float, v1: Float,
v2: Float, v2: Float,
) { ) {
RenderSystem.enableBlend()
drawContext.draw { drawContext.draw {
val bufferBuilder = it.getBuffer(GuiRenderLayers.GUI_TEXTURED_TRIS.apply(texture)) val bufferBuilder = it.getBuffer(CustomRenderLayers.GUI_TEXTURED_NO_DEPTH_TRIS.apply(texture))
val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix
val corners = listOf( val corners = listOf(
@@ -86,7 +79,6 @@ object RenderCircleProgress {
.next() .next()
} }
} }
RenderSystem.disableBlend()
} }

View File

@@ -5,15 +5,12 @@ import io.github.notenoughupdates.moulconfig.platform.next
import java.lang.Math.pow import java.lang.Math.pow
import org.joml.Matrix4f import org.joml.Matrix4f
import org.joml.Vector3f import org.joml.Vector3f
import net.minecraft.client.gl.VertexBuffer import util.render.CustomRenderLayers
import net.minecraft.client.render.Camera import net.minecraft.client.render.Camera
import net.minecraft.client.render.RenderLayer import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.RenderPhase
import net.minecraft.client.render.RenderTickCounter import net.minecraft.client.render.RenderTickCounter
import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexConsumer import net.minecraft.client.render.VertexConsumer
import net.minecraft.client.render.VertexConsumerProvider import net.minecraft.client.render.VertexConsumerProvider
import net.minecraft.client.render.VertexFormat
import net.minecraft.client.render.VertexFormats import net.minecraft.client.render.VertexFormats
import net.minecraft.client.texture.Sprite import net.minecraft.client.texture.Sprite
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
@@ -27,47 +24,12 @@ import moe.nea.firmament.util.MC
@RenderContextDSL @RenderContextDSL
class RenderInWorldContext private constructor( class RenderInWorldContext private constructor(
private val tesselator: Tessellator,
val matrixStack: MatrixStack, val matrixStack: MatrixStack,
private val camera: Camera, private val camera: Camera,
private val tickCounter: RenderTickCounter, private val tickCounter: RenderTickCounter,
val vertexConsumers: VertexConsumerProvider.Immediate, val vertexConsumers: VertexConsumerProvider.Immediate,
) { ) {
object RenderLayers {
val TRANSLUCENT_TRIS = RenderLayer.of("firmament_translucent_tris",
VertexFormats.POSITION_COLOR,
VertexFormat.DrawMode.TRIANGLES,
RenderLayer.CUTOUT_BUFFER_SIZE,
false, true,
RenderLayer.MultiPhaseParameters.builder()
.depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
.transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
.program(RenderPhase.POSITION_COLOR_PROGRAM)
.build(false))
val LINES = RenderLayer.of("firmament_rendertype_lines",
VertexFormats.LINES,
VertexFormat.DrawMode.LINES,
RenderLayer.CUTOUT_BUFFER_SIZE,
false, false, // do we need translucent? i dont think so
RenderLayer.MultiPhaseParameters.builder()
.depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
.program(FirmamentShaders.LINES)
.build(false)
)
val COLORED_QUADS = RenderLayer.of(
"firmament_quads",
VertexFormats.POSITION_COLOR,
VertexFormat.DrawMode.QUADS,
RenderLayer.CUTOUT_BUFFER_SIZE,
false, true,
RenderLayer.MultiPhaseParameters.builder()
.depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
.program(RenderPhase.POSITION_COLOR_PROGRAM)
.transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
.build(false)
)
}
@Deprecated("stateful color management is no longer a thing") @Deprecated("stateful color management is no longer a thing")
fun color(color: me.shedaniel.math.Color) { fun color(color: me.shedaniel.math.Color) {
@@ -82,7 +44,7 @@ class RenderInWorldContext private constructor(
fun block(blockPos: BlockPos, color: Int) { fun block(blockPos: BlockPos, color: Int) {
matrixStack.push() matrixStack.push()
matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat()) matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat())
buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(RenderLayers.COLORED_QUADS), color) buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS), color)
matrixStack.pop() matrixStack.pop()
} }
@@ -155,7 +117,7 @@ class RenderInWorldContext private constructor(
matrixStack.translate(vec3d.x, vec3d.y, vec3d.z) matrixStack.translate(vec3d.x, vec3d.y, vec3d.z)
matrixStack.scale(size, size, size) matrixStack.scale(size, size, size)
matrixStack.translate(-.5, -.5, -.5) matrixStack.translate(-.5, -.5, -.5)
buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(RenderLayers.COLORED_QUADS), color) buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS), color)
matrixStack.pop() matrixStack.pop()
vertexConsumers.draw() vertexConsumers.draw()
} }
@@ -182,8 +144,7 @@ class RenderInWorldContext private constructor(
fun line(points: List<Vec3d>, lineWidth: Float = 10F) { fun line(points: List<Vec3d>, lineWidth: Float = 10F) {
RenderSystem.lineWidth(lineWidth) RenderSystem.lineWidth(lineWidth)
// TODO: replace with renderlayers val buffer = vertexConsumers.getBuffer(CustomRenderLayers.LINES)
val buffer = tesselator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES)
val matrix = matrixStack.peek() val matrix = matrixStack.peek()
var lastNormal: Vector3f? = null var lastNormal: Vector3f? = null
@@ -203,7 +164,6 @@ class RenderInWorldContext private constructor(
.next() .next()
} }
RenderLayers.LINES.draw(buffer.end())
} }
// TODO: put the favourite icons in front of items again // TODO: put the favourite icons in front of items again
@@ -281,16 +241,15 @@ class RenderInWorldContext private constructor(
fun renderInWorld(event: WorldRenderLastEvent, block: RenderInWorldContext. () -> Unit) { fun renderInWorld(event: WorldRenderLastEvent, block: RenderInWorldContext. () -> Unit) {
// TODO: there should be *no more global state*. the only thing we should be doing is render layers. that includes settings like culling, blending, shader color, and depth testing // TODO: there should be *no more global state*. the only thing we should be doing is render layers. that includes settings like culling, blending, shader color, and depth testing
// For now i will let these functions remain, but this needs to go before i do a full (non-beta) release // For now i will let these functions remain, but this needs to go before i do a full (non-beta) release
RenderSystem.disableDepthTest() // RenderSystem.disableDepthTest()
RenderSystem.enableBlend() // RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc() // RenderSystem.defaultBlendFunc()
RenderSystem.disableCull() // RenderSystem.disableCull()
event.matrices.push() event.matrices.push()
event.matrices.translate(-event.camera.pos.x, -event.camera.pos.y, -event.camera.pos.z) event.matrices.translate(-event.camera.pos.x, -event.camera.pos.y, -event.camera.pos.z)
val ctx = RenderInWorldContext( val ctx = RenderInWorldContext(
RenderSystem.renderThreadTesselator(),
event.matrices, event.matrices,
event.camera, event.camera,
event.tickCounter, event.tickCounter,
@@ -302,10 +261,6 @@ class RenderInWorldContext private constructor(
event.matrices.pop() event.matrices.pop()
event.vertexConsumers.draw() event.vertexConsumers.draw()
RenderSystem.setShaderColor(1F, 1F, 1F, 1F) RenderSystem.setShaderColor(1F, 1F, 1F, 1F)
VertexBuffer.unbind()
RenderSystem.enableDepthTest()
RenderSystem.enableCull()
RenderSystem.disableBlend()
} }
} }
} }

View File

@@ -1,7 +1,5 @@
package moe.nea.firmament.util.render package moe.nea.firmament.util.render
import com.mojang.blaze3d.platform.GlConst
import com.mojang.blaze3d.systems.RenderSystem
import me.shedaniel.math.Color import me.shedaniel.math.Color
import net.minecraft.client.render.OverlayTexture import net.minecraft.client.render.OverlayTexture
import net.minecraft.util.math.ColorHelper import net.minecraft.util.math.ColorHelper
@@ -29,16 +27,9 @@ class TintedOverlayTexture : OverlayTexture() {
} }
} }
RenderSystem.activeTexture(GlConst.GL_TEXTURE1)
texture.bindTexture()
texture.setFilter(false, false) texture.setFilter(false, false)
texture.setClamp(true) texture.setClamp(true)
image.upload(0, texture.upload()
0, 0,
0, 0,
image.width, image.height,
false)
RenderSystem.activeTexture(GlConst.GL_TEXTURE0)
return this return this
} }
} }

View File

@@ -93,7 +93,7 @@ object SackUtil {
fun updateFromHoverText(text: Text) { fun updateFromHoverText(text: Text) {
text.siblings.forEach(::updateFromHoverText) text.siblings.forEach(::updateFromHoverText)
val hoverText = text.style.hoverEvent?.getValue(HoverEvent.Action.SHOW_TEXT) ?: return val hoverText = (text.style.hoverEvent as? HoverEvent.ShowText)?.value ?: return
val cleanedText = hoverText.unformattedString val cleanedText = hoverText.unformattedString
if (cleanedText.startsWith("Added items:\n")) { if (cleanedText.startsWith("Added items:\n")) {
if (!foundAdded) { if (!foundAdded) {

View File

@@ -127,13 +127,13 @@ fun MutableText.darkGrey() = withColor(Formatting.DARK_GRAY)
fun MutableText.red() = withColor(Formatting.RED) fun MutableText.red() = withColor(Formatting.RED)
fun MutableText.white() = withColor(Formatting.WHITE) fun MutableText.white() = withColor(Formatting.WHITE)
fun MutableText.bold(): MutableText = styled { it.withBold(true) } fun MutableText.bold(): MutableText = styled { it.withBold(true) }
fun MutableText.hover(text: Text): MutableText = styled {it.withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_TEXT, text))} fun MutableText.hover(text: Text): MutableText = styled {it.withHoverEvent(HoverEvent.ShowText(text))}
fun MutableText.clickCommand(command: String): MutableText { fun MutableText.clickCommand(command: String): MutableText {
require(command.startsWith("/")) require(command.startsWith("/"))
return this.styled { return this.styled {
it.withClickEvent(ClickEvent(ClickEvent.Action.RUN_COMMAND, command)) it.withClickEvent(ClickEvent.RunCommand(command))
} }
} }

View File

@@ -9,9 +9,6 @@ accessible class net/minecraft/registry/RegistryOps$CachedRegistryInfoGetter
accessible field net/minecraft/entity/mob/CreeperEntity CHARGED Lnet/minecraft/entity/data/TrackedData; accessible field net/minecraft/entity/mob/CreeperEntity CHARGED Lnet/minecraft/entity/data/TrackedData;
accessible method net/minecraft/entity/decoration/ArmorStandEntity setSmall (Z)V accessible method net/minecraft/entity/decoration/ArmorStandEntity setSmall (Z)V
accessible field net/minecraft/entity/passive/AbstractHorseEntity items Lnet/minecraft/inventory/SimpleInventory;
accessible field net/minecraft/entity/passive/AbstractHorseEntity SADDLED_FLAG I
accessible field net/minecraft/entity/passive/AbstractHorseEntity HORSE_FLAGS Lnet/minecraft/entity/data/TrackedData;
accessible method net/minecraft/resource/NamespaceResourceManager loadMetadata (Lnet/minecraft/resource/InputSupplier;)Lnet/minecraft/resource/metadata/ResourceMetadata; accessible method net/minecraft/resource/NamespaceResourceManager loadMetadata (Lnet/minecraft/resource/InputSupplier;)Lnet/minecraft/resource/metadata/ResourceMetadata;
accessible method net/minecraft/client/gui/DrawContext drawTexturedQuad (Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIIIFFFFI)V accessible method net/minecraft/client/gui/DrawContext drawTexturedQuad (Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIIIFFFFI)V

View File

@@ -19,8 +19,8 @@ import kotlinx.serialization.serializer
import kotlin.jvm.optionals.getOrNull import kotlin.jvm.optionals.getOrNull
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.client.render.model.BakedModel import net.minecraft.client.render.item.model.ItemModel
import net.minecraft.client.util.ModelIdentifier import net.minecraft.client.render.model.BlockStateModel
import net.minecraft.registry.RegistryKey import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys import net.minecraft.registry.RegistryKeys
import net.minecraft.resource.ResourceManager import net.minecraft.resource.ResourceManager
@@ -57,11 +57,11 @@ object CustomBlockTextures {
) { ) {
@Transient @Transient
val blockModelIdentifier get() = ModelIdentifier(block.withPrefixedPath("block/"), "firmament") val blockModelIdentifier get() = block.withPrefixedPath("block/")
@Transient @Transient
val bakedModel: BakedModel by lazy(LazyThreadSafetyMode.NONE) { val bakedModel: ItemModel by lazy(LazyThreadSafetyMode.NONE) {
MC.instance.bakedModelManager.getModel(blockModelIdentifier) MC.instance.bakedModelManager.blockModels.(blockModelIdentifier)
} }
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
@@ -189,7 +189,7 @@ object CustomBlockTextures {
} }
@JvmStatic @JvmStatic
fun getReplacementModel(block: BlockState, blockPos: BlockPos?): BakedModel? { fun getReplacementModel(block: BlockState, blockPos: BlockPos?): BlockStateModel? {
return getReplacement(block, blockPos)?.bakedModel return getReplacement(block, blockPos)?.bakedModel
} }
@@ -269,11 +269,6 @@ object CustomBlockTextures {
return BakedReplacements(map.mapValues { LocationReplacements(it.value) }) return BakedReplacements(map.mapValues { LocationReplacements(it.value) })
} }
@JvmStatic
fun patchIndigo(orig: BakedModel, pos: BlockPos, state: BlockState): BakedModel {
return getReplacementModel(state, pos) ?: orig
}
@Subscribe @Subscribe
fun onStart(event: FinalizeResourceManagerEvent) { fun onStart(event: FinalizeResourceManagerEvent) {
event.resourceManager.registerReloader(object : event.resourceManager.registerReloader(object :

View File

@@ -81,7 +81,11 @@ object CustomGlobalArmorOverrides {
null, null,
Optional.of(RegistryKey.of(EquipmentAssetKeys.REGISTRY_KEY, model)), Optional.of(RegistryKey.of(EquipmentAssetKeys.REGISTRY_KEY, model)),
Optional.empty(), Optional.empty(),
Optional.empty(), false, false, false Optional.empty(),
false,
false,
false,
false
) )
} }

View File

@@ -8,7 +8,6 @@ import org.slf4j.LoggerFactory
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
import kotlin.jvm.optionals.getOrNull import kotlin.jvm.optionals.getOrNull
import net.minecraft.client.util.ModelIdentifier
import net.minecraft.resource.ResourceManager import net.minecraft.resource.ResourceManager
import net.minecraft.resource.SinglePreparationResourceReloader import net.minecraft.resource.SinglePreparationResourceReloader
import net.minecraft.text.Text import net.minecraft.text.Text

View File

@@ -9,12 +9,11 @@ import net.minecraft.client.render.item.ItemRenderState
import net.minecraft.client.render.item.model.BasicItemModel import net.minecraft.client.render.item.model.BasicItemModel
import net.minecraft.client.render.item.model.ItemModel import net.minecraft.client.render.item.model.ItemModel
import net.minecraft.client.render.item.model.ItemModelTypes import net.minecraft.client.render.item.model.ItemModelTypes
import net.minecraft.client.render.item.tint.TintSource
import net.minecraft.client.render.model.ResolvableModel import net.minecraft.client.render.model.ResolvableModel
import net.minecraft.client.world.ClientWorld import net.minecraft.client.world.ClientWorld
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemDisplayContext
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.item.ModelTransformationMode
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.features.texturepack.predicates.AndPredicate import moe.nea.firmament.features.texturepack.predicates.AndPredicate
@@ -29,10 +28,10 @@ class PredicateModel {
) )
override fun update( override fun update(
state: ItemRenderState, state: ItemRenderState?,
stack: ItemStack, stack: ItemStack,
resolver: ItemModelManager, resolver: ItemModelManager?,
transformationMode: ModelTransformationMode, displayContext: ItemDisplayContext?,
world: ClientWorld?, world: ClientWorld?,
user: LivingEntity?, user: LivingEntity?,
seed: Int seed: Int
@@ -42,7 +41,7 @@ class PredicateModel {
.findLast { it.predicate.test(stack, user) } .findLast { it.predicate.test(stack, user) }
?.model ?.model
?: fallback ?: fallback
model.update(state, stack, resolver, transformationMode, world, user, seed) model.update(state, stack, resolver, displayContext, world, user, seed)
} }
} }

View File

@@ -13,6 +13,7 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlin.jvm.optionals.getOrNull
import net.minecraft.nbt.NbtString import net.minecraft.nbt.NbtString
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
@@ -26,7 +27,7 @@ interface StringMatcher {
} }
fun matches(nbt: NbtString): Boolean { fun matches(nbt: NbtString): Boolean {
val string = nbt.asString() val string = nbt.value
val jsonStart = string.indexOf('{') val jsonStart = string.indexOf('{')
val stringStart = string.indexOf('"') val stringStart = string.indexOf('"')
val isString = stringStart >= 0 && string.subSequence(0, stringStart).isBlank() val isString = stringStart >= 0 && string.subSequence(0, stringStart).isBlank()

View File

@@ -1,3 +1,4 @@
package moe.nea.firmament.features.texturepack.predicates package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.Gson import com.google.gson.Gson
@@ -5,8 +6,9 @@ import com.google.gson.JsonArray
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive import com.google.gson.JsonPrimitive
import com.mojang.serialization.JsonOps
import kotlin.jvm.optionals.getOrDefault import kotlin.jvm.optionals.getOrDefault
import kotlin.jvm.optionals.getOrNull
import com.mojang.serialization.JsonOps
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher import moe.nea.firmament.features.texturepack.StringMatcher

View File

@@ -7,16 +7,17 @@ import moe.nea.firmament.features.texturepack.CustomBlockTextures;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.block.BlockModels; import net.minecraft.client.render.block.BlockModels;
import net.minecraft.client.render.block.BlockRenderManager; import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.chunk.SectionBuilder;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BlockStateModel;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@Mixin(BlockRenderManager.class) @Mixin(SectionBuilder.class)
public class ReplaceBlockRenderManagerBlockModel { public class ReplaceBlockRenderManagerBlockModel {
@WrapOperation(method = "renderBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;")) @WrapOperation(method = "build", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BlockStateModel;"))
private BakedModel replaceModelInRenderBlock( private BlockStateModel replaceModelInRenderBlock(BlockRenderManager instance, BlockState state, Operation<BlockStateModel> original, @Local(argsOnly = true) BlockPos pos) {
BlockRenderManager instance, BlockState state, Operation<BakedModel> original, @Local(argsOnly = true) BlockPos pos) {
var replacement = CustomBlockTextures.getReplacementModel(state, pos); var replacement = CustomBlockTextures.getReplacementModel(state, pos);
if (replacement != null) return replacement; if (replacement != null) return replacement;
CustomBlockTextures.enterFallbackCall(); CustomBlockTextures.enterFallbackCall();