weak reference utils, migrate villager prep code into central location
This commit is contained in:
parent
af64fa4363
commit
c4dceeeede
6 changed files with 69 additions and 103 deletions
|
@ -12,10 +12,13 @@ import net.minecraft.world.InteractionHand
|
|||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
const val TAU = Math.PI * 2.0
|
||||
const val SQRT_3 = 1.7320508f
|
||||
|
@ -168,6 +171,34 @@ val String.asTranslatedComponent get() = TranslatableComponent(this)
|
|||
|
||||
fun String.asTranslatedComponent(vararg args: Any) = TranslatableComponent(this, *args)
|
||||
|
||||
|
||||
interface WeakValue<T> {
|
||||
var value: T?
|
||||
}
|
||||
|
||||
private class WeakReferencedValue<T>(var reference: WeakReference<T>?) : WeakValue<T> {
|
||||
override var value: T?
|
||||
get() = reference?.get()
|
||||
set(value) { reference = value?.let { WeakReference(it) } }
|
||||
}
|
||||
|
||||
private class WeakMappedValue<K, T>(val keyGen: (T) -> K) : WeakValue<T> {
|
||||
val reference = WeakHashMap<K, T>()
|
||||
override var value: T?
|
||||
get() = reference.values.firstOrNull()
|
||||
set(value) { if (value != null) reference[keyGen(value)] = value else reference.clear() }
|
||||
}
|
||||
|
||||
fun <T> weakReference(value: T? = null): WeakValue<T> = WeakReferencedValue(value?.let { WeakReference(it) })
|
||||
fun <T, K> weakMapped(keyGen: (T) -> K): WeakValue<T> = WeakMappedValue(keyGen)
|
||||
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline operator fun <T> WeakValue<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = value
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline operator fun <T> WeakValue<T>.setValue(thisRef: Any?, property: KProperty<*>, value: T?) { this.value = value }
|
||||
|
||||
fun Iterable<SpellDatum<*>>.serializeToNBT(): ListTag {
|
||||
val tag = ListTag()
|
||||
for (elt in this)
|
||||
|
|
|
@ -4,7 +4,11 @@ package at.petrak.hexcasting.client
|
|||
import at.petrak.hexcasting.api.mod.HexConfig
|
||||
import at.petrak.hexcasting.api.spell.math.HexPattern
|
||||
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.VillagerIngredient
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
|
@ -16,9 +20,14 @@ import net.minecraft.client.Minecraft
|
|||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.util.FastColor
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.EntityType
|
||||
import net.minecraft.world.entity.npc.Villager
|
||||
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
|
||||
|
@ -286,6 +295,29 @@ fun transferMsToGl(ms: PoseStack, toRun: Runnable) {
|
|||
RenderSystem.applyModelViewMatrix()
|
||||
}
|
||||
|
||||
private var villager: Villager? by weakMapped { it.level }
|
||||
|
||||
fun prepareVillagerForRendering(ingredient: VillagerIngredient, level: Level): Villager {
|
||||
val profession: VillagerProfession = Registry.VILLAGER_PROFESSION.getOptional(ingredient.profession())
|
||||
.orElse(VillagerProfession.TOOLSMITH)
|
||||
val biome: VillagerType = Registry.VILLAGER_TYPE.getOptional(ingredient.biome())
|
||||
.orElse(VillagerType.PLAINS)
|
||||
val minLevel: Int = ingredient.minLevel()
|
||||
|
||||
val instantiatedVillager = villager ?: run {
|
||||
val newVillager = Villager(EntityType.VILLAGER, level)
|
||||
villager = newVillager
|
||||
newVillager
|
||||
}
|
||||
|
||||
instantiatedVillager.villagerData = instantiatedVillager.villagerData
|
||||
.setProfession(profession)
|
||||
.setType(biome)
|
||||
.setLevel(minLevel)
|
||||
|
||||
return instantiatedVillager
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun renderEntity(
|
||||
ms: PoseStack, entity: Entity, world: Level, x: Float, y: Float, rotation: Float,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package at.petrak.hexcasting.fabric.interop.emi;
|
||||
|
||||
import at.petrak.hexcasting.client.ClientTickCounter;
|
||||
import at.petrak.hexcasting.client.RenderLib;
|
||||
import at.petrak.hexcasting.client.shader.FakeBufferSource;
|
||||
import at.petrak.hexcasting.client.shader.HexRenderTypes;
|
||||
import at.petrak.hexcasting.common.recipe.ingredient.VillagerIngredient;
|
||||
|
@ -21,8 +22,6 @@ import net.minecraft.network.chat.TranslatableComponent;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
import net.minecraft.world.entity.npc.VillagerType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -130,28 +129,13 @@ public class VillagerEmiStack extends EmiStack {
|
|||
return ingredient.name();
|
||||
}
|
||||
|
||||
// Used for rendering
|
||||
private static Villager villager;
|
||||
|
||||
@Override
|
||||
public void render(PoseStack poseStack, int x, int y, float delta, int flags) {
|
||||
if ((flags & RENDER_ICON) != 0) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ClientLevel level = mc.level;
|
||||
if (level != null) {
|
||||
VillagerProfession profession = Registry.VILLAGER_PROFESSION.getOptional(ingredient.profession())
|
||||
.orElse(VillagerProfession.TOOLSMITH);
|
||||
VillagerType biome = Registry.VILLAGER_TYPE.getOptional(ingredient.biome())
|
||||
.orElse(VillagerType.PLAINS);
|
||||
int minLevel = ingredient.minLevel();
|
||||
if (villager == null) {
|
||||
villager = new Villager(EntityType.VILLAGER, level);
|
||||
}
|
||||
|
||||
villager.setVillagerData(villager.getVillagerData()
|
||||
.setProfession(profession)
|
||||
.setType(biome)
|
||||
.setLevel(minLevel));
|
||||
Villager villager = RenderLib.prepareVillagerForRendering(ingredient, level);
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package at.petrak.hexcasting.fabric.interop.rei;
|
||||
|
||||
import at.petrak.hexcasting.client.ClientTickCounter;
|
||||
import at.petrak.hexcasting.client.RenderLib;
|
||||
import at.petrak.hexcasting.common.recipe.ingredient.VillagerIngredient;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@ -10,11 +11,7 @@ import me.shedaniel.rei.api.client.gui.widgets.Widget;
|
|||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
import net.minecraft.world.entity.npc.VillagerType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -27,8 +24,6 @@ public class VillagerWidget extends Widget {
|
|||
private final int x;
|
||||
private final int y;
|
||||
|
||||
private Villager displayVillager;
|
||||
|
||||
public VillagerWidget(VillagerIngredient villager, int x, int y) {
|
||||
this.villager = villager;
|
||||
this.x = x;
|
||||
|
@ -39,19 +34,7 @@ public class VillagerWidget extends Widget {
|
|||
public void render(@NotNull PoseStack poseStack, int mouseX, int mouseY, float delta) {
|
||||
ClientLevel level = Minecraft.getInstance().level;
|
||||
if (level != null) {
|
||||
VillagerProfession profession = Registry.VILLAGER_PROFESSION.getOptional(villager.profession())
|
||||
.orElse(VillagerProfession.TOOLSMITH);
|
||||
VillagerType biome = Registry.VILLAGER_TYPE.getOptional(villager.biome())
|
||||
.orElse(VillagerType.PLAINS);
|
||||
int minLevel = villager.minLevel();
|
||||
if (displayVillager == null) {
|
||||
displayVillager = new Villager(EntityType.VILLAGER, level);
|
||||
}
|
||||
|
||||
displayVillager.setVillagerData(displayVillager.getVillagerData()
|
||||
.setProfession(profession)
|
||||
.setType(biome)
|
||||
.setLevel(minLevel));
|
||||
Villager displayVillager = RenderLib.prepareVillagerForRendering(villager, level);
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package at.petrak.hexcasting.forge.interop.jei;
|
||||
|
||||
import at.petrak.hexcasting.client.ClientTickCounter;
|
||||
import at.petrak.hexcasting.client.RenderLib;
|
||||
import at.petrak.hexcasting.common.recipe.BrainsweepRecipe;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@ -15,23 +16,17 @@ import mezz.jei.api.recipe.RecipeType;
|
|||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
import net.minecraft.world.entity.npc.VillagerType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
import static at.petrak.hexcasting.client.RenderLib.renderEntity;
|
||||
|
@ -78,27 +73,12 @@ public class BrainsweepRecipeCategory implements IRecipeCategory<BrainsweepRecip
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Villager villager;
|
||||
|
||||
@Override
|
||||
public void draw(@NotNull BrainsweepRecipe recipe, @NotNull IRecipeSlotsView recipeSlotsView,
|
||||
@NotNull PoseStack stack, double mouseX, double mouseY) {
|
||||
ClientLevel level = Minecraft.getInstance().level;
|
||||
if (level != null) {
|
||||
VillagerProfession profession = Objects.requireNonNullElse(
|
||||
ForgeRegistries.PROFESSIONS.getValue(recipe.villagerIn().profession()),
|
||||
VillagerProfession.TOOLSMITH);
|
||||
VillagerType biome = Objects.requireNonNullElse(Registry.VILLAGER_TYPE.get(recipe.villagerIn().biome()),
|
||||
VillagerType.PLAINS);
|
||||
int minLevel = recipe.villagerIn().minLevel();
|
||||
if (villager == null) {
|
||||
villager = new Villager(EntityType.VILLAGER, level);
|
||||
}
|
||||
|
||||
villager.setVillagerData(villager.getVillagerData()
|
||||
.setProfession(profession)
|
||||
.setType(biome)
|
||||
.setLevel(minLevel));
|
||||
Villager villager = RenderLib.prepareVillagerForRendering(recipe.villagerIn(), level);
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package at.petrak.hexcasting.forge.misc;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public final class PlayerPositionRecorder {
|
||||
private static final Map<Player, Vec3> LAST_SECOND_POSITION_MAP = new WeakHashMap<>();
|
||||
private static final Map<Player, Vec3> LAST_POSITION_MAP = new WeakHashMap<>();
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onEntityUpdate(TickEvent.WorldTickEvent evt) {
|
||||
if (evt.phase == TickEvent.Phase.END && evt.world instanceof ServerLevel world) {
|
||||
for (ServerPlayer player : world.players()) {
|
||||
var prev = LAST_POSITION_MAP.get(player);
|
||||
if (prev != null) {
|
||||
LAST_SECOND_POSITION_MAP.put(player, prev);
|
||||
}
|
||||
LAST_POSITION_MAP.put(player, player.position());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec3 getMotion(ServerPlayer player) {
|
||||
Vec3 vec = LAST_POSITION_MAP.get(player);
|
||||
Vec3 prev = LAST_SECOND_POSITION_MAP.get(player);
|
||||
|
||||
if (vec == null) {
|
||||
return Vec3.ZERO;
|
||||
}
|
||||
|
||||
if (prev == null) {
|
||||
return player.position().subtract(vec);
|
||||
}
|
||||
|
||||
return vec.subtract(prev);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue