implement all (hopefully?) the cardinal components and make items no longer use RegistryObjects

This commit is contained in:
gamma-delta 2022-04-30 15:58:17 -05:00
parent 0274aa525e
commit 2bae373b38
46 changed files with 1311 additions and 602 deletions

View file

@ -0,0 +1,37 @@
package at.petrak.hexcasting.api.addldata;
import net.minecraft.util.FastColor;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import java.util.UUID;
public interface Colorizer {
int color(UUID owner, float time, Vec3 position);
static int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) {
float fIdx = Mth.positiveModulo(time + (float) gradientDir.dot(position), 1f) * colors.length;
int baseIdx = Mth.floor(fIdx);
float tRaw = fIdx - baseIdx;
float t = tRaw < 0.5 ? 4 * tRaw * tRaw * tRaw : (float) (1 - Math.pow(-2 * tRaw + 2, 3) / 2);
int start = colors[baseIdx % colors.length];
int end = colors[(baseIdx + 1) % colors.length];
var r1 = FastColor.ARGB32.red(start);
var g1 = FastColor.ARGB32.green(start);
var b1 = FastColor.ARGB32.blue(start);
var a1 = FastColor.ARGB32.alpha(start);
var r2 = FastColor.ARGB32.red(end);
var g2 = FastColor.ARGB32.green(end);
var b2 = FastColor.ARGB32.blue(end);
var a2 = FastColor.ARGB32.alpha(end);
var r = Mth.lerp(t, r1, r2);
var g = Mth.lerp(t, g1, g2);
var b = Mth.lerp(t, b1, b2);
var a = Mth.lerp(t, a1, a2);
return FastColor.ARGB32.color((int) a, (int) r, (int) g, (int) b);
}
}

View file

@ -0,0 +1,28 @@
package at.petrak.hexcasting.api.addldata;
import at.petrak.hexcasting.api.spell.SpellDatum;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;
public interface DataHolder {
@Nullable
CompoundTag readRawDatum();
@Nullable
default SpellDatum<?> readDatum(ServerLevel world) {
var tag = readRawDatum();
if (tag != null) {
return SpellDatum.DeserializeFromNBT(tag, world);
} else {
return null;
}
}
@Nullable
default SpellDatum<?> emptyDatum() {
return null;
}
boolean writeDatum(@Nullable SpellDatum<?> datum, boolean simulate);
}

View file

@ -0,0 +1,30 @@
package at.petrak.hexcasting.api.addldata;
public interface ManaHolder {
int getMana();
int getMaxMana();
void setMana(int mana);
boolean canRecharge();
boolean canProvide();
int getConsumptionPriority();
boolean canConstructBattery();
default int withdrawMana(int cost, boolean simulate) {
var manaHere = getMana();
if (cost < 0) {
cost = manaHere;
}
if (!simulate) {
var manaLeft = manaHere - cost;
setMana(manaLeft);
}
return Math.min(cost, manaHere);
}
}

View file

@ -1,37 +0,0 @@
package at.petrak.hexcasting.api.cap;
import net.minecraft.util.FastColor;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import java.util.UUID;
public interface Colorizer {
int color(UUID owner, float time, Vec3 position);
static int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) {
float fIdx = Mth.positiveModulo(time + (float) gradientDir.dot(position), 1f) * colors.length;
int baseIdx = Mth.floor(fIdx);
float tRaw = fIdx - baseIdx;
float t = tRaw < 0.5 ? 4 * tRaw * tRaw * tRaw : (float) (1 - Math.pow(-2 * tRaw + 2, 3) / 2);
int start = colors[baseIdx % colors.length];
int end = colors[(baseIdx + 1) % colors.length];
var r1 = FastColor.ARGB32.red(start);
var g1 = FastColor.ARGB32.green(start);
var b1 = FastColor.ARGB32.blue(start);
var a1 = FastColor.ARGB32.alpha(start);
var r2 = FastColor.ARGB32.red(end);
var g2 = FastColor.ARGB32.green(end);
var b2 = FastColor.ARGB32.blue(end);
var a2 = FastColor.ARGB32.alpha(end);
var r = Mth.lerp(t, r1, r2);
var g = Mth.lerp(t, g1, g2);
var b = Mth.lerp(t, b1, b2);
var a = Mth.lerp(t, a1, a2);
return FastColor.ARGB32.color((int) a, (int) r, (int) g, (int) b);
}
}

View file

@ -1,29 +0,0 @@
package at.petrak.hexcasting.api.cap;
import at.petrak.hexcasting.api.spell.SpellDatum;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;
public interface DataHolder {
@Nullable
CompoundTag readRawDatum();
@Nullable
default SpellDatum<?> readDatum(ServerLevel world) {
var tag = readRawDatum();
if (tag != null) {
return SpellDatum.DeserializeFromNBT(tag, world);
} else {
return null;
}
}
@Nullable
default SpellDatum<?> emptyDatum() {
return null;
}
boolean writeDatum(@Nullable SpellDatum<?> datum, boolean simulate);
}

View file

@ -1,17 +1,20 @@
package at.petrak.hexcasting.api.cap; package at.petrak.hexcasting.api.cap;
import at.petrak.hexcasting.api.addldata.Colorizer;
import at.petrak.hexcasting.api.addldata.DataHolder;
import at.petrak.hexcasting.api.addldata.ManaHolder;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.CapabilityToken; import net.minecraftforge.common.capabilities.CapabilityToken;
public final class HexCapabilities { public final class HexCapabilities {
public static final Capability<ManaHolder> MANA = CapabilityManager.get(new CapabilityToken<>() { public static final Capability<ManaHolder> MANA = CapabilityManager.get(new CapabilityToken<>() {
}); });
public static final Capability<DataHolder> DATUM = CapabilityManager.get(new CapabilityToken<>() { public static final Capability<DataHolder> DATUM = CapabilityManager.get(new CapabilityToken<>() {
}); });
public static final Capability<SpellHolder> SPELL = CapabilityManager.get(new CapabilityToken<>() { public static final Capability<HexHolder> SPELL = CapabilityManager.get(new CapabilityToken<>() {
}); });
public static final Capability<Colorizer> COLOR = CapabilityManager.get(new CapabilityToken<>() { public static final Capability<Colorizer> COLOR = CapabilityManager.get(new CapabilityToken<>() {
}); });
} }

View file

@ -0,0 +1,18 @@
package at.petrak.hexcasting.api.cap;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface HexHolder {
boolean canDrawManaFromInventory();
@Nullable
List<HexPattern> getPatterns();
void writePatterns(List<HexPattern> patterns, int mana);
void clearPatterns();
}

View file

@ -1,26 +0,0 @@
package at.petrak.hexcasting.api.cap;
public interface ManaHolder {
int getMana();
int getMaxMana();
void setMana(int mana);
boolean canRecharge();
boolean canProvide();
int getConsumptionPriority();
boolean canConstructBattery();
default int withdrawMana(int cost, boolean simulate) {
var manaHere = getMana();
if (cost < 0)
cost = manaHere;
if (!simulate) {
var manaLeft = manaHere - cost;
setMana(manaLeft);
}
return Math.min(cost, manaHere);
}
}

View file

@ -1,18 +0,0 @@
package at.petrak.hexcasting.api.cap;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface SpellHolder {
boolean canDrawManaFromInventory();
@Nullable
List<HexPattern> getPatterns();
void writePatterns(List<HexPattern> patterns, int mana);
void clearPatterns();
}

View file

@ -6,7 +6,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
public interface SpellHolderItem extends ManaHolderItem { public interface HexHolderItem extends ManaHolderItem {
boolean canDrawManaFromInventory(ItemStack stack); boolean canDrawManaFromInventory(ItemStack stack);

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.misc; package at.petrak.hexcasting.api.misc;
import at.petrak.hexcasting.api.cap.Colorizer; import at.petrak.hexcasting.api.addldata.Colorizer;
import at.petrak.hexcasting.api.cap.HexCapabilities; import at.petrak.hexcasting.api.cap.HexCapabilities;
import at.petrak.hexcasting.api.mod.HexApiItems; import at.petrak.hexcasting.api.mod.HexApiItems;
import net.minecraft.Util; import net.minecraft.Util;
@ -21,14 +21,14 @@ import java.util.function.Supplier;
public record FrozenColorizer(ItemStack item, UUID owner) { public record FrozenColorizer(ItemStack item, UUID owner) {
private static final int[] MINIMUM_LUMINANCE_COLOR_WHEEL = { private static final int[] MINIMUM_LUMINANCE_COLOR_WHEEL = {
0xFF200000, 0xFF202000, 0xFF002000, 0xFF002020, 0xFF000020, 0xFF200020 0xFF200000, 0xFF202000, 0xFF002000, 0xFF002020, 0xFF000020, 0xFF200020
}; };
public static final String TAG_STACK = "stack"; public static final String TAG_STACK = "stack";
public static final String TAG_OWNER = "owner"; public static final String TAG_OWNER = "owner";
public static final Supplier<FrozenColorizer> DEFAULT = public static final Supplier<FrozenColorizer> DEFAULT =
() -> new FrozenColorizer(new ItemStack(HexApiItems.COLORIZER_WHITE), Util.NIL_UUID); () -> new FrozenColorizer(new ItemStack(HexApiItems.COLORIZER_WHITE), Util.NIL_UUID);
public CompoundTag serialize() { public CompoundTag serialize() {
var out = new CompoundTag(); var out = new CompoundTag();
@ -38,8 +38,9 @@ public record FrozenColorizer(ItemStack item, UUID owner) {
} }
public static FrozenColorizer deserialize(CompoundTag tag) { public static FrozenColorizer deserialize(CompoundTag tag) {
if (tag.isEmpty()) if (tag.isEmpty()) {
return FrozenColorizer.DEFAULT.get(); return FrozenColorizer.DEFAULT.get();
}
try { try {
ItemStack item; ItemStack item;
if (tag.contains("item", Tag.TAG_STRING) && !tag.contains(TAG_STACK, Tag.TAG_COMPOUND)) { if (tag.contains("item", Tag.TAG_STRING) && !tag.contains(TAG_STACK, Tag.TAG_COMPOUND)) {
@ -60,6 +61,7 @@ public record FrozenColorizer(ItemStack item, UUID owner) {
/** /**
* Gets a color with a minimum luminance applied. * Gets a color with a minimum luminance applied.
*
* @param time absolute world time in ticks * @param time absolute world time in ticks
* @param position a position for the icosahedron, a randomish number for particles. * @param position a position for the icosahedron, a randomish number for particles.
* @return an AARRGGBB color. * @return an AARRGGBB color.
@ -70,10 +72,11 @@ public record FrozenColorizer(ItemStack item, UUID owner) {
var r = FastColor.ARGB32.red(raw); var r = FastColor.ARGB32.red(raw);
var g = FastColor.ARGB32.green(raw); var g = FastColor.ARGB32.green(raw);
var b = FastColor.ARGB32.blue(raw); var b = FastColor.ARGB32.blue(raw);
double luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 0xFF; // Standard relative luminance calculation double luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 0xFF; // Standard relative luminance calculation
if (luminance < 0.05) { if (luminance < 0.05) {
int rawMod = Colorizer.morphBetweenColors(MINIMUM_LUMINANCE_COLOR_WHEEL, new Vec3(0.1, 0.1, 0.1), time / 20 / 20, position); int rawMod = Colorizer.morphBetweenColors(MINIMUM_LUMINANCE_COLOR_WHEEL, new Vec3(0.1, 0.1, 0.1),
time / 20 / 20, position);
r += FastColor.ARGB32.red(rawMod); r += FastColor.ARGB32.red(rawMod);
g += FastColor.ARGB32.green(rawMod); g += FastColor.ARGB32.green(rawMod);

View file

@ -9,16 +9,12 @@ public class HexConfig {
public interface CommonConfigAccess { public interface CommonConfigAccess {
int dustManaAmount(); int dustManaAmount();
int shardManaAmount(); int shardManaAmount();
int chargedCrystalManaAmount(); int chargedCrystalManaAmount();
double manaToHealthRate(); double manaToHealthRate();
int DEFAULT_DUST_MANA_AMOUNT = 10_000; int DEFAULT_DUST_MANA_AMOUNT = 10_000;
int DEFAULT_SHARD_MANA_AMOUNT = 50_000; int DEFAULT_SHARD_MANA_AMOUNT = 50_000;
int DEFAULT_CHARGED_MANA_AMOUNT = 100_000; int DEFAULT_CHARGED_MANA_AMOUNT = 100_000;
@ -28,8 +24,7 @@ public class HexConfig {
public interface ClientConfigAccess { public interface ClientConfigAccess {
double patternPointSpeedMultiplier(); double patternPointSpeedMultiplier();
boolean ctrlTogglesOffStrokeOrder(); boolean ctrlTogglesOffStrokeOrder();
double DEFAULT_PATTERN_POINT_SPEED_MULTIPLIER = 1; double DEFAULT_PATTERN_POINT_SPEED_MULTIPLIER = 1;

View file

@ -1,193 +0,0 @@
package at.petrak.hexcasting.api.player;
import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.api.mod.HexApiMessages;
import at.petrak.hexcasting.api.spell.casting.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
import at.petrak.hexcasting.api.utils.HexUtils;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.network.PacketDistributor;
import java.util.ArrayList;
import java.util.List;
public class HexPlayerDataHelper {
public static final String TAG_SENTINEL_EXISTS = "hexcasting:sentinel_exists";
public static final String TAG_SENTINEL_GREATER = "hexcasting:sentinel_extends_range";
public static final String TAG_SENTINEL_POSITION = "hexcasting:sentinel_position";
public static final String TAG_SENTINEL_DIMENSION = "hexcasting:sentinel_dimension";
public static final String TAG_COLOR = "hexcasting:colorizer";
public static final String TAG_FLIGHT_ALLOWED = "hexcasting:flight_allowed";
public static final String TAG_FLIGHT_TIME = "hexcasting:flight_time";
public static final String TAG_FLIGHT_ORIGIN = "hexcasting:flight_origin";
public static final String TAG_FLIGHT_DIMENSION = "hexcasting:flight_origin";
public static final String TAG_FLIGHT_RADIUS = "hexcasting:flight_radius";
public static final String TAG_HARNESS = "hexcasting:spell_harness";
public static final String TAG_PATTERNS = "hexcasting:spell_patterns";
@SubscribeEvent
public static void copyDataOnDeath(PlayerEvent.Clone evt) {
var eitherSidePlayer = evt.getPlayer();
// this apparently defines it in outside scope. the more you know.
if (!(eitherSidePlayer instanceof ServerPlayer player)) {
return;
}
var eitherSideProto = evt.getOriginal();
if (!(eitherSideProto instanceof ServerPlayer proto)) {
return;
}
// Copy data from this to new player
setFlight(player, getFlight(proto));
setSentinel(player, getSentinel(proto));
setColorizer(player, getColorizer(proto));
setHarness(player, getHarness(proto, InteractionHand.MAIN_HAND));
setPatterns(player, getPatterns(proto));
}
@SubscribeEvent
public static void syncDataOnLogin(PlayerEvent.PlayerLoggedInEvent evt) {
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
return;
}
syncSentinel(player);
syncColorizer(player);
}
@SubscribeEvent
public static void syncDataOnRejoin(PlayerEvent.PlayerRespawnEvent evt) {
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
return;
}
syncSentinel(player);
syncColorizer(player);
}
private static void syncSentinel(ServerPlayer player) {
HexApiMessages.getChannel().send(PacketDistributor.PLAYER.with(() -> player), HexApiMessages.getSentinelMessage(getSentinel(player)));
}
private static void syncColorizer(ServerPlayer player) {
HexApiMessages.getChannel().send(PacketDistributor.PLAYER.with(() -> player), HexApiMessages.getColorizerMessage(getColorizer(player)));
}
public static void setFlight(ServerPlayer player, FlightAbility flight) {
CompoundTag tag = player.getPersistentData();
tag.putBoolean(TAG_FLIGHT_ALLOWED, flight.allowed());
if (flight.allowed()) {
tag.putInt(TAG_FLIGHT_TIME, flight.timeLeft());
tag.put(TAG_FLIGHT_ORIGIN, HexUtils.serializeToNBT(flight.origin()));
tag.putString(TAG_FLIGHT_DIMENSION, flight.dimension().location().toString());
tag.putDouble(TAG_FLIGHT_RADIUS, flight.radius());
} else {
tag.remove(TAG_FLIGHT_TIME);
tag.remove(TAG_FLIGHT_ORIGIN);
tag.remove(TAG_FLIGHT_RADIUS);
}
}
public static void setColorizer(Player player, FrozenColorizer colorizer) {
CompoundTag tag = player.getPersistentData();
tag.put(TAG_COLOR, colorizer.serialize());
if (player instanceof ServerPlayer serverPlayer)
syncColorizer(serverPlayer);
}
public static void setSentinel(Player player, Sentinel sentinel) {
CompoundTag tag = player.getPersistentData();
tag.putBoolean(TAG_SENTINEL_EXISTS, sentinel.hasSentinel());
if (sentinel.hasSentinel()) {
tag.putBoolean(TAG_SENTINEL_GREATER, sentinel.extendsRange());
tag.put(TAG_SENTINEL_POSITION, HexUtils.serializeToNBT(sentinel.position()));
tag.putString(TAG_SENTINEL_DIMENSION, sentinel.dimension().location().toString());
} else {
tag.remove(TAG_SENTINEL_GREATER);
tag.remove(TAG_SENTINEL_POSITION);
tag.remove(TAG_SENTINEL_DIMENSION);
}
if (player instanceof ServerPlayer serverPlayer)
syncSentinel(serverPlayer);
}
public static void setHarness(ServerPlayer player, CastingHarness harness) {
player.getPersistentData().put(TAG_HARNESS, harness == null ? new CompoundTag() : harness.serializeToNBT());
}
public static void setPatterns(ServerPlayer player, List<ResolvedPattern> patterns) {
var listTag = new ListTag();
for (ResolvedPattern pattern : patterns) {
listTag.add(pattern.serializeToNBT());
}
player.getPersistentData().put(TAG_PATTERNS, listTag);
}
public static FlightAbility getFlight(ServerPlayer player) {
CompoundTag tag = player.getPersistentData();
boolean allowed = tag.getBoolean(TAG_FLIGHT_ALLOWED);
if (allowed) {
var timeLeft = tag.getInt(TAG_FLIGHT_TIME);
var origin = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_FLIGHT_ORIGIN));
var radius = tag.getDouble(TAG_FLIGHT_RADIUS);
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION)));
return new FlightAbility(true, timeLeft, dimension, origin, radius);
}
return FlightAbility.deny();
}
public static FrozenColorizer getColorizer(Player player) {
return FrozenColorizer.deserialize(player.getPersistentData().getCompound(TAG_COLOR));
}
public static Sentinel getSentinel(Player player) {
CompoundTag tag = player.getPersistentData();
var exists = tag.getBoolean(TAG_SENTINEL_EXISTS);
if (!exists)
return Sentinel.none();
var extendsRange = tag.getBoolean(TAG_SENTINEL_GREATER);
var position = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_SENTINEL_POSITION));
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION)));
return new Sentinel(true, extendsRange, position, dimension);
}
public static CastingHarness getHarness(ServerPlayer player, InteractionHand hand) {
var ctx = new CastingContext(player, hand);
return CastingHarness.DeserializeFromNBT(player.getPersistentData().getCompound(TAG_HARNESS), ctx);
}
public static List<ResolvedPattern> getPatterns(ServerPlayer player) {
ListTag patternsTag = player.getPersistentData().getList(TAG_PATTERNS, Tag.TAG_COMPOUND);
List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size());
for (int i = 0; i < patternsTag.size(); i++) {
patterns.add(ResolvedPattern.DeserializeFromNBT(patternsTag.getCompound(i)));
}
return patterns;
}
public static void clearCastingData(ServerPlayer player) {
player.getPersistentData().remove(TAG_HARNESS);
player.getPersistentData().remove(TAG_PATTERNS);
}
}

View file

@ -5,8 +5,10 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public record Sentinel(boolean hasSentinel, boolean extendsRange, Vec3 position, public record Sentinel(boolean hasSentinel, boolean extendsRange, Vec3 position,
ResourceKey<Level> dimension) { ResourceKey<Level> dimension) {
public static Sentinel none() { public static Sentinel none() {
return new Sentinel(false, false, Vec3.ZERO, Level.OVERWORLD); return new Sentinel(false, false, Vec3.ZERO, Level.OVERWORLD);
} }
} }

View file

@ -19,7 +19,7 @@ import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicRecord;
import at.petrak.hexcasting.common.entities.HexEntities; import at.petrak.hexcasting.common.entities.HexEntities;
import at.petrak.hexcasting.common.items.*; import at.petrak.hexcasting.common.items.*;
import at.petrak.hexcasting.common.items.magic.ItemManaBattery; import at.petrak.hexcasting.common.items.magic.ItemManaBattery;
import at.petrak.hexcasting.common.items.magic.ItemPackagedSpell; import at.petrak.hexcasting.common.items.magic.ItemPackagedHex;
import at.petrak.hexcasting.common.particles.HexParticles; import at.petrak.hexcasting.common.particles.HexParticles;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
@ -211,8 +211,8 @@ public class RegisterClientStuff {
(stack, level, holder, holderID) -> item.canWrite(stack, SpellDatum.make(Widget.NULL)) ? 0f : 1f); (stack, level, holder, holderID) -> item.canWrite(stack, SpellDatum.make(Widget.NULL)) ? 0f : 1f);
} }
private static void registerPackagedSpellOverrides(ItemPackagedSpell item) { private static void registerPackagedSpellOverrides(ItemPackagedHex item) {
ItemProperties.register(item, ItemPackagedSpell.HAS_PATTERNS_PRED, ItemProperties.register(item, ItemPackagedHex.HAS_PATTERNS_PRED,
(stack, level, holder, holderID) -> (stack, level, holder, holderID) ->
item.getPatterns(stack) != null ? 1f : 0f item.getPatterns(stack) != null ? 1f : 0f
); );

View file

@ -1,6 +1,5 @@
package at.petrak.hexcasting.common.blocks; package at.petrak.hexcasting.common.blocks;
import at.petrak.hexcasting.HexMod;
import at.petrak.hexcasting.api.circle.BlockAbstractImpetus; import at.petrak.hexcasting.api.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.api.spell.DatumType; import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.common.blocks.akashic.*; import at.petrak.hexcasting.common.blocks.akashic.*;
@ -15,6 +14,8 @@ import at.petrak.hexcasting.common.blocks.decoration.BlockAxis;
import at.petrak.hexcasting.common.blocks.decoration.BlockSconce; import at.petrak.hexcasting.common.blocks.decoration.BlockSconce;
import at.petrak.hexcasting.common.blocks.decoration.BlockStrippable; import at.petrak.hexcasting.common.blocks.decoration.BlockStrippable;
import at.petrak.hexcasting.common.items.HexItems; import at.petrak.hexcasting.common.items.HexItems;
import com.mojang.datafixers.util.Pair;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
@ -22,38 +23,28 @@ import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import java.util.function.Supplier; import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class HexBlocks { public class HexBlocks {
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, HexMod.MOD_ID); public static void registerBlocks(BiConsumer<Block, ResourceLocation> r) {
for (var e : BLOCKS.entrySet()) {
r.accept(e.getValue(), e.getKey());
}
}
public static final RegistryObject<Block> CONJURED_LIGHT = blockNoItem("conjured", public static void registerBlockItems(BiConsumer<Item, ResourceLocation> r) {
() -> new BlockConjuredLight( for (var e : BLOCK_ITEMS.entrySet()) {
BlockBehaviour.Properties.of(Material.GLASS, MaterialColor.NONE) r.accept(new BlockItem(e.getValue().getFirst(), e.getValue().getSecond()), e.getKey());
.sound(SoundType.AMETHYST) }
.lightLevel((state) -> 15) }
.noDrops()
.isValidSpawn(HexBlocks::never)
.instabreak()
.noCollission()
.isSuffocating(HexBlocks::never)
.isViewBlocking(HexBlocks::never)));
public static final RegistryObject<Block> CONJURED_BLOCK = blockNoItem("conjured_block", private static final Map<ResourceLocation, Block> BLOCKS = new LinkedHashMap<>();
() -> new BlockConjured( private static final Map<ResourceLocation, Pair<Block, Item.Properties>> BLOCK_ITEMS = new LinkedHashMap<>();
BlockBehaviour.Properties.of(Material.GLASS, MaterialColor.NONE)
.sound(SoundType.AMETHYST)
.lightLevel((state) -> 2)
.noDrops()
.isValidSpawn(HexBlocks::never)
.instabreak()
.noOcclusion()
.isSuffocating(HexBlocks::never)
.isViewBlocking(HexBlocks::never)));
private static BlockBehaviour.Properties slateish() { private static BlockBehaviour.Properties slateish() {
return BlockBehaviour.Properties return BlockBehaviour.Properties
@ -100,111 +91,140 @@ public class HexBlocks {
.isViewBlocking(HexBlocks::never); .isViewBlocking(HexBlocks::never);
} }
public static final RegistryObject<BlockSlate> SLATE = BLOCKS.register("slate", // we give these faux items so Patchi can have an item to view with
() -> new BlockSlate(slateish())); public static final Block CONJURED_LIGHT = blockItem("conjured",
new BlockConjuredLight(
BlockBehaviour.Properties.of(Material.GLASS, MaterialColor.NONE)
.sound(SoundType.AMETHYST)
.lightLevel((state) -> 15)
.noDrops()
.isValidSpawn(HexBlocks::never)
.instabreak()
.noCollission()
.isSuffocating(HexBlocks::never)
.isViewBlocking(HexBlocks::never)),
new Item.Properties());
public static final Block CONJURED_BLOCK = blockItem("conjured_block",
new BlockConjured(
BlockBehaviour.Properties.of(Material.GLASS, MaterialColor.NONE)
.sound(SoundType.AMETHYST)
.lightLevel((state) -> 2)
.noDrops()
.isValidSpawn(HexBlocks::never)
.instabreak()
.noOcclusion()
.isSuffocating(HexBlocks::never)
.isViewBlocking(HexBlocks::never)),
new Item.Properties());
public static final RegistryObject<BlockEmptyImpetus> EMPTY_IMPETUS = blockItem("empty_impetus", // "no" item because we add it manually
() -> new BlockEmptyImpetus(slateish())); public static final BlockSlate SLATE = blockNoItem("slate", new BlockSlate(slateish()));
public static final RegistryObject<BlockRightClickImpetus> IMPETUS_RIGHTCLICK = blockItem( public static final BlockEmptyImpetus EMPTY_IMPETUS = blockItem("empty_impetus", new BlockEmptyImpetus(slateish()));
"impetus_rightclick", public static final BlockRightClickImpetus IMPETUS_RIGHTCLICK = blockItem("impetus_rightclick",
() -> new BlockRightClickImpetus(slateish() new BlockRightClickImpetus(slateish()
.lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0)));
public static final RegistryObject<BlockLookingImpetus> IMPETUS_LOOK = blockItem( public static final BlockLookingImpetus IMPETUS_LOOK = blockItem("impetus_look",
"impetus_look", new BlockLookingImpetus(slateish()
() -> new BlockLookingImpetus(slateish()
.lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0)));
public static final RegistryObject<BlockStoredPlayerImpetus> IMPETUS_STOREDPLAYER = blockItem( public static final BlockStoredPlayerImpetus IMPETUS_STOREDPLAYER = blockItem("impetus_storedplayer",
"impetus_storedplayer", new BlockStoredPlayerImpetus(slateish()
() -> new BlockStoredPlayerImpetus(slateish()
.lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0)));
public static final RegistryObject<BlockEmptyDirectrix> EMPTY_DIRECTRIX = blockItem("empty_directrix", public static final BlockEmptyDirectrix EMPTY_DIRECTRIX = blockItem("empty_directrix",
() -> new BlockEmptyDirectrix(slateish())); new BlockEmptyDirectrix(slateish()));
public static final RegistryObject<BlockRedstoneDirectrix> DIRECTRIX_REDSTONE = blockItem("directrix_redstone", public static final BlockRedstoneDirectrix DIRECTRIX_REDSTONE = blockItem("directrix_redstone",
() -> new BlockRedstoneDirectrix(slateish())); new BlockRedstoneDirectrix(slateish()));
public static final RegistryObject<BlockAkashicRecord> AKASHIC_RECORD = blockItem("akashic_record", public static final BlockAkashicRecord AKASHIC_RECORD = blockItem("akashic_record",
() -> new BlockAkashicRecord(akashicWoodyHard().lightLevel(bs -> 15))); new BlockAkashicRecord(akashicWoodyHard().lightLevel(bs -> 15)));
public static final RegistryObject<BlockAkashicBookshelf> AKASHIC_BOOKSHELF = blockItem("akashic_bookshelf", public static final BlockAkashicBookshelf AKASHIC_BOOKSHELF = blockItem("akashic_bookshelf",
() -> new BlockAkashicBookshelf(akashicWoodyHard() new BlockAkashicBookshelf(akashicWoodyHard()
.lightLevel(bs -> (bs.getValue(BlockAkashicBookshelf.DATUM_TYPE) == DatumType.EMPTY) ? 0 : 4))); .lightLevel(bs -> (bs.getValue(BlockAkashicBookshelf.DATUM_TYPE) == DatumType.EMPTY) ? 0 : 4)));
public static final RegistryObject<BlockAkashicFloodfiller> AKASHIC_CONNECTOR = blockItem("akashic_connector", public static final BlockAkashicFloodfiller AKASHIC_CONNECTOR = blockItem("akashic_connector",
() -> new BlockAkashicFloodfiller(akashicWoodyHard().lightLevel(bs -> 10))); new BlockAkashicFloodfiller(akashicWoodyHard().lightLevel(bs -> 10)));
// Decoration?! // Decoration?!
public static final RegistryObject<Block> SLATE_BLOCK = blockItem("slate_block", public static final Block SLATE_BLOCK = blockItem("slate_block", new Block(slateish().strength(2f, 4f)));
() -> new Block(slateish().strength(2f, 4f))); public static final SandBlock AMETHYST_DUST_BLOCK = blockItem("amethyst_dust_block",
public static final RegistryObject<SandBlock> AMETHYST_DUST_BLOCK = blockItem("amethyst_dust_block", new SandBlock(0xff_b38ef3, BlockBehaviour.Properties.of(Material.SAND, MaterialColor.COLOR_PURPLE)
() -> new SandBlock(0xff_b38ef3, BlockBehaviour.Properties.of(Material.SAND, MaterialColor.COLOR_PURPLE)
.strength(0.5f).sound(SoundType.SAND))); .strength(0.5f).sound(SoundType.SAND)));
public static final RegistryObject<AmethystBlock> AMETHYST_TILES = blockItem("amethyst_tiles", public static final AmethystBlock AMETHYST_TILES = blockItem("amethyst_tiles",
() -> new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK)));
public static final RegistryObject<Block> SCROLL_PAPER = blockItem("scroll_paper", public static final Block SCROLL_PAPER = blockItem("scroll_paper",
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_WHITE), 100, 60)); new BlockBurns(papery(MaterialColor.TERRACOTTA_WHITE), 100, 60));
public static final RegistryObject<Block> ANCIENT_SCROLL_PAPER = blockItem("ancient_scroll_paper", public static final Block ANCIENT_SCROLL_PAPER = blockItem("ancient_scroll_paper",
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_ORANGE), 100, 60)); new BlockBurns(papery(MaterialColor.TERRACOTTA_ORANGE), 100, 60));
public static final RegistryObject<Block> SCROLL_PAPER_LANTERN = blockItem("scroll_paper_lantern", public static final Block SCROLL_PAPER_LANTERN = blockItem("scroll_paper_lantern",
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_WHITE).lightLevel($ -> 15), 100, 60)); new BlockBurns(papery(MaterialColor.TERRACOTTA_WHITE).lightLevel($ -> 15), 100, 60));
public static final RegistryObject<Block> ANCIENT_SCROLL_PAPER_LANTERN = blockItem( public static final Block ANCIENT_SCROLL_PAPER_LANTERN = blockItem(
"ancient_scroll_paper_lantern", "ancient_scroll_paper_lantern",
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_ORANGE).lightLevel($ -> 12), 100, 60)); new BlockBurns(papery(MaterialColor.TERRACOTTA_ORANGE).lightLevel($ -> 12), 100, 60));
public static final RegistryObject<BlockSconce> SCONCE = blockItem("amethyst_sconce", public static final BlockSconce SCONCE = blockItem("amethyst_sconce",
() -> new BlockSconce(BlockBehaviour.Properties.of(Material.AMETHYST, MaterialColor.COLOR_PURPLE) new BlockSconce(BlockBehaviour.Properties.of(Material.AMETHYST, MaterialColor.COLOR_PURPLE)
.sound(SoundType.AMETHYST) .sound(SoundType.AMETHYST)
.strength(1f) .strength(1f)
.lightLevel($ -> 15))); .lightLevel($ -> 15)));
public static final RegistryObject<BlockAxis> AKASHIC_LOG_STRIPPED = blockItem("akashic_log_stripped",
() -> new BlockAkashicLog(akashicWoody())); public static final BlockAxis AKASHIC_LOG_STRIPPED = blockItem("akashic_log_stripped",
public static final RegistryObject<BlockStrippable> AKASHIC_LOG = blockItem("akashic_log", new BlockAkashicLog(akashicWoody()));
() -> new BlockAkashicWood(akashicWoody(), AKASHIC_LOG_STRIPPED)); public static final BlockStrippable AKASHIC_LOG = blockItem("akashic_log",
public static final RegistryObject<Block> AKASHIC_WOOD_STRIPPED = blockItem("akashic_wood_stripped", new BlockAkashicWood(akashicWoody(), () -> AKASHIC_LOG_STRIPPED));
() -> new BlockBurns(akashicWoody(), 5, 5)); public static final Block AKASHIC_WOOD_STRIPPED = blockItem("akashic_wood_stripped",
public static final RegistryObject<BlockStrippable> AKASHIC_WOOD = blockItem("akashic_wood", new BlockBurns(akashicWoody(), 5, 5));
() -> new BlockStrippable(akashicWoody(), AKASHIC_WOOD_STRIPPED)); public static final BlockStrippable AKASHIC_WOOD = blockItem("akashic_wood",
public static final RegistryObject<Block> AKASHIC_PLANKS = blockItem("akashic_planks", new BlockStrippable(akashicWoody(), () -> AKASHIC_WOOD_STRIPPED));
() -> new BlockBurns(akashicWoody(), 20, 5)); public static final Block AKASHIC_PLANKS = blockItem("akashic_planks",
public static final RegistryObject<Block> AKASHIC_PANEL = blockItem("akashic_panel", new BlockBurns(akashicWoody(), 20, 5));
() -> new BlockBurns(akashicWoody(), 20, 5)); public static final Block AKASHIC_PANEL = blockItem("akashic_panel",
public static final RegistryObject<Block> AKASHIC_TILE = blockItem("akashic_tile", new BlockBurns(akashicWoody(), 20, 5));
() -> new BlockBurns(akashicWoody(), 20, 5)); public static final Block AKASHIC_TILE = blockItem("akashic_tile",
public static final RegistryObject<DoorBlock> AKASHIC_DOOR = blockItem("akashic_door", new BlockBurns(akashicWoody(), 20, 5));
() -> new DoorBlock(akashicWoody().noOcclusion())); // todo: mixin? AT?
public static final RegistryObject<TrapDoorBlock> AKASHIC_TRAPDOOR = blockItem("akashic_trapdoor", public static final DoorBlock AKASHIC_DOOR = blockItem("akashic_door",
() -> new TrapDoorBlock(akashicWoody().noOcclusion())); new DoorBlock(akashicWoody().noOcclusion()));
public static final RegistryObject<StairBlock> AKASHIC_STAIRS = blockItem("akashic_stairs", public static final TrapDoorBlock AKASHIC_TRAPDOOR = blockItem("akashic_trapdoor",
() -> new StairBlock(() -> AKASHIC_PLANKS.get().defaultBlockState(), akashicWoody().noOcclusion())); new TrapDoorBlock(akashicWoody().noOcclusion()));
public static final RegistryObject<SlabBlock> AKASHIC_SLAB = blockItem("akashic_slab", public static final StairBlock AKASHIC_STAIRS = blockItem("akashic_stairs",
() -> new SlabBlock(akashicWoody().noOcclusion())); new StairBlock(AKASHIC_PLANKS.defaultBlockState(), akashicWoody().noOcclusion()));
public static final RegistryObject<WoodButtonBlock> AKASHIC_BUTTON = blockItem("akashic_button", public static final SlabBlock AKASHIC_SLAB = blockItem("akashic_slab",
() -> new WoodButtonBlock(akashicWoody().noOcclusion())); new SlabBlock(akashicWoody().noOcclusion()));
public static final RegistryObject<PressurePlateBlock> AKASHIC_PRESSURE_PLATE = blockItem("akashic_pressure_plate", public static final WoodButtonBlock AKASHIC_BUTTON = blockItem("akashic_button",
() -> new PressurePlateBlock(PressurePlateBlock.Sensitivity.EVERYTHING, akashicWoody().noOcclusion())); new WoodButtonBlock(akashicWoody().noOcclusion()));
public static final RegistryObject<BlockAkashicLeaves> AKASHIC_LEAVES1 = blockItem("akashic_leaves1", public static final PressurePlateBlock AKASHIC_PRESSURE_PLATE = blockItem("akashic_pressure_plate",
() -> new BlockAkashicLeaves(leaves(MaterialColor.COLOR_PURPLE))); new PressurePlateBlock(PressurePlateBlock.Sensitivity.EVERYTHING, akashicWoody().noOcclusion()));
public static final RegistryObject<BlockAkashicLeaves> AKASHIC_LEAVES2 = blockItem("akashic_leaves2", public static final BlockAkashicLeaves AKASHIC_LEAVES1 = blockItem("akashic_leaves1",
() -> new BlockAkashicLeaves(leaves(MaterialColor.COLOR_BLUE))); new BlockAkashicLeaves(leaves(MaterialColor.COLOR_PURPLE)));
public static final RegistryObject<BlockAkashicLeaves> AKASHIC_LEAVES3 = blockItem("akashic_leaves3", public static final BlockAkashicLeaves AKASHIC_LEAVES2 = blockItem("akashic_leaves2",
() -> new BlockAkashicLeaves(leaves(MaterialColor.COLOR_YELLOW))); new BlockAkashicLeaves(leaves(MaterialColor.COLOR_BLUE)));
public static final BlockAkashicLeaves AKASHIC_LEAVES3 = blockItem("akashic_leaves3",
new BlockAkashicLeaves(leaves(MaterialColor.COLOR_YELLOW)));
private static boolean never(Object... args) { private static boolean never(Object... args) {
return false; return false;
} }
private static <T extends Block> RegistryObject<T> blockNoItem(String name, Supplier<T> block) { private static <T extends Block> T blockNoItem(String name, T block) {
return BLOCKS.register(name, block); var old = BLOCKS.put(modLoc(name), block);
if (old != null) {
throw new IllegalArgumentException("Typo? Duplicate id " + name);
}
return block;
} }
private static <T extends Block> RegistryObject<T> blockItem(String name, Supplier<T> block) { private static <T extends Block> T blockItem(String name, T block) {
blockNoItem(name, block);
return blockItem(name, block, HexItems.props()); return blockItem(name, block, HexItems.props());
} }
private static <T extends Block> RegistryObject<T> blockItem(String name, Supplier<T> block, private static <T extends Block> T blockItem(String name, T block, Item.Properties props) {
Item.Properties props) { blockNoItem(name, block);
var out = BLOCKS.register(name, block); var old = BLOCK_ITEMS.put(modLoc(name), new Pair<>(block, props));
HexItems.ITEMS.register(name, () -> new BlockItem(out.get(), props)); if (old != null) {
return out; throw new IllegalArgumentException("Typo? Duplicate id " + name);
}
return block;
} }
} }

View file

@ -12,11 +12,11 @@ import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
import at.petrak.hexcasting.api.utils.ManaHelper import at.petrak.hexcasting.api.utils.ManaHelper
import at.petrak.hexcasting.common.items.magic.ItemPackagedSpell import at.petrak.hexcasting.common.items.magic.ItemPackagedHex
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
class OpMakePackagedSpell<T : ItemPackagedSpell>(val itemType: T, val cost: Int) : SpellOperator { class OpMakePackagedSpell<T : ItemPackagedHex>(val itemType: T, val cost: Int) : SpellOperator {
override val argc = 2 override val argc = 2
override fun execute( override fun execute(
args: List<SpellDatum<*>>, args: List<SpellDatum<*>>,

View file

@ -1,29 +1,40 @@
package at.petrak.hexcasting.common.items; package at.petrak.hexcasting.common.items;
import at.petrak.hexcasting.HexMod; import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.common.blocks.HexBlocks; import at.petrak.hexcasting.common.blocks.HexBlocks;
import at.petrak.hexcasting.common.items.colorizer.ItemDyeColorizer; import at.petrak.hexcasting.common.items.colorizer.ItemDyeColorizer;
import at.petrak.hexcasting.common.items.colorizer.ItemPrideColorizer; import at.petrak.hexcasting.common.items.colorizer.ItemPrideColorizer;
import at.petrak.hexcasting.common.items.colorizer.ItemUUIDColorizer; import at.petrak.hexcasting.common.items.colorizer.ItemUUIDColorizer;
import at.petrak.hexcasting.common.items.magic.*; import at.petrak.hexcasting.common.items.magic.*;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.food.FoodProperties; import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
// https://github.com/VazkiiMods/Botania/blob/2c4f7fdf9ebf0c0afa1406dfe1322841133d75fa/Common/src/main/java/vazkii/botania/common/item/ModItems.java
public class HexItems { public class HexItems {
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, HexMod.MOD_ID); public static void registerItems(BiConsumer<Item, ResourceLocation> r) {
public static final CreativeModeTab TAB = new CreativeModeTab(HexMod.MOD_ID) { for (var e : ITEMS.entrySet()) {
r.accept(e.getValue(), e.getKey());
}
}
private static final Map<ResourceLocation, Item> ITEMS = new LinkedHashMap<>(); // preserve insertion order
public static final CreativeModeTab TAB = new CreativeModeTab(HexAPI.MOD_ID) {
@Override @Override
public ItemStack makeIcon() { public ItemStack makeIcon() {
return new ItemStack(SPELLBOOK::get); return new ItemStack(SPELLBOOK);
} }
@Override @Override
@ -38,83 +49,64 @@ public class HexItems {
1_000_000_000, 1_000_000_000,
}; };
for (int manamount : manamounts) { for (int manamount : manamounts) {
var stack = new ItemStack(BATTERY.get()); var stack = new ItemStack(BATTERY);
items.add(ItemManaHolder.withMana(stack, manamount, manamount)); items.add(ItemManaHolder.withMana(stack, manamount, manamount));
} }
} }
}; };
public static final RegistryObject<ItemWand> WAND_OAK = ITEMS.register("wand_oak",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_SPRUCE = ITEMS.register("wand_spruce",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_BIRCH = ITEMS.register("wand_birch",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_JUNGLE = ITEMS.register("wand_jungle",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_ACACIA = ITEMS.register("wand_acacia",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_DARK_OAK = ITEMS.register("wand_dark_oak",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_CRIMSON = ITEMS.register("wand_crimson",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_WARPED = ITEMS.register("wand_warped",
() -> new ItemWand(unstackable()));
public static final RegistryObject<ItemWand> WAND_AKASHIC = ITEMS.register("wand_akashic",
() -> new ItemWand(unstackable()));
public static final RegistryObject<Item> AMETHYST_DUST = ITEMS.register("amethyst_dust", public static final Item AMETHYST_DUST = make("amethyst_dust", new Item(props()));
() -> new Item(props())); public static final Item CHARGED_AMETHYST = make("charged_amethyst", new Item(props()));
public static final RegistryObject<Item> CHARGED_AMETHYST = ITEMS.register("charged_amethyst",
() -> new Item(props()));
public static final RegistryObject<Item> SCRYING_LENS = ITEMS.register("lens", public static final ItemWand WAND_OAK = make("wand_oak", new ItemWand(unstackable()));
() -> new ItemLens(unstackable())); public static final ItemWand WAND_SPRUCE = make("wand_spruce", new ItemWand(unstackable()));
public static final RegistryObject<Item> SCROLL = ITEMS.register("scroll", public static final ItemWand WAND_BIRCH = make("wand_birch", new ItemWand(unstackable()));
() -> new ItemScroll(props())); public static final ItemWand WAND_JUNGLE = make("wand_jungle", new ItemWand(unstackable()));
public static final ItemWand WAND_ACACIA = make("wand_acacia", new ItemWand(unstackable()));
public static final ItemWand WAND_DARK_OAK = make("wand_dark_oak", new ItemWand(unstackable()));
public static final ItemWand WAND_CRIMSON = make("wand_crimson", new ItemWand(unstackable()));
public static final ItemWand WAND_WARPED = make("wand_warped", new ItemWand(unstackable()));
public static final ItemWand WAND_AKASHIC = make("wand_akashic", new ItemWand(unstackable()));
public static final RegistryObject<ItemFocus> FOCUS = ITEMS.register("focus", public static final ItemLens SCRYING_LENS = make("lens", new ItemLens(unstackable()));
() -> new ItemFocus(unstackable()));
public static final RegistryObject<ItemAbacus> ABACUS = ITEMS.register("abacus",
() -> new ItemAbacus(unstackable()));
public static final RegistryObject<ItemSpellbook> SPELLBOOK = ITEMS.register("spellbook",
() -> new ItemSpellbook(unstackable()));
public static final RegistryObject<ItemCypher> CYPHER = ITEMS.register("cypher", public static final ItemAbacus ABACUS = make("abacus", new ItemAbacus(unstackable()));
() -> new ItemCypher(unstackable())); public static final ItemFocus FOCUS = make("focus", new ItemFocus(unstackable()));
public static final RegistryObject<ItemTrinket> TRINKET = ITEMS.register("trinket", public static final ItemSpellbook SPELLBOOK = make("spellbook", new ItemSpellbook(unstackable()));
() -> new ItemTrinket(unstackable()));
public static final RegistryObject<ItemArtifact> ARTIFACT = ITEMS.register("artifact",
() -> new ItemArtifact(unstackable()));
public static final RegistryObject<ItemManaBattery> BATTERY = ITEMS.register("battery", public static final ItemCypher CYPHER = make("cypher", new ItemCypher(unstackable()));
() -> new ItemManaBattery(new Item.Properties().stacksTo(1))); public static final ItemTrinket TRINKET = make("trinket", new ItemTrinket(unstackable()));
public static final ItemArtifact ARTIFACT = make("artifact", new ItemArtifact(unstackable()));
public static final EnumMap<DyeColor, RegistryObject<ItemDyeColorizer>> DYE_COLORIZERS = new EnumMap<>(
public static final ItemScroll SCROLL = make("scroll", new ItemScroll(props()));
public static final ItemSlate SLATE = make("slate", new ItemSlate(HexBlocks.SLATE, props()));
public static final ItemManaBattery BATTERY = make("battery",
new ItemManaBattery(new Item.Properties().stacksTo(1)));
public static final EnumMap<DyeColor, ItemDyeColorizer> DYE_COLORIZERS = new EnumMap<>(
DyeColor.class); DyeColor.class);
public static final RegistryObject<ItemPrideColorizer>[] PRIDE_COLORIZERS = new RegistryObject[14]; public static final ItemPrideColorizer[] PRIDE_COLORIZERS = new ItemPrideColorizer[14];
static { static {
for (var dye : DyeColor.values()) { for (var dye : DyeColor.values()) {
DYE_COLORIZERS.put(dye, ITEMS.register("dye_colorizer_" + dye.getName(), DYE_COLORIZERS.put(dye, make("dye_colorizer_" + dye.getName(), new ItemDyeColorizer(dye, unstackable())));
() -> new ItemDyeColorizer(dye, unstackable())));
} }
for (int i = 0; i < PRIDE_COLORIZERS.length; i++) { for (int i = 0; i < PRIDE_COLORIZERS.length; i++) {
final var finalI = i; PRIDE_COLORIZERS[i] = make("pride_colorizer_" + i, new ItemPrideColorizer(i, unstackable()));
PRIDE_COLORIZERS[i] = ITEMS.register("pride_colorizer_" + i,
() -> new ItemPrideColorizer(finalI, unstackable()));
} }
} }
public static final RegistryObject<Item> UUID_COLORIZER = ITEMS.register("uuid_colorizer", public static final Item UUID_COLORIZER = make("uuid_colorizer", new ItemUUIDColorizer(unstackable()));
() -> new ItemUUIDColorizer(unstackable()));
// BUFF SANDVICH // BUFF SANDVICH
public static final RegistryObject<Item> SUBMARINE_SANDWICH = ITEMS.register("sub_sandwich", public static final Item SUBMARINE_SANDWICH = make("sub_sandwich",
() -> new Item(props().food(new FoodProperties.Builder().nutrition(14).saturationMod(1.2f).build()))); new Item(props().food(new FoodProperties.Builder().nutrition(14).saturationMod(1.2f).build())));
public static final RegistryObject<ItemSlate> SLATE = ITEMS.register("slate", //
() -> new ItemSlate(HexBlocks.SLATE.get(), props()));
public static Item.Properties props() { public static Item.Properties props() {
return new Item.Properties().tab(TAB); return new Item.Properties().tab(TAB);
@ -123,4 +115,16 @@ public class HexItems {
public static Item.Properties unstackable() { public static Item.Properties unstackable() {
return props().stacksTo(1); return props().stacksTo(1);
} }
private static <T extends Item> T make(ResourceLocation id, T item) {
var old = ITEMS.put(id, item);
if (old != null) {
throw new IllegalArgumentException("Typo? Duplicate id " + id);
}
return item;
}
private static <T extends Item> T make(String id, T item) {
return make(modLoc(id), item);
}
} }

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.common.items.colorizer; package at.petrak.hexcasting.common.items.colorizer;
import at.petrak.hexcasting.api.cap.Colorizer; import at.petrak.hexcasting.api.addldata.Colorizer;
import at.petrak.hexcasting.api.item.ColorizerItem; import at.petrak.hexcasting.api.item.ColorizerItem;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.common.items.colorizer; package at.petrak.hexcasting.common.items.colorizer;
import at.petrak.hexcasting.api.cap.Colorizer; import at.petrak.hexcasting.api.addldata.Colorizer;
import at.petrak.hexcasting.api.item.ColorizerItem; import at.petrak.hexcasting.api.item.ColorizerItem;
import at.petrak.paucal.api.contrib.Contributors; import at.petrak.paucal.api.contrib.Contributors;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.items.magic;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class ItemArtifact extends ItemPackagedSpell { public class ItemArtifact extends ItemPackagedHex {
public ItemArtifact(Properties pProperties) { public ItemArtifact(Properties pProperties) {
super(pProperties); super(pProperties);
} }

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.items.magic;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class ItemCypher extends ItemPackagedSpell { public class ItemCypher extends ItemPackagedHex {
public ItemCypher(Properties pProperties) { public ItemCypher(Properties pProperties) {
super(pProperties); super(pProperties);
} }

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.items.magic; package at.petrak.hexcasting.common.items.magic;
import at.petrak.hexcasting.HexMod; import at.petrak.hexcasting.HexMod;
import at.petrak.hexcasting.api.item.SpellHolderItem; import at.petrak.hexcasting.api.item.HexHolderItem;
import at.petrak.hexcasting.api.spell.casting.CastingContext; import at.petrak.hexcasting.api.spell.casting.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness; import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.common.lib.HexSounds; import at.petrak.hexcasting.common.lib.HexSounds;
@ -28,11 +28,11 @@ import java.util.List;
/** /**
* Item that holds a list of patterns in it ready to be cast * Item that holds a list of patterns in it ready to be cast
*/ */
public abstract class ItemPackagedSpell extends ItemManaHolder implements SpellHolderItem { public abstract class ItemPackagedHex extends ItemManaHolder implements HexHolderItem {
public static final String TAG_PATTERNS = "patterns"; public static final String TAG_PATTERNS = "patterns";
public static final ResourceLocation HAS_PATTERNS_PRED = new ResourceLocation(HexMod.MOD_ID, "has_patterns"); public static final ResourceLocation HAS_PATTERNS_PRED = new ResourceLocation(HexMod.MOD_ID, "has_patterns");
public ItemPackagedSpell(Properties pProperties) { public ItemPackagedHex(Properties pProperties) {
super(pProperties); super(pProperties);
} }
@ -70,14 +70,14 @@ public abstract class ItemPackagedSpell extends ItemManaHolder implements SpellH
for (HexPattern pat : patterns) for (HexPattern pat : patterns)
patsTag.add(pat.serializeToNBT()); patsTag.add(pat.serializeToNBT());
stack.getOrCreateTag().put(ItemPackagedSpell.TAG_PATTERNS, patsTag); stack.getOrCreateTag().put(ItemPackagedHex.TAG_PATTERNS, patsTag);
withMana(stack, mana, mana); withMana(stack, mana, mana);
} }
@Override @Override
public void clearPatterns(ItemStack stack) { public void clearPatterns(ItemStack stack) {
stack.removeTagKey(ItemPackagedSpell.TAG_PATTERNS); stack.removeTagKey(ItemPackagedHex.TAG_PATTERNS);
withMana(stack, 0, 0); withMana(stack, 0, 0);
} }

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.items.magic;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class ItemTrinket extends ItemPackagedSpell { public class ItemTrinket extends ItemPackagedHex {
public ItemTrinket(Properties pProperties) { public ItemTrinket(Properties pProperties) {
super(pProperties); super(pProperties);
} }

View file

@ -1,9 +0,0 @@
package at.petrak.hexcasting.common.lib;
/**
* Tags, capability keys, etc that need to be used in more than one place
* (for example, across platforms, or between an item and block).
*/
public class HexStringKeys {
public static final String BRAINSWEPT = "hexcasting:brainswept";
}

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.HexMod;
import at.petrak.hexcasting.common.blocks.HexBlocks; import at.petrak.hexcasting.common.blocks.HexBlocks;
import at.petrak.hexcasting.common.items.*; import at.petrak.hexcasting.common.items.*;
import at.petrak.hexcasting.common.items.magic.ItemManaBattery; import at.petrak.hexcasting.common.items.magic.ItemManaBattery;
import at.petrak.hexcasting.common.items.magic.ItemPackagedSpell; import at.petrak.hexcasting.common.items.magic.ItemPackagedHex;
import at.petrak.paucal.api.datagen.PaucalItemModelProvider; import at.petrak.paucal.api.datagen.PaucalItemModelProvider;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -180,11 +180,11 @@ public class HexItemModels extends PaucalItemModelProvider {
simpleItem(modLoc(name + "_filled")); simpleItem(modLoc(name + "_filled"));
getBuilder(item.getRegistryName().getPath()) getBuilder(item.getRegistryName().getPath())
.override() .override()
.predicate(ItemPackagedSpell.HAS_PATTERNS_PRED, -0.01f) .predicate(ItemPackagedHex.HAS_PATTERNS_PRED, -0.01f)
.model(new ModelFile.UncheckedModelFile(modLoc("item/" + name))) .model(new ModelFile.UncheckedModelFile(modLoc("item/" + name)))
.end() .end()
.override() .override()
.predicate(ItemPackagedSpell.HAS_PATTERNS_PRED, 1f - 0.01f) .predicate(ItemPackagedHex.HAS_PATTERNS_PRED, 1f - 0.01f)
.model(new ModelFile.UncheckedModelFile(modLoc("item/" + name + "_filled"))) .model(new ModelFile.UncheckedModelFile(modLoc("item/" + name + "_filled")))
.end(); .end();
} }

View file

@ -1,13 +1,23 @@
package at.petrak.hexcasting.xplat; package at.petrak.hexcasting.xplat;
import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.api.player.FlightAbility;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
import at.petrak.hexcasting.common.command.PatternResLocArgument; import at.petrak.hexcasting.common.command.PatternResLocArgument;
import at.petrak.hexcasting.common.network.IMessage; import at.petrak.hexcasting.common.network.IMessage;
import at.petrak.hexcasting.common.network.MsgColorizerUpdateAck;
import at.petrak.hexcasting.common.network.MsgSentinelStatusUpdateAck;
import net.minecraft.commands.synchronization.ArgumentTypes; import net.minecraft.commands.synchronization.ArgumentTypes;
import net.minecraft.commands.synchronization.EmptyArgumentSerializer; import net.minecraft.commands.synchronization.EmptyArgumentSerializer;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import java.util.List;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -16,14 +26,47 @@ public interface IXplatAbstractions {
boolean isPhysicalClient(); boolean isPhysicalClient();
void brainsweep(LivingEntity e);
boolean isBrainswept(LivingEntity e);
void sendPacketToPlayer(ServerPlayer target, IMessage packet); void sendPacketToPlayer(ServerPlayer target, IMessage packet);
void sendPacketToServer(IMessage packet); void sendPacketToServer(IMessage packet);
// Things that used to be caps
void brainsweep(LivingEntity e);
void setColorizer(Player target, FrozenColorizer colorizer);
void setSentinel(Player target, Sentinel sentinel);
void setFlight(ServerPlayer target, FlightAbility flight);
void setHarness(ServerPlayer target, CastingHarness harness);
void setPatterns(ServerPlayer target, List<ResolvedPattern> patterns);
boolean isBrainswept(LivingEntity e);
FlightAbility getFlight(ServerPlayer player);
FrozenColorizer getColorizer(Player player);
Sentinel getSentinel(Player player);
CastingHarness getHarness(ServerPlayer player, InteractionHand hand);
List<ResolvedPattern> getPatterns(ServerPlayer player);
void clearCastingData(ServerPlayer player);
default void syncSentinel(ServerPlayer player) {
this.sendPacketToPlayer(player, new MsgSentinelStatusUpdateAck(this.getSentinel(player)));
}
default void syncColorizer(ServerPlayer player) {
this.sendPacketToPlayer(player, new MsgColorizerUpdateAck(this.getColorizer(player)));
}
default void init() { default void init() {
HexAPI.LOGGER.info("Hello Hexcasting! This is {}!", this.platform()); HexAPI.LOGGER.info("Hello Hexcasting! This is {}!", this.platform());

View file

@ -9,6 +9,9 @@ archivesBaseName = "${modName}-fabric-${minecraftVersion}"
repositories { repositories {
mavenCentral() mavenCentral()
maven { url "https://maven.shedaniel.me/" } maven { url "https://maven.shedaniel.me/" }
maven {
url 'https://ladysnake.jfrog.io/artifactory/mods'
}
} }
dependencies { dependencies {
@ -21,11 +24,12 @@ dependencies {
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
// compileOnly fg.deobf("at.petra-k.paucal:paucal-$minecraftVersion:$paucalVersion")
modImplementation("vazkii.patchouli:Patchouli:$minecraftVersion-$patchouliVersion:api") modImplementation("vazkii.patchouli:Patchouli:$minecraftVersion-$patchouliVersion:api")
modImplementation("net.fabricmc:fabric-language-kotlin:1.7.4+kotlin.1.6.21") modImplementation("net.fabricmc:fabric-language-kotlin:1.7.4+kotlin.1.6.21")
implementation "me.zeroeightsix:fiber:$fiberVersion" implementation "me.zeroeightsix:fiber:$fiberVersion"
modImplementation "dev.onyxstudios.cardinal-components-api:cardinal-components-api:$cardinalComponentsVersion"
} }
loom { loom {

View file

@ -1 +1,2 @@
fiberVersion=0.23.0-2 fiberVersion=0.23.0-2
cardinalComponentsVersion=4.1.4

View file

@ -1,12 +1,36 @@
import at.petrak.hexcasting.common.blocks.HexBlocks
import at.petrak.hexcasting.common.items.HexItems
import at.petrak.hexcasting.common.misc.Brainsweeping
import at.petrak.hexcasting.fabric.FabricHexConfig import at.petrak.hexcasting.fabric.FabricHexConfig
import at.petrak.hexcasting.fabric.network.FabricPacketHandler import at.petrak.hexcasting.fabric.network.FabricPacketHandler
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.fabricmc.api.ModInitializer import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.event.player.UseEntityCallback
import net.minecraft.core.Registry
import net.minecraft.resources.ResourceLocation
import java.util.function.BiConsumer
object FabricHexInitializer : ModInitializer { object FabricHexInitializer : ModInitializer {
override fun onInitialize() { override fun onInitialize() {
IXplatAbstractions.INSTANCE.init() IXplatAbstractions.INSTANCE.init()
FabricPacketHandler.init() FabricPacketHandler.init()
FabricHexConfig.setup() FabricHexConfig.setup()
initListeners()
initRegistries()
} }
fun initListeners() {
UseEntityCallback.EVENT.register(Brainsweeping::tradeWithVillager)
}
fun initRegistries() {
HexBlocks.registerBlocks(bind(Registry.BLOCK))
HexBlocks.registerBlockItems(bind(Registry.ITEM))
HexItems.registerItems(bind(Registry.ITEM))
}
private fun <T> bind(registry: Registry<in T>): BiConsumer<T, ResourceLocation> =
BiConsumer<T, ResourceLocation> { t, id -> Registry.register(registry, id, t) }
} }

View file

@ -0,0 +1,37 @@
package at.petrak.hexcasting.fabric.cc;
import dev.onyxstudios.cca.api.v3.component.Component;
import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.LivingEntity;
public class CCBrainswept implements Component, AutoSyncedComponent {
public static final String TAG_BRAINSWEPT = "brainswept";
private final LivingEntity owner;
public CCBrainswept(LivingEntity owner) {
this.owner = owner;
}
private boolean brainswept = false;
public boolean isBrainswept() {
return this.brainswept;
}
public void setBrainswept(boolean brainswept) {
this.brainswept = brainswept;
HexCardinalComponents.BRAINSWEPT.sync(this.owner);
}
@Override
public void readFromNbt(CompoundTag tag) {
this.brainswept = tag.getBoolean(TAG_BRAINSWEPT);
}
@Override
public void writeToNbt(CompoundTag tag) {
tag.putBoolean(TAG_BRAINSWEPT, this.brainswept);
}
}

View file

@ -0,0 +1,36 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.addldata.Colorizer;
import at.petrak.hexcasting.api.item.ColorizerItem;
import dev.onyxstudios.cca.api.v3.item.ItemComponent;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import java.util.UUID;
/**
* The colorizer itself
*/
public abstract class CCColorizer extends ItemComponent implements Colorizer {
public CCColorizer(ItemStack stack) {
super(stack, HexCardinalComponents.COLORIZER);
}
public static class ItemBased extends CCColorizer {
private final ColorizerItem item;
public ItemBased(ItemStack owner) {
super(owner);
var item = owner.getItem();
if (!(item instanceof ColorizerItem col)) {
throw new IllegalStateException("item is not a colorizer: " + owner);
}
this.item = col;
}
@Override
public int color(UUID owner, float time, Vec3 position) {
return item.color(this.stack, owner, time, position);
}
}
}

View file

@ -0,0 +1,66 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.addldata.DataHolder;
import at.petrak.hexcasting.api.item.DataHolderItem;
import at.petrak.hexcasting.api.spell.SpellDatum;
import dev.onyxstudios.cca.api.v3.item.ItemComponent;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
public abstract class CCDataHolder extends ItemComponent implements DataHolder {
public CCDataHolder(ItemStack stack) {
super(stack, HexCardinalComponents.DATA_HOLDER);
}
public static class ItemBased extends CCDataHolder {
private final DataHolderItem dataHolder;
public ItemBased(ItemStack stack) {
super(stack);
if (!(stack.getItem() instanceof DataHolderItem data)) {
throw new IllegalStateException("item is not a data holder: " + stack);
}
this.dataHolder = data;
}
@Override
public @Nullable CompoundTag readRawDatum() {
return this.dataHolder.readDatumTag(this.stack);
}
@Override
public boolean writeDatum(@Nullable SpellDatum<?> datum, boolean simulate) {
var canWrite = this.dataHolder.canWrite(this.stack, datum);
if (!canWrite) {
return false;
}
if (!simulate) {
this.dataHolder.writeDatum(this.stack, datum);
}
return true;
}
}
public static class Static extends CCDataHolder {
private final Function<ItemStack, SpellDatum<?>> provider;
public Static(ItemStack stack, Function<ItemStack, SpellDatum<?>> provider) {
super(stack);
this.provider = provider;
}
@Override
public @Nullable CompoundTag readRawDatum() {
SpellDatum<?> datum = this.provider.apply(this.stack);
return datum == null ? null : datum.serializeToNBT();
}
@Override
public boolean writeDatum(@Nullable SpellDatum<?> datum, boolean simulate) {
return false;
}
}
}

View file

@ -0,0 +1,41 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.misc.FrozenColorizer;
import dev.onyxstudios.cca.api.v3.component.Component;
import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
/**
* Holds the colorizer item favored by the player
*/
public class CCFavoredColorizer implements Component, AutoSyncedComponent {
public static final String TAG_COLORIZER = "colorizer";
private final Player owner;
public CCFavoredColorizer(Player owner) {
this.owner = owner;
}
private FrozenColorizer colorizer = FrozenColorizer.DEFAULT.get();
public FrozenColorizer getColorizer() {
return colorizer;
}
public void setColorizer(FrozenColorizer colorizer) {
this.colorizer = colorizer;
HexCardinalComponents.FAVORED_COLORIZER.sync(this.owner);
}
@Override
public void readFromNbt(CompoundTag tag) {
this.colorizer = FrozenColorizer.deserialize(tag.getCompound(TAG_COLORIZER));
}
@Override
public void writeToNbt(CompoundTag tag) {
tag.put(TAG_COLORIZER, this.colorizer.serialize());
}
}

View file

@ -0,0 +1,63 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.player.FlightAbility;
import at.petrak.hexcasting.api.utils.HexUtils;
import dev.onyxstudios.cca.api.v3.component.Component;
import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
public class CCFlight implements Component, AutoSyncedComponent {
public static final String
TAG_ALLOWED = "allowed",
TAG_TIME_LEFT = "time_left",
TAG_DIMENSION = "dimension",
TAG_ORIGIN = "origin",
TAG_RADIUS = "radius";
private final Player owner;
private FlightAbility flight = FlightAbility.deny();
public CCFlight(Player owner) {
this.owner = owner;
}
public FlightAbility getFlight() {
return flight;
}
public void setFlight(FlightAbility flight) {
this.flight = flight;
HexCardinalComponents.FLIGHT.sync(this.owner);
}
@Override
public void readFromNbt(CompoundTag tag) {
var allowed = tag.getBoolean(TAG_ALLOWED);
if (!allowed) {
this.flight = FlightAbility.deny();
} else {
var timeLeft = tag.getInt(TAG_TIME_LEFT);
var dim = ResourceKey.create(Registry.DIMENSION_REGISTRY,
new ResourceLocation(tag.getString(TAG_DIMENSION)));
var origin = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_ORIGIN));
var radius = tag.getDouble(TAG_RADIUS);
this.flight = new FlightAbility(true, timeLeft, dim, origin, radius);
}
}
@Override
public void writeToNbt(CompoundTag tag) {
tag.putBoolean(TAG_ALLOWED, this.flight.allowed());
if (this.flight.allowed()) {
tag.putInt(TAG_TIME_LEFT, this.flight.timeLeft());
tag.putString(TAG_DIMENSION, this.flight.dimension().location().toString());
tag.put(TAG_ORIGIN, HexUtils.serializeToNBT(this.flight.origin()));
tag.putDouble(TAG_RADIUS, this.flight.radius());
}
}
}

View file

@ -0,0 +1,53 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.cap.HexHolder;
import at.petrak.hexcasting.api.item.HexHolderItem;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import dev.onyxstudios.cca.api.v3.item.ItemComponent;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* The colorizer itself
*/
public abstract class CCHexHolder extends ItemComponent implements HexHolder {
public CCHexHolder(ItemStack stack) {
super(stack, HexCardinalComponents.HEX_HOLDER);
}
public static class ItemBased extends CCHexHolder {
private final HexHolderItem spellHolder;
public ItemBased(ItemStack owner) {
super(owner);
var item = owner.getItem();
if (!(item instanceof HexHolderItem hexHolderItem)) {
throw new IllegalStateException("item is not a colorizer: " + owner);
}
this.spellHolder = hexHolderItem;
}
@Override
public boolean canDrawManaFromInventory() {
return this.spellHolder.canDrawManaFromInventory(this.stack);
}
@Override
public @Nullable List<HexPattern> getPatterns() {
return this.spellHolder.getPatterns(this.stack);
}
@Override
public void writePatterns(List<HexPattern> patterns, int mana) {
this.spellHolder.writePatterns(this.stack, patterns, mana);
}
@Override
public void clearPatterns() {
this.spellHolder.clearPatterns(this.stack);
}
}
}

View file

@ -0,0 +1,121 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.addldata.ManaHolder;
import at.petrak.hexcasting.api.item.ManaHolderItem;
import dev.onyxstudios.cca.api.v3.item.ItemComponent;
import net.minecraft.world.item.ItemStack;
import java.util.function.Supplier;
public abstract class CCManaHolder extends ItemComponent implements ManaHolder {
public CCManaHolder(ItemStack stack) {
super(stack, HexCardinalComponents.MANA_HOLDER);
}
public static class ItemBased extends CCManaHolder {
private final ManaHolderItem manaHolder;
public ItemBased(ItemStack stack) {
super(stack);
if (!(stack.getItem() instanceof ManaHolderItem mana)) {
throw new IllegalStateException("item is not a mana holder: " + stack);
}
this.manaHolder = mana;
}
@Override
public int getMana() {
return this.manaHolder.getMana(this.stack);
}
@Override
public int getMaxMana() {
return this.manaHolder.getMaxMana(this.stack);
}
@Override
public void setMana(int mana) {
this.manaHolder.setMana(this.stack, mana);
}
@Override
public boolean canRecharge() {
return this.manaHolder.canRecharge(this.stack);
}
@Override
public boolean canProvide() {
return this.manaHolder.manaProvider(this.stack);
}
@Override
public int getConsumptionPriority() {
return 40;
}
@Override
public boolean canConstructBattery() {
return false;
}
}
public static class Static extends CCManaHolder {
private final Supplier<Integer> baseWorth;
private final int consumptionPriority;
public Static(Supplier<Integer> baseWorth, int consumptionPriority, ItemStack stack) {
super(stack);
this.baseWorth = baseWorth;
this.consumptionPriority = consumptionPriority;
}
@Override
public int getMana() {
return baseWorth.get() * stack.getCount();
}
@Override
public int getMaxMana() {
return getMana();
}
@Override
public void setMana(int mana) {
// NO-OP
}
@Override
public boolean canRecharge() {
return false;
}
@Override
public boolean canProvide() {
return true;
}
@Override
public int getConsumptionPriority() {
return consumptionPriority;
}
@Override
public boolean canConstructBattery() {
return true;
}
@Override
public int withdrawMana(int cost, boolean simulate) {
int worth = baseWorth.get();
if (cost < 0) {
cost = worth * stack.getCount();
}
double itemsRequired = cost / (double) worth;
int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount());
if (!simulate) {
stack.shrink(itemsUsed);
}
return itemsUsed * worth;
}
}
}

View file

@ -0,0 +1,59 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.api.utils.HexUtils;
import dev.onyxstudios.cca.api.v3.component.Component;
import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
public class CCSentinel implements Component, AutoSyncedComponent {
public static final String
TAG_HAS_SENTINEL = "has_sentinel",
TAG_EXTENDS_RANGE = "extends_range",
TAG_POSITION = "position",
TAG_DIMENSION = "dimension";
private final Player owner;
private Sentinel sentinel = Sentinel.none();
public CCSentinel(Player owner) {
this.owner = owner;
}
public Sentinel getSentinel() {
return sentinel;
}
public void setSentinel(Sentinel sentinel) {
this.sentinel = sentinel;
HexCardinalComponents.SENTINEL.sync(this.owner);
}
@Override
public void readFromNbt(CompoundTag tag) {
var hasSentinel = tag.getBoolean(TAG_HAS_SENTINEL);
if (hasSentinel) {
var extendsRange = tag.getBoolean(TAG_EXTENDS_RANGE);
var position = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_POSITION));
var dim = ResourceKey.create(Registry.DIMENSION_REGISTRY,
new ResourceLocation(tag.getString(TAG_DIMENSION)));
this.sentinel = new Sentinel(true, extendsRange, position, dim);
} else {
this.sentinel = Sentinel.none();
}
}
@Override
public void writeToNbt(CompoundTag tag) {
tag.putBoolean(TAG_HAS_SENTINEL, this.sentinel.hasSentinel());
if (this.sentinel.hasSentinel()) {
tag.putBoolean(TAG_EXTENDS_RANGE, this.sentinel.extendsRange());
tag.put(TAG_POSITION, HexUtils.serializeToNBT(this.sentinel.position()));
tag.putString(TAG_DIMENSION, this.sentinel.dimension().location().toString());
}
}
}

View file

@ -0,0 +1,73 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.item.ColorizerItem;
import at.petrak.hexcasting.api.item.DataHolderItem;
import at.petrak.hexcasting.api.item.HexHolderItem;
import at.petrak.hexcasting.api.item.ManaHolderItem;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.spell.SpellDatum;
import at.petrak.hexcasting.common.items.HexItems;
import dev.onyxstudios.cca.api.v3.component.ComponentKey;
import dev.onyxstudios.cca.api.v3.component.ComponentRegistry;
import dev.onyxstudios.cca.api.v3.entity.EntityComponentFactoryRegistry;
import dev.onyxstudios.cca.api.v3.entity.EntityComponentInitializer;
import dev.onyxstudios.cca.api.v3.item.ItemComponentFactoryRegistry;
import dev.onyxstudios.cca.api.v3.item.ItemComponentInitializer;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class HexCardinalComponents implements EntityComponentInitializer, ItemComponentInitializer {
// entities
public static final ComponentKey<CCBrainswept> BRAINSWEPT = ComponentRegistry.getOrCreate(modLoc("brainswept"),
CCBrainswept.class);
public static final ComponentKey<CCFavoredColorizer> FAVORED_COLORIZER = ComponentRegistry.getOrCreate(
modLoc("favored_colorizer"), CCFavoredColorizer.class);
public static final ComponentKey<CCSentinel> SENTINEL = ComponentRegistry.getOrCreate(modLoc("sentinel"),
CCSentinel.class);
public static final ComponentKey<CCFlight> FLIGHT = ComponentRegistry.getOrCreate(modLoc("flight"),
CCFlight.class);
public static final ComponentKey<CCColorizer> COLORIZER = ComponentRegistry.getOrCreate(modLoc("colorizer"),
CCColorizer.class);
public static final ComponentKey<CCDataHolder> DATA_HOLDER = ComponentRegistry.getOrCreate(modLoc("data_holder"),
CCDataHolder.class);
public static final ComponentKey<CCManaHolder> MANA_HOLDER = ComponentRegistry.getOrCreate(modLoc("mana_holder"),
CCManaHolder.class);
public static final ComponentKey<CCHexHolder> HEX_HOLDER = ComponentRegistry.getOrCreate(modLoc("hex_holder"),
CCHexHolder.class);
@Override
public void registerEntityComponentFactories(EntityComponentFactoryRegistry registry) {
registry.registerFor(LivingEntity.class, BRAINSWEPT, CCBrainswept::new);
registry.registerFor(Player.class, FAVORED_COLORIZER, CCFavoredColorizer::new);
registry.registerFor(Player.class, SENTINEL, CCSentinel::new);
registry.registerFor(Player.class, FLIGHT, CCFlight::new);
}
@Override
public void registerItemComponentFactories(ItemComponentFactoryRegistry registry) {
registry.register(i -> i instanceof ColorizerItem, COLORIZER, CCColorizer.ItemBased::new);
registry.register(i -> i instanceof DataHolderItem, DATA_HOLDER, CCDataHolder.ItemBased::new);
// oh havoc, you think you're so funny
// the worst part is you're /right/
registry.register(Items.PUMPKIN_PIE, DATA_HOLDER, stack -> new CCDataHolder.Static(stack,
s -> SpellDatum.make(Math.PI * s.getCount())));
registry.register(i -> i instanceof ManaHolderItem, MANA_HOLDER, CCManaHolder.ItemBased::new);
registry.register(HexItems.AMETHYST_DUST, MANA_HOLDER, s -> new CCManaHolder.Static(
() -> HexConfig.common().dustManaAmount(), 30, s
));
registry.register(Items.AMETHYST_SHARD, MANA_HOLDER, s -> new CCManaHolder.Static(
() -> HexConfig.common().shardManaAmount(), 20, s
));
registry.register(HexItems.CHARGED_AMETHYST, MANA_HOLDER, s -> new CCManaHolder.Static(
() -> HexConfig.common().chargedCrystalManaAmount(), 10, s
));
registry.register(i -> i instanceof HexHolderItem, HEX_HOLDER, CCHexHolder.ItemBased::new);
}
}

View file

@ -1,10 +0,0 @@
package at.petrak.hexcasting.fabric.xplat;
import at.petrak.hexcasting.common.misc.Brainsweeping;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
public class FabricListenersSetup {
public static void init() {
UseEntityCallback.EVENT.register(Brainsweeping::tradeWithVillager);
}
}

View file

@ -23,6 +23,9 @@
], ],
"client": [ "client": [
{"adapter": "kotlin", "value": "at.petrak.hexcasting.FabricHexInitializer"} {"adapter": "kotlin", "value": "at.petrak.hexcasting.FabricHexInitializer"}
],
"cardinal-components": [
"at.petrak.hexcasting.fabric.cc.HexCardinalComponents"
] ]
}, },
"mixins": [ "mixins": [
@ -37,5 +40,19 @@
"fabric-language-kotlin": ">=1.7.4+kotlin.1.6.21", "fabric-language-kotlin": ">=1.7.4+kotlin.1.6.21",
"patchouli": ">=1.18.2-66", "patchouli": ">=1.18.2-66",
"paucal": ">=0.3.4" "paucal": ">=0.3.4"
},
"custom": {
"cardinal-components": [
"hexcasting:brainswept",
"hexcasting:favored_colorizer",
"hexcasting:sentinel",
"hexcasting:flight",
"hexcasting:colorizer",
"hexcasting:data_holder",
"hexcasting:mana_holder",
"hexcasting:hex_holder"
]
} }
} }

View file

@ -4,18 +4,31 @@ import at.petrak.hexcasting.api.HexAPI
import at.petrak.hexcasting.api.PatternRegistry import at.petrak.hexcasting.api.PatternRegistry
import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers
import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.common.blocks.HexBlocks
import at.petrak.hexcasting.common.items.HexItems
import at.petrak.hexcasting.common.misc.Brainsweeping
import at.petrak.hexcasting.forge.ForgeHexConfig import at.petrak.hexcasting.forge.ForgeHexConfig
import at.petrak.hexcasting.forge.cap.CapSyncers
import at.petrak.hexcasting.forge.network.ForgePacketHandler import at.petrak.hexcasting.forge.network.ForgePacketHandler
import at.petrak.hexcasting.forge.xplat.ForgeListenersSetup
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.resources.ResourceLocation
import net.minecraftforge.common.ForgeConfigSpec import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.event.RegistryEvent
import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteract
import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.ModLoadingContext import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod
import net.minecraftforge.fml.config.ModConfig import net.minecraftforge.fml.config.ModConfig
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext
import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.IForgeRegistry
import net.minecraftforge.registries.IForgeRegistryEntry
import org.apache.logging.log4j.Logger import org.apache.logging.log4j.Logger
import java.util.function.BiConsumer
import java.util.function.Consumer
@Mod(HexAPI.MOD_ID) @Mod(HexAPI.MOD_ID)
object ForgeHexInitializer { object ForgeHexInitializer {
@ -35,18 +48,38 @@ object ForgeHexInitializer {
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, serverConfig.right) ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, serverConfig.right)
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, clientConfig.right) ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, clientConfig.right)
initRegistry()
initListeners()
}
ForgeListenersSetup.init() fun initRegistry() {
ForgePacketHandler.init() bind(ForgeRegistries.BLOCKS, HexBlocks::registerBlocks)
bind(ForgeRegistries.ITEMS, HexBlocks::registerBlockItems)
/* bind(ForgeRegistries.ITEMS, HexItems::registerItems)
}
fun initListeners() {
// mod lifecycle // mod lifecycle
val modBus = thedarkcolour.kotlinforforge.forge.MOD_BUS val modBus = thedarkcolour.kotlinforforge.forge.MOD_BUS
// game events // game events
val evBus = thedarkcolour.kotlinforforge.forge.FORGE_BUS val evBus = thedarkcolour.kotlinforforge.forge.FORGE_BUS
modBus.register(this) modBus.addListener(this::commonSetup)
evBus.addListener { evt: EntityInteract ->
val res = Brainsweeping.tradeWithVillager(
evt.player, evt.world, evt.hand, evt.target,
null
)
if (res.consumesAction()) {
evt.isCanceled = true
evt.cancellationResult = res
}
}
evBus.register(CapSyncers::class.java)
/*
modBus.register(this)
// gotta do it at *some* point // gotta do it at *some* point
modBus.register(RegisterPatterns::class.java) modBus.register(RegisterPatterns::class.java)
modBus.register(HexDataGenerators::class.java) modBus.register(HexDataGenerators::class.java)
@ -81,13 +114,30 @@ object ForgeHexInitializer {
evBus.register(HexTooltips::class.java) evBus.register(HexTooltips::class.java)
} }
} }
*/ */
} }
private fun <T : IForgeRegistryEntry<T>> bind(
registry: IForgeRegistry<T>,
source: Consumer<BiConsumer<T, ResourceLocation>>
) {
FMLJavaModLoadingContext.get().modEventBus.addGenericListener(
registry.registrySuperType
) { event: RegistryEvent.Register<T> ->
val forgeRegistry = event.registry
source.accept { t, rl ->
t.registryName = rl
forgeRegistry.register(t)
}
}
}
@SubscribeEvent @SubscribeEvent
fun commonSetup(evt: FMLCommonSetupEvent) { fun commonSetup(evt: FMLCommonSetupEvent) {
evt.enqueueWork { HexAdvancementTriggers.registerTriggers() } evt.enqueueWork {
HexAdvancementTriggers.registerTriggers()
ForgePacketHandler.init()
}
} }
@JvmStatic @JvmStatic

View file

@ -0,0 +1,51 @@
package at.petrak.hexcasting.forge.cap;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
public class CapSyncers {
@SubscribeEvent
public static void copyDataOnDeath(PlayerEvent.Clone evt) {
var eitherSidePlayer = evt.getPlayer();
// this apparently defines it in outside scope. the more you know.
if (!(eitherSidePlayer instanceof ServerPlayer player)) {
return;
}
var eitherSideProto = evt.getOriginal();
if (!(eitherSideProto instanceof ServerPlayer proto)) {
return;
}
// Copy data from this to new player
var x = IXplatAbstractions.INSTANCE;
x.setFlight(player, x.getFlight(proto));
x.setSentinel(player, x.getSentinel(proto));
x.setColorizer(player, x.getColorizer(proto));
x.setHarness(player, x.getHarness(proto, InteractionHand.MAIN_HAND));
x.setPatterns(player, x.getPatterns(proto));
}
@SubscribeEvent
public static void syncDataOnLogin(PlayerEvent.PlayerLoggedInEvent evt) {
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
return;
}
IXplatAbstractions.INSTANCE.syncSentinel(player);
IXplatAbstractions.INSTANCE.syncColorizer(player);
}
@SubscribeEvent
public static void syncDataOnRejoin(PlayerEvent.PlayerRespawnEvent evt) {
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
return;
}
IXplatAbstractions.INSTANCE.syncSentinel(player);
IXplatAbstractions.INSTANCE.syncColorizer(player);
}
}

View file

@ -1,15 +1,18 @@
package at.petrak.hexcasting.common.lib; package at.petrak.hexcasting.forge.cap;
import at.petrak.hexcasting.api.cap.Colorizer; import at.petrak.hexcasting.api.addldata.Colorizer;
import at.petrak.hexcasting.api.cap.DataHolder; import at.petrak.hexcasting.api.addldata.DataHolder;
import at.petrak.hexcasting.api.cap.ManaHolder; import at.petrak.hexcasting.api.addldata.ManaHolder;
import at.petrak.hexcasting.api.cap.SpellHolder;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.item.*;
import at.petrak.hexcasting.api.spell.SpellDatum;
import at.petrak.hexcasting.api.cap.HexCapabilities; import at.petrak.hexcasting.api.cap.HexCapabilities;
import at.petrak.hexcasting.common.items.HexItems; import at.petrak.hexcasting.api.cap.HexHolder;
import at.petrak.hexcasting.api.item.ColorizerItem;
import at.petrak.hexcasting.api.item.DataHolderItem;
import at.petrak.hexcasting.api.item.ManaHolderItem;
import at.petrak.hexcasting.api.item.HexHolderItem;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.spell.SpellDatum;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.items.HexItems;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -17,8 +20,9 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.*; import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.common.util.NonNullSupplier; import net.minecraftforge.common.util.NonNullSupplier;
import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent;
@ -29,8 +33,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
public class HexCapabilityHandler { public class ForgeCapabilityHandler {
private static final ResourceLocation DATA_HOLDER_CAPABILITY = new ResourceLocation("hexcasting", "data_holder"); private static final ResourceLocation DATA_HOLDER_CAPABILITY = new ResourceLocation("hexcasting", "data_holder");
private static final ResourceLocation DATA_ITEM_CAPABILITY = new ResourceLocation("hexcasting", "data_item"); private static final ResourceLocation DATA_ITEM_CAPABILITY = new ResourceLocation("hexcasting", "data_item");
@ -43,40 +48,45 @@ public class HexCapabilityHandler {
public static void registerCaps(RegisterCapabilitiesEvent evt) { public static void registerCaps(RegisterCapabilitiesEvent evt) {
evt.register(ManaHolder.class); evt.register(ManaHolder.class);
evt.register(DataHolder.class); evt.register(DataHolder.class);
evt.register(SpellHolder.class); evt.register(HexHolder.class);
evt.register(Colorizer.class); evt.register(Colorizer.class);
} }
@SubscribeEvent @SubscribeEvent
public static void attachCaps(AttachCapabilitiesEvent<ItemStack> evt) { public static void attachCaps(AttachCapabilitiesEvent<ItemStack> evt) {
ItemStack stack = evt.getObject(); ItemStack stack = evt.getObject();
if (stack.getItem() instanceof ManaHolderItem holder) if (stack.getItem() instanceof ManaHolderItem holder) {
evt.addCapability(MANA_HOLDER_CAPABILITY, provide(HexCapabilities.MANA, evt.addCapability(MANA_HOLDER_CAPABILITY, provide(HexCapabilities.MANA,
() -> new ItemBasedManaHolder(holder, stack))); () -> new ItemBasedManaHolder(holder, stack)));
else if (stack.is(HexItems.AMETHYST_DUST.get())) } else if (stack.is(HexItems.AMETHYST_DUST)) {
evt.addCapability(MANA_ITEM_CAPABILITY, provide(HexCapabilities.MANA, evt.addCapability(MANA_ITEM_CAPABILITY, provide(HexCapabilities.MANA,
() -> new StaticManaHolder(HexConfig.dustManaAmount, 3, stack))); () -> new StaticManaHolder(() -> HexConfig.common().dustManaAmount(), 30, stack)));
else if (stack.is(Items.AMETHYST_SHARD)) } else if (stack.is(Items.AMETHYST_SHARD)) {
evt.addCapability(MANA_ITEM_CAPABILITY, provide(HexCapabilities.MANA, evt.addCapability(MANA_ITEM_CAPABILITY, provide(HexCapabilities.MANA,
() -> new StaticManaHolder(HexConfig.shardManaAmount, 2, stack))); () -> new StaticManaHolder(() -> HexConfig.common().shardManaAmount(), 20, stack)));
else if (stack.is(HexItems.CHARGED_AMETHYST.get())) } else if (stack.is(HexItems.CHARGED_AMETHYST)) {
evt.addCapability(MANA_ITEM_CAPABILITY, provide(HexCapabilities.MANA, evt.addCapability(MANA_ITEM_CAPABILITY, provide(HexCapabilities.MANA,
() -> new StaticManaHolder(HexConfig.chargedCrystalManaAmount, 1, stack))); () -> new StaticManaHolder(() -> HexConfig.common().chargedCrystalManaAmount(), 10, stack)));
}
if (stack.getItem() instanceof DataHolderItem holder) if (stack.getItem() instanceof DataHolderItem holder) {
evt.addCapability(DATA_HOLDER_CAPABILITY, provide(HexCapabilities.DATUM, evt.addCapability(DATA_HOLDER_CAPABILITY, provide(HexCapabilities.DATUM,
() -> new ItemBasedDataHolder(holder, stack))); () -> new ItemBasedDataHolder(holder, stack)));
else if (stack.is(Items.PUMPKIN_PIE)) // haha yes } else if (stack.is(Items.PUMPKIN_PIE)) // haha yes
{
evt.addCapability(DATA_ITEM_CAPABILITY, provide(HexCapabilities.DATUM, evt.addCapability(DATA_ITEM_CAPABILITY, provide(HexCapabilities.DATUM,
() -> new StaticDatumHolder((s) -> SpellDatum.make(Math.PI * s.getCount()), stack))); () -> new StaticDatumHolder((s) -> SpellDatum.make(Math.PI * s.getCount()), stack)));
}
if (stack.getItem() instanceof SpellHolderItem holder) if (stack.getItem() instanceof HexHolderItem holder) {
evt.addCapability(SPELL_HOLDER_CAPABILITY, provide(HexCapabilities.SPELL, evt.addCapability(SPELL_HOLDER_CAPABILITY, provide(HexCapabilities.SPELL,
() -> new ItemBasedSpellHolder(holder, stack))); () -> new ItemBasedHexHolder(holder, stack)));
}
if (stack.getItem() instanceof ColorizerItem colorizer) if (stack.getItem() instanceof ColorizerItem colorizer) {
evt.addCapability(COLORIZER_CAPABILITY, provide(HexCapabilities.COLOR, evt.addCapability(COLORIZER_CAPABILITY, provide(HexCapabilities.COLOR,
() -> new ItemBasedColorizer(colorizer, stack))); () -> new ItemBasedColorizer(colorizer, stack)));
}
} }
private static <CAP> SimpleProvider<CAP> provide(Capability<CAP> capability, NonNullSupplier<CAP> supplier) { private static <CAP> SimpleProvider<CAP> provide(Capability<CAP> capability, NonNullSupplier<CAP> supplier) {
@ -93,7 +103,7 @@ public class HexCapabilityHandler {
} }
} }
private record StaticManaHolder(ForgeConfigSpec.IntValue baseWorth, private record StaticManaHolder(Supplier<Integer> baseWorth,
int consumptionPriority, int consumptionPriority,
ItemStack stack) implements ManaHolder { ItemStack stack) implements ManaHolder {
@Override @Override
@ -134,12 +144,14 @@ public class HexCapabilityHandler {
@Override @Override
public int withdrawMana(int cost, boolean simulate) { public int withdrawMana(int cost, boolean simulate) {
int worth = baseWorth.get(); int worth = baseWorth.get();
if (cost < 0) if (cost < 0) {
cost = worth * stack.getCount(); cost = worth * stack.getCount();
}
double itemsRequired = cost / (double) worth; double itemsRequired = cost / (double) worth;
int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount()); int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount());
if (!simulate) if (!simulate) {
stack.shrink(itemsUsed); stack.shrink(itemsUsed);
}
return itemsUsed * worth; return itemsUsed * worth;
} }
} }
@ -174,7 +186,7 @@ public class HexCapabilityHandler {
@Override @Override
public int getConsumptionPriority() { public int getConsumptionPriority() {
return 4; return 40;
} }
@Override @Override
@ -189,7 +201,7 @@ public class HexCapabilityHandler {
} }
private record StaticDatumHolder(Function<ItemStack, SpellDatum<?>> provider, private record StaticDatumHolder(Function<ItemStack, SpellDatum<?>> provider,
ItemStack stack) implements DataHolder { ItemStack stack) implements DataHolder {
@Override @Override
public @Nullable CompoundTag readRawDatum() { public @Nullable CompoundTag readRawDatum() {
@ -228,16 +240,18 @@ public class HexCapabilityHandler {
@Override @Override
public boolean writeDatum(@Nullable SpellDatum<?> datum, boolean simulate) { public boolean writeDatum(@Nullable SpellDatum<?> datum, boolean simulate) {
if (!holder.canWrite(stack, datum)) if (!holder.canWrite(stack, datum)) {
return false; return false;
if (!simulate) }
if (!simulate) {
holder.writeDatum(stack, datum); holder.writeDatum(stack, datum);
}
return true; return true;
} }
} }
private record ItemBasedSpellHolder(SpellHolderItem holder, private record ItemBasedHexHolder(HexHolderItem holder,
ItemStack stack) implements SpellHolder { ItemStack stack) implements HexHolder {
@Override @Override
public boolean canDrawManaFromInventory() { public boolean canDrawManaFromInventory() {
@ -260,9 +274,8 @@ public class HexCapabilityHandler {
} }
} }
private record ItemBasedColorizer(ColorizerItem holder, public record ItemBasedColorizer(ColorizerItem holder,
ItemStack stack) implements Colorizer { ItemStack stack) implements Colorizer {
@Override @Override
public int color(UUID owner, float time, Vec3 position) { public int color(UUID owner, float time, Vec3 position) {
return holder.color(stack, owner, time, position); return holder.color(stack, owner, time, position);

View file

@ -1,20 +1,5 @@
package at.petrak.hexcasting.forge.xplat; package at.petrak.hexcasting.forge.xplat;
import at.petrak.hexcasting.common.misc.Brainsweeping;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
public class ForgeListenersSetup { public class ForgeListenersSetup {
public static void init() {
var evBus = MinecraftForge.EVENT_BUS;
evBus.addListener((PlayerInteractEvent.EntityInteract evt) -> {
var res = Brainsweeping.tradeWithVillager(evt.getPlayer(), evt.getWorld(), evt.getHand(), evt.getTarget(),
null);
if (res.consumesAction()) {
evt.setCanceled(true);
evt.setCancellationResult(res);
}
});
}
} }

View file

@ -1,23 +1,40 @@
package at.petrak.hexcasting.forge.xplat; package at.petrak.hexcasting.forge.xplat;
import at.petrak.hexcasting.common.lib.HexStringKeys; import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.api.player.FlightAbility;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.api.spell.casting.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.network.IMessage; import at.petrak.hexcasting.common.network.IMessage;
import at.petrak.hexcasting.common.network.MsgBrainsweepAck; import at.petrak.hexcasting.common.network.MsgBrainsweepAck;
import at.petrak.hexcasting.forge.network.ForgePacketHandler; import at.petrak.hexcasting.forge.network.ForgePacketHandler;
import at.petrak.hexcasting.mixin.AccessorLivingEntity; import at.petrak.hexcasting.mixin.AccessorLivingEntity;
import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.IXplatAbstractions;
import at.petrak.hexcasting.xplat.Platform; import at.petrak.hexcasting.xplat.Platform;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.Brain; import net.minecraft.world.entity.ai.Brain;
import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerDataHolder; import net.minecraft.world.entity.npc.VillagerDataHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import java.util.ArrayList;
import java.util.List;
public class ForgeXplatImpl implements IXplatAbstractions { public class ForgeXplatImpl implements IXplatAbstractions {
@Override @Override
public Platform platform() { public Platform platform() {
@ -32,7 +49,7 @@ public class ForgeXplatImpl implements IXplatAbstractions {
@Override @Override
public void brainsweep(LivingEntity entity) { public void brainsweep(LivingEntity entity) {
if (entity instanceof VillagerDataHolder) { if (entity instanceof VillagerDataHolder) {
entity.getPersistentData().putBoolean(HexStringKeys.BRAINSWEPT, true); entity.getPersistentData().putBoolean(TAG_BRAINSWEPT, true);
if (entity instanceof Mob mob) { if (entity instanceof Mob mob) {
mob.removeFreeWill(); mob.removeFreeWill();
@ -53,9 +70,128 @@ public class ForgeXplatImpl implements IXplatAbstractions {
} }
} }
@Override
public void setFlight(ServerPlayer player, FlightAbility flight) {
CompoundTag tag = player.getPersistentData();
tag.putBoolean(TAG_FLIGHT_ALLOWED, flight.allowed());
if (flight.allowed()) {
tag.putInt(TAG_FLIGHT_TIME, flight.timeLeft());
tag.put(TAG_FLIGHT_ORIGIN, HexUtils.serializeToNBT(flight.origin()));
tag.putString(TAG_FLIGHT_DIMENSION, flight.dimension().location().toString());
tag.putDouble(TAG_FLIGHT_RADIUS, flight.radius());
} else {
tag.remove(TAG_FLIGHT_TIME);
tag.remove(TAG_FLIGHT_ORIGIN);
tag.remove(TAG_FLIGHT_RADIUS);
}
}
@Override
public void setColorizer(Player player, FrozenColorizer colorizer) {
CompoundTag tag = player.getPersistentData();
tag.put(TAG_COLOR, colorizer.serialize());
if (player instanceof ServerPlayer serverPlayer) {
this.syncColorizer(serverPlayer);
}
}
@Override
public void setSentinel(Player player, Sentinel sentinel) {
CompoundTag tag = player.getPersistentData();
tag.putBoolean(TAG_SENTINEL_EXISTS, sentinel.hasSentinel());
if (sentinel.hasSentinel()) {
tag.putBoolean(TAG_SENTINEL_GREATER, sentinel.extendsRange());
tag.put(TAG_SENTINEL_POSITION, HexUtils.serializeToNBT(sentinel.position()));
tag.putString(TAG_SENTINEL_DIMENSION, sentinel.dimension().location().toString());
} else {
tag.remove(TAG_SENTINEL_GREATER);
tag.remove(TAG_SENTINEL_POSITION);
tag.remove(TAG_SENTINEL_DIMENSION);
}
if (player instanceof ServerPlayer serverPlayer) {
this.syncSentinel(serverPlayer);
}
}
@Override
public void setHarness(ServerPlayer player, CastingHarness harness) {
player.getPersistentData().put(TAG_HARNESS, harness == null ? new CompoundTag() : harness.serializeToNBT());
}
@Override
public void setPatterns(ServerPlayer player, List<ResolvedPattern> patterns) {
var listTag = new ListTag();
for (ResolvedPattern pattern : patterns) {
listTag.add(pattern.serializeToNBT());
}
player.getPersistentData().put(TAG_PATTERNS, listTag);
}
@Override @Override
public boolean isBrainswept(LivingEntity e) { public boolean isBrainswept(LivingEntity e) {
return e instanceof VillagerDataHolder && e.getPersistentData().getBoolean(HexStringKeys.BRAINSWEPT); return e instanceof VillagerDataHolder && e.getPersistentData().getBoolean(TAG_BRAINSWEPT);
}
@Override
public FlightAbility getFlight(ServerPlayer player) {
CompoundTag tag = player.getPersistentData();
boolean allowed = tag.getBoolean(TAG_FLIGHT_ALLOWED);
if (allowed) {
var timeLeft = tag.getInt(TAG_FLIGHT_TIME);
var origin = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_FLIGHT_ORIGIN));
var radius = tag.getDouble(TAG_FLIGHT_RADIUS);
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY,
new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION)));
return new FlightAbility(true, timeLeft, dimension, origin, radius);
}
return FlightAbility.deny();
}
@Override
public FrozenColorizer getColorizer(Player player) {
return FrozenColorizer.deserialize(player.getPersistentData().getCompound(TAG_COLOR));
}
@Override
public Sentinel getSentinel(Player player) {
CompoundTag tag = player.getPersistentData();
var exists = tag.getBoolean(TAG_SENTINEL_EXISTS);
if (!exists) {
return Sentinel.none();
}
var extendsRange = tag.getBoolean(TAG_SENTINEL_GREATER);
var position = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_SENTINEL_POSITION));
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY,
new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION)));
return new Sentinel(true, extendsRange, position, dimension);
}
@Override
public CastingHarness getHarness(ServerPlayer player, InteractionHand hand) {
var ctx = new CastingContext(player, hand);
return CastingHarness.DeserializeFromNBT(player.getPersistentData().getCompound(TAG_HARNESS), ctx);
}
@Override
public List<ResolvedPattern> getPatterns(ServerPlayer player) {
ListTag patternsTag = player.getPersistentData().getList(TAG_PATTERNS, Tag.TAG_COMPOUND);
List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size());
for (int i = 0; i < patternsTag.size(); i++) {
patterns.add(ResolvedPattern.DeserializeFromNBT(patternsTag.getCompound(i)));
}
return patterns;
}
@Override
public void clearCastingData(ServerPlayer player) {
player.getPersistentData().remove(TAG_HARNESS);
player.getPersistentData().remove(TAG_PATTERNS);
} }
@Override @Override
@ -67,4 +203,22 @@ public class ForgeXplatImpl implements IXplatAbstractions {
public void sendPacketToServer(IMessage packet) { public void sendPacketToServer(IMessage packet) {
ForgePacketHandler.getNetwork().sendToServer(packet); ForgePacketHandler.getNetwork().sendToServer(packet);
} }
public static final String TAG_BRAINSWEPT = "hexcasting:brainswept";
public static final String TAG_SENTINEL_EXISTS = "hexcasting:sentinel_exists";
public static final String TAG_SENTINEL_GREATER = "hexcasting:sentinel_extends_range";
public static final String TAG_SENTINEL_POSITION = "hexcasting:sentinel_position";
public static final String TAG_SENTINEL_DIMENSION = "hexcasting:sentinel_dimension";
public static final String TAG_COLOR = "hexcasting:colorizer";
public static final String TAG_FLIGHT_ALLOWED = "hexcasting:flight_allowed";
public static final String TAG_FLIGHT_TIME = "hexcasting:flight_time";
public static final String TAG_FLIGHT_ORIGIN = "hexcasting:flight_origin";
public static final String TAG_FLIGHT_DIMENSION = "hexcasting:flight_origin";
public static final String TAG_FLIGHT_RADIUS = "hexcasting:flight_radius";
public static final String TAG_HARNESS = "hexcasting:spell_harness";
public static final String TAG_PATTERNS = "hexcasting:spell_patterns";
} }