Skip to content

Commit

Permalink
refactor the spell system 🙀
Browse files Browse the repository at this point in the history
  • Loading branch information
reoseah committed Nov 3, 2024
1 parent 65dabe1 commit 3c7ec41
Show file tree
Hide file tree
Showing 64 changed files with 1,076 additions and 1,050 deletions.
53 changes: 27 additions & 26 deletions src/main/java/io/github/reoseah/magisterium/Magisterium.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import com.google.common.collect.ImmutableSet;
import io.github.reoseah.magisterium.block.*;
import io.github.reoseah.magisterium.data.ItemValuesLoader;
import io.github.reoseah.magisterium.data.effect.*;
import io.github.reoseah.magisterium.data.element.BookElement;
import io.github.reoseah.magisterium.data.SpellRecipe;
import io.github.reoseah.magisterium.data.element.*;
import io.github.reoseah.magisterium.item.BookmarkItem;
import io.github.reoseah.magisterium.item.SpellBookItem;
import io.github.reoseah.magisterium.item.SpellPageItem;
Expand All @@ -11,10 +15,8 @@
import io.github.reoseah.magisterium.network.StopUtterancePayload;
import io.github.reoseah.magisterium.network.UseBookmarkPayload;
import io.github.reoseah.magisterium.particle.MagisteriumParticles;
import io.github.reoseah.magisterium.recipe.*;
import io.github.reoseah.magisterium.screen.ArcaneTableScreenHandler;
import io.github.reoseah.magisterium.screen.SpellBookScreenHandler;
import io.github.reoseah.magisterium.spellbook.SpellDataLoader;
import io.github.reoseah.magisterium.world.MagisteriumPlaygrounds;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
Expand All @@ -24,7 +26,6 @@
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.impl.resource.loader.ResourceManagerHelperImpl;
import net.minecraft.block.LecternBlock;
import net.minecraft.block.entity.LecternBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
Expand All @@ -43,14 +44,12 @@
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Set;

