TheBrokenRail
a3be3712d4
All checks were successful
SorceryCraft/pipeline/head This commit looks good
Update Mappings Add Config Screen Clarify Terms
195 lines
9.7 KiB
Java
195 lines
9.7 KiB
Java
package com.thebrokenrail.sorcerycraft;
|
|
|
|
import com.thebrokenrail.sorcerycraft.block.CastingTableBlock;
|
|
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
|
|
import com.thebrokenrail.sorcerycraft.client.gui.CastingTableScreen;
|
|
import com.thebrokenrail.sorcerycraft.client.entity.SpellEntityRenderer;
|
|
import com.thebrokenrail.sorcerycraft.command.SpellCommand;
|
|
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
|
import com.thebrokenrail.sorcerycraft.item.SpellItem;
|
|
import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket;
|
|
import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket;
|
|
import com.thebrokenrail.sorcerycraft.spell.util.RandomSpellLootTableFunction;
|
|
import com.thebrokenrail.sorcerycraft.spell.registry.Spells;
|
|
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
|
import me.sargunvohra.mcmods.autoconfig1u.gui.registry.GuiRegistry;
|
|
import me.sargunvohra.mcmods.autoconfig1u.serializer.GsonConfigSerializer;
|
|
import me.sargunvohra.mcmods.autoconfig1u.util.Utils;
|
|
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
|
|
import net.fabricmc.api.ClientModInitializer;
|
|
import net.fabricmc.api.ModInitializer;
|
|
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
|
|
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
|
|
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
|
|
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
|
|
import net.fabricmc.fabric.api.entity.FabricEntityTypeBuilder;
|
|
import net.fabricmc.fabric.api.loot.v1.FabricLootPoolBuilder;
|
|
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
|
|
import net.fabricmc.fabric.api.registry.CommandRegistry;
|
|
import net.fabricmc.fabric.impl.networking.ClientSidePacketRegistryImpl;
|
|
import net.fabricmc.fabric.impl.networking.ServerSidePacketRegistryImpl;
|
|
import net.minecraft.block.DispenserBlock;
|
|
import net.minecraft.block.dispenser.ProjectileDispenserBehavior;
|
|
import net.minecraft.client.MinecraftClient;
|
|
import net.minecraft.entity.EntityCategory;
|
|
import net.minecraft.entity.EntityDimensions;
|
|
import net.minecraft.entity.EntityType;
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.entity.projectile.Projectile;
|
|
import net.minecraft.item.BlockItem;
|
|
import net.minecraft.item.Item;
|
|
import net.minecraft.item.ItemGroup;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.loot.BinomialLootTableRange;
|
|
import net.minecraft.loot.LootTables;
|
|
import net.minecraft.loot.entry.ItemEntry;
|
|
import net.minecraft.sound.SoundCategory;
|
|
import net.minecraft.sound.SoundEvent;
|
|
import net.minecraft.sound.SoundEvents;
|
|
import net.minecraft.stat.StatFormatter;
|
|
import net.minecraft.stat.Stats;
|
|
import net.minecraft.text.TranslatableText;
|
|
import net.minecraft.util.Identifier;
|
|
import net.minecraft.util.math.BlockPointer;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.MathHelper;
|
|
import net.minecraft.util.math.Position;
|
|
import net.minecraft.util.registry.Registry;
|
|
import net.minecraft.world.World;
|
|
|
|
import java.util.Collections;
|
|
import java.util.Objects;
|
|
|
|
public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
|
public static final String NAMESPACE = "sorcerycraft";
|
|
public static SpellItem SPELL_ITEM;
|
|
public static CastingTableBlock CASTING_TABLE_BLOCK;
|
|
public static BlockItem CASTING_TABLE_BLOCK_ITEM;
|
|
public static ItemGroup ITEM_GROUP;
|
|
public static EntityType<SpellEntity> SPELL_ENTITY;
|
|
public static final Identifier[] LOOT_TABLES = new Identifier[]{
|
|
LootTables.SIMPLE_DUNGEON_CHEST,
|
|
LootTables.END_CITY_TREASURE_CHEST,
|
|
LootTables.NETHER_BRIDGE_CHEST,
|
|
LootTables.ABANDONED_MINESHAFT_CHEST,
|
|
LootTables.SHIPWRECK_TREASURE_CHEST,
|
|
LootTables.DESERT_PYRAMID_CHEST,
|
|
LootTables.JUNGLE_TEMPLE_CHEST,
|
|
LootTables.STRONGHOLD_LIBRARY_CHEST,
|
|
LootTables.PILLAGER_OUTPOST_CHEST,
|
|
LootTables.WOODLAND_MANSION_CHEST
|
|
};
|
|
public static Identifier STAT_INTERACT_WITH_CASTING_TABLE;
|
|
public static Identifier STAT_CAST_SPELL;
|
|
|
|
public static ModConfig getConfig() {
|
|
return AutoConfig.getConfigHolder(ModConfig.class).getConfig();
|
|
}
|
|
|
|
private boolean isSelectedLootTable(Identifier lootTable) {
|
|
for (Identifier id : LOOT_TABLES) {
|
|
if (id.equals(lootTable)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onInitialize() {
|
|
new Spells();
|
|
|
|
AutoConfig.register(ModConfig.class, GsonConfigSerializer::new);
|
|
GuiRegistry guiRegistry = AutoConfig.getGuiRegistry(ModConfig.class);
|
|
guiRegistry.registerAnnotationProvider((s, field, config, defaults, guiRegistryAccess) -> {
|
|
ModConfig.UsePercentage bounds = field.getAnnotation(ModConfig.UsePercentage.class);
|
|
return Collections.singletonList(ConfigEntryBuilder.create().startIntSlider(s, MathHelper.ceil(Utils.getUnsafely(field, config, 0.0) * 100), MathHelper.ceil(bounds.min() * 100), MathHelper.ceil(bounds.max() * 100)).setDefaultValue(() -> MathHelper.ceil((double) Utils.getUnsafely(field, defaults) * 100)).setSaveConsumer((newValue) -> Utils.setUnsafely(field, config, newValue / 100d)).setTextGetter(integer -> String.format("%d%%", integer)).build());
|
|
}, field -> field.getType() == Double.TYPE || field.getType() == Double.class, ModConfig.UsePercentage.class);
|
|
|
|
ITEM_GROUP = FabricItemGroupBuilder.create(
|
|
new Identifier(NAMESPACE, "spells"))
|
|
.icon(() -> new ItemStack(SPELL_ITEM))
|
|
.build();
|
|
|
|
CASTING_TABLE_BLOCK = new CastingTableBlock();
|
|
CASTING_TABLE_BLOCK_ITEM = new BlockItem(CASTING_TABLE_BLOCK, new Item.Settings().group(ITEM_GROUP));
|
|
SPELL_ITEM = new SpellItem();
|
|
|
|
SPELL_ENTITY = FabricEntityTypeBuilder.create(EntityCategory.MISC, (EntityType.EntityFactory<SpellEntity>) SpellEntity::new).size(EntityDimensions.fixed(0.25f, 0.25f)).build();
|
|
|
|
Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "spell"), SPELL_ITEM);
|
|
Registry.register(Registry.BLOCK, new Identifier(NAMESPACE, "casting_table"), CASTING_TABLE_BLOCK);
|
|
Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "casting_table"), CASTING_TABLE_BLOCK_ITEM);
|
|
Registry.register(Registry.ENTITY_TYPE, new Identifier(NAMESPACE, "spell"), SPELL_ENTITY);
|
|
|
|
ContainerProviderRegistry.INSTANCE.registerFactory(new Identifier(NAMESPACE, "casting_table"), (syncId, identifier, player, buf) -> {
|
|
final World world = player.world;
|
|
final BlockPos pos = buf.readBlockPos();
|
|
return Objects.requireNonNull(world.getBlockState(pos).createScreenHandlerFactory(player.world, pos)).createMenu(syncId, player.inventory, player);
|
|
});
|
|
|
|
CommandRegistry.INSTANCE.register(false, SpellCommand::register);
|
|
|
|
ServerSidePacketRegistryImpl.INSTANCE.register(new Identifier(NAMESPACE, "select_spell"), SelectSpellC2SPacket::handle);
|
|
ClientSidePacketRegistryImpl.INSTANCE.register(new Identifier(NAMESPACE, "update_known_spells"), UpdateKnownSpellsS2CPacket::handle);
|
|
|
|
LootTableLoadingCallback.EVENT.register((resourceManager, lootManager, id, supplier, setter) -> {
|
|
if (isSelectedLootTable(id)) {
|
|
FabricLootPoolBuilder poolBuilder = FabricLootPoolBuilder.builder()
|
|
.withRolls(new BinomialLootTableRange(2, 0.5f))
|
|
.withEntry(ItemEntry.builder(SPELL_ITEM))
|
|
.withFunction(new RandomSpellLootTableFunction.Builder());
|
|
|
|
supplier.withPool(poolBuilder);
|
|
}
|
|
});
|
|
|
|
DispenserBlock.registerBehavior(SorceryCraft.SPELL_ITEM, new ProjectileDispenserBehavior() {
|
|
@Override
|
|
protected Projectile createProjectile(World position, Position stack, ItemStack itemStack) {
|
|
SpellEntity entity = new SpellEntity(position, stack.getX(), stack.getY(), stack.getZ());
|
|
entity.setItem(itemStack);
|
|
return entity;
|
|
}
|
|
|
|
@Override
|
|
protected void playSound(BlockPointer pointer) {
|
|
playSpellSound(pointer);
|
|
}
|
|
});
|
|
|
|
STAT_INTERACT_WITH_CASTING_TABLE = registerStat("interact_with_casting_table");
|
|
STAT_CAST_SPELL = registerStat("cast_spell");
|
|
}
|
|
|
|
private Identifier registerStat(String name) {
|
|
Identifier statID = new Identifier(NAMESPACE, name);
|
|
Registry.register(Registry.CUSTOM_STAT, name, statID);
|
|
Stats.CUSTOM.getOrCreateStat(statID, StatFormatter.DEFAULT);
|
|
return statID;
|
|
}
|
|
|
|
private static final SoundEvent SPELL_SOUND_EFFECT = SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE;
|
|
|
|
public static void playSpellSound(World world, BlockPos pos) {
|
|
world.playSound(null, pos, SPELL_SOUND_EFFECT, SoundCategory.BLOCKS, 1.0f, 1.0f);
|
|
}
|
|
|
|
public static void playSpellSound(BlockPointer block) {
|
|
playSpellSound(block.getWorld(), block.getBlockPos());
|
|
}
|
|
|
|
public static void playSpellSound(PlayerEntity player) {
|
|
player.playSound(SPELL_SOUND_EFFECT, SoundCategory.PLAYERS, 1.0f, 1.0f);
|
|
}
|
|
|
|
@Override
|
|
public void onInitializeClient() {
|
|
EntityRendererRegistry.INSTANCE.register(SPELL_ENTITY, (entityRenderDispatcher, context) -> new SpellEntityRenderer(entityRenderDispatcher));
|
|
ScreenProviderRegistry.INSTANCE.<CastingTableScreenHandler>registerFactory(new Identifier(NAMESPACE, "casting_table"), (container) -> {
|
|
assert MinecraftClient.getInstance().player != null;
|
|
return new CastingTableScreen(container, MinecraftClient.getInstance().player.inventory, new TranslatableText("block." + SorceryCraft.NAMESPACE + ".casting_table"));
|
|
});
|
|
}
|
|
}
|