public class Magisterium implements ModInitializer {
Expand All @@ -74,7 +73,6 @@ public void onInitialize() {
Registry.register(Registries.ITEM, "magisterium:glyphic_ignition_page", SpellPageItem.GLYPHIC_IGNITION);
Registry.register(Registries.ITEM, "magisterium:conflagrate_page", SpellPageItem.CONFLAGRATE);
Registry.register(Registries.ITEM, "magisterium:illusory_wall_page", SpellPageItem.ILLUSORY_WALL);
Registry.register(Registries.ITEM, "magisterium:unstable_charge_page", SpellPageItem.UNSTABLE_CHARGE);
Registry.register(Registries.ITEM, "magisterium:cold_snap_page", SpellPageItem.COLD_SNAP);
Registry.register(Registries.ITEM, "magisterium:arcane_lift_page", SpellPageItem.ARCANE_LIFT);
Registry.register(Registries.ITEM, "magisterium:dispel_magic_page", SpellPageItem.DISPEL_MAGIC);
Expand All @@ -96,7 +94,6 @@ public void onInitialize() {
entries.add(SpellPageItem.GLYPHIC_IGNITION);
entries.add(SpellPageItem.CONFLAGRATE);
entries.add(SpellPageItem.ILLUSORY_WALL);
// entries.add(SpellPageItem.UNSTABLE_CHARGE);
entries.add(SpellPageItem.COLD_SNAP);
entries.add(SpellPageItem.ARCANE_LIFT);
entries.add(SpellPageItem.DISPEL_MAGIC);
Expand All @@ -105,21 +102,9 @@ public void onInitialize() {
.build();
Registry.register(Registries.ITEM_GROUP, "magisterium", group);

// TODO if spell data is server loaded, won't need these recipes anymore
// currently, they load parts of the spell data that the server needs to know
// and they have to match the client data...
Registry.register(Registries.RECIPE_TYPE, "magisterium:spell_book", SpellBookRecipe.TYPE);

Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:spell_crafting", SpellBookCraftingRecipe.Serializer.INSTANCE);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:awaken_the_flame", AwakenFlameRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:quench_the_flame", QuenchFlameRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:glyphic_ignition", GlyphicIgnitionRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:conflagrate", ConflagrateRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:illusory_wall", IllusoryWallRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:unstable_charge", UnstableChargeRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:cold_snap", ColdSnapRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:arcane_lift", ArcaneLiftRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:dispel_magic", DispelMagicRecipe.SERIALIZER);
Registry.register(Registries.RECIPE_TYPE, "magisterium:spell", SpellRecipe.TYPE);

Registry.register(Registries.RECIPE_SERIALIZER, "magisterium:spell", SpellRecipe.SERIALIZER);

Registry.register(Registries.SCREEN_HANDLER, "magisterium:spell_book", SpellBookScreenHandler.TYPE);
Registry.register(Registries.SCREEN_HANDLER, "magisterium:arcane_table", ArcaneTableScreenHandler.TYPE);
Expand All @@ -134,6 +119,24 @@ public void onInitialize() {
Registry.register(Registries.SOUND_EVENT, "magisterium:chant", MagisteriumSounds.CHANT);
Registry.register(Registries.SOUND_EVENT, "magisterium:arcane_lift_loop", MagisteriumSounds.ARCANE_LIFT_LOOP);

Registry.register(BookElement.REGISTRY, "magisterium:heading", Heading.CODEC);
Registry.register(BookElement.REGISTRY, "magisterium:paragraph", Paragraph.CODEC);
Registry.register(BookElement.REGISTRY, "magisterium:page_break", PageBreak.CODEC);
Registry.register(BookElement.REGISTRY, "magisterium:inventory", BookInventory.CODEC);
Registry.register(BookElement.REGISTRY, "magisterium:utterance", Utterance.CODEC);
Registry.register(BookElement.REGISTRY, "magisterium:fold", Fold.CODEC);
Registry.register(BookElement.REGISTRY, "magisterium:bookmark", BookmarkElement.CODEC);
Registry.register(BookElement.REGISTRY, "magisterium:vertically_centered", VerticallyCenteredElement.CODEC);

Registry.register(SpellEffect.REGISTRY, "magisterium:awaken_the_flame", AwakenFlameEffect.CODEC);
Registry.register(SpellEffect.REGISTRY, "magisterium:quench_the_flame", QuenchFlameEffect.CODEC);
Registry.register(SpellEffect.REGISTRY, "magisterium:glyphic_ignition", GlyphicIgnitionEffect.CODEC);
Registry.register(SpellEffect.REGISTRY, "magisterium:conflagrate", ConflagrateEffect.CODEC);
Registry.register(SpellEffect.REGISTRY, "magisterium:cold_snap", ColdSnapEffect.CODEC);
Registry.register(SpellEffect.REGISTRY, "magisterium:illusory_wall", IllusoryWallEffect.CODEC);
Registry.register(SpellEffect.REGISTRY, "magisterium:arcane_lift", ArcaneLiftEffect.CODEC);
Registry.register(SpellEffect.REGISTRY, "magisterium:dispel_magic", DispelMagicEffect.CODEC);

ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new ItemValuesLoader());

MagisteriumGameRules.initialize();
Expand Down Expand Up @@ -179,8 +182,7 @@ private static ActionResult interact(PlayerEntity player, World world, Hand hand
var state = world.getBlockState(pos);
var be = world.getBlockEntity(pos);

if (state.getBlock() instanceof LecternBlock
&& be instanceof LecternBlockEntity lectern) {
if (state.getBlock() instanceof LecternBlock && be instanceof LecternBlockEntity lectern) {
var book = lectern.getBook();
if (book.isEmpty() && stack.isOf(SpellBookItem.INSTANCE)) {
if (MagisteriumPlaygrounds.canModifyWorld(world, pos, player)) {
Expand Down Expand Up @@ -240,8 +242,7 @@ private static boolean tryPlaceGlyph(PlayerEntity player, World world, Hand hand
}
}
var sounds = placementState.getSoundGroup();
world.playSound(player, placementPos, sounds.getPlaceSound(), SoundCategory.BLOCKS, (sounds.getVolume() + 1.0F) / 2.0F,
sounds.getPitch());
world.playSound(player, placementPos, sounds.getPlaceSound(), SoundCategory.BLOCKS, (sounds.getVolume() + 1.0F) / 2.0F, sounds.getPitch());
world.emitGameEvent(player, GameEvent.BLOCK_PLACE, placementPos);

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,19 @@
import io.github.reoseah.magisterium.screen.ArcaneTableScreenHandler;
import io.github.reoseah.magisterium.screen.SpellBookScreen;
import io.github.reoseah.magisterium.screen.SpellBookScreenHandler;
import io.github.reoseah.magisterium.spellbook.SpellDataLoader;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.impl.resource.loader.ResourceManagerHelperImpl;
import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.client.item.ModelPredicateProviderRegistry;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactories;
import net.minecraft.resource.ResourceType;
import net.minecraft.util.Identifier;

public class MagisteriumClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
// perhaps it could be loaded on the server and sent to client,
// like the recipes do?
// this will help with making items for each spell
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SpellDataLoader());

BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ArcaneTableBlock.INSTANCE, GlyphBlock.INSTANCE);

ModelLoadingPlugin.register(ctx -> ctx.addModels(Identifier.of("magisterium", "item/spell_book_in_hand")));
Expand Down
89 changes: 89 additions & 0 deletions src/main/java/io/github/reoseah/magisterium/data/SpellRecipe.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package io.github.reoseah.magisterium.data;

import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.github.reoseah.magisterium.data.element.BookElement;
import io.github.reoseah.magisterium.recipe.SpellBookRecipeInput;
import net.minecraft.item.ItemStack;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.RecipeType;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.world.World;
import io.github.reoseah.magisterium.data.effect.SpellEffect;

import java.util.List;

public class SpellRecipe implements Recipe<SpellBookRecipeInput> {
public static final RecipeType<SpellRecipe> TYPE = new RecipeType<>() {
};

public static final MapCodec<SpellRecipe> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( //
BookElement.CODEC.listOf().fieldOf("elements").forGetter(SpellRecipe::getElements), //
SpellEffect.CODEC.listOf().fieldOf("effects").forGetter(SpellRecipe::getEffects) //
).apply(instance, SpellRecipe::new));

public static final PacketCodec<RegistryByteBuf, SpellRecipe> PACKET_CODEC = PacketCodecs.registryCodec(CODEC.codec());

public static final RecipeSerializer<SpellRecipe> SERIALIZER = new RecipeSerializer<>() {
@Override
public MapCodec<SpellRecipe> codec() {
return CODEC;
}

@Override
public PacketCodec<RegistryByteBuf, SpellRecipe> packetCodec() {
return PACKET_CODEC;
}
};

public final List<BookElement> elements;
public final List<SpellEffect> effects;

public SpellRecipe(List<BookElement> elements, List<SpellEffect> effects) {
this.elements = elements;
this.effects = effects;
}

public List<BookElement> getElements() {
return elements;
}

public List<SpellEffect> getEffects() {
return effects;
}

@Override
public boolean matches(SpellBookRecipeInput input, World world) {
// TODO implement
return true;
}

@Override
public ItemStack craft(SpellBookRecipeInput input, RegistryWrapper.WrapperLookup lookup) {
return ItemStack.EMPTY;
}

@Override
public boolean fits(int width, int height) {
return true;
}

@Override
public ItemStack getResult(RegistryWrapper.WrapperLookup registriesLookup) {
return ItemStack.EMPTY;
}

@Override
public RecipeSerializer<?> getSerializer() {
return SERIALIZER;
}

@Override
public RecipeType<?> getType() {
return TYPE;
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
package io.github.reoseah.magisterium.recipe;
package io.github.reoseah.magisterium.data.effect;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.github.reoseah.magisterium.block.ArcaneLiftBlock;
import io.github.reoseah.magisterium.block.GlyphBlock;
import io.github.reoseah.magisterium.recipe.SpellBookRecipeInput;
import io.github.reoseah.magisterium.world.MagisteriumPlaygrounds;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;

public class ArcaneLiftRecipe extends SpellBookRecipe {
public static final RecipeSerializer<ArcaneLiftRecipe> SERIALIZER = new SpellBookRecipe.SimpleSerializer<>(ArcaneLiftRecipe::new);
public class ArcaneLiftEffect extends SpellEffect {
public static final MapCodec<ArcaneLiftEffect> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( //
Identifier.CODEC.fieldOf("utterance").forGetter(effect -> effect.utterance), //
Codec.INT.fieldOf("duration").forGetter(effect -> effect.duration) //
).apply(instance, ArcaneLiftEffect::new));

protected ArcaneLiftRecipe(Identifier utterance, int duration) {
private static final int SEARCH_RADIUS = 8;

public ArcaneLiftEffect(Identifier utterance, int duration) {
super(utterance, duration);
}

@Override
public boolean matches(SpellBookRecipeInput input, World world) {
return true;
public MapCodec<? extends SpellEffect> getCodec() {
return CODEC;
}

@Override
public ItemStack craft(SpellBookRecipeInput input, RegistryWrapper.WrapperLookup lookup) {
public void finish(SpellBookRecipeInput input, RegistryWrapper.WrapperLookup lookup) {
var world = input.getPlayer().getWorld();
var pos = input.getPlayer().getBlockPos();

var circlePos = find3x3GlyphCircle(world, pos);
if (circlePos == null) {
return ItemStack.EMPTY;
return;
}

if (world.isAir(circlePos)) {
Expand All @@ -41,23 +45,21 @@ public ItemStack craft(SpellBookRecipeInput input, RegistryWrapper.WrapperLookup
MagisteriumPlaygrounds.trySetBlockState(world, circlePos, ArcaneLiftBlock.INSTANCE.getDefaultState(), input.getPlayer());
// TODO check result and send feedback
}

return ItemStack.EMPTY;
}

private static final int SEARCH_RADIUS = 8;

private static BlockPos find3x3GlyphCircle(WorldAccess world, BlockPos start) {
for (var pos : BlockPos.iterateOutwards(start, SEARCH_RADIUS, SEARCH_RADIUS, SEARCH_RADIUS)) {
boolean isCircle = true;
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (dx == 0 && dz == 0) {
if (!world.isAir(pos.add(dx, 0, dz))) {
isCircle = false;
}
continue;
}
if (!world.getBlockState(pos.add(dx, 0, dz)).isOf(GlyphBlock.INSTANCE)) {
isCircle = false;
continue;
}
}
}
Expand All @@ -68,14 +70,4 @@ private static BlockPos find3x3GlyphCircle(WorldAccess world, BlockPos start) {

return null;
}

@Override
public ItemStack getResult(RegistryWrapper.WrapperLookup registriesLookup) {
return ItemStack.EMPTY;
}

@Override
public RecipeSerializer<?> getSerializer() {
return SERIALIZER;
}
}
Loading

0 comments on commit 3c7ec41

Please sign in to comment.