Initial commit for 3.0
The altar mostly works. Sigils exist. Orbs exist. Living Armor framework exists. Probably some other things.
This commit is contained in:
parent
ecebe75f33
commit
26af9d5c6d
1764 changed files with 7049 additions and 90817 deletions
61
src/main/java/com/wayoftime/bloodmagic/BloodMagic.java
Normal file
61
src/main/java/com/wayoftime/bloodmagic/BloodMagic.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
package com.wayoftime.bloodmagic;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.api.BloodMagicPlugin;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicPlugin;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicBlocks;
|
||||
import com.wayoftime.bloodmagic.core.util.PluginUtil;
|
||||
import com.wayoftime.bloodmagic.proxy.IProxy;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidRegistry;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.SidedProxy;
|
||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
@Mod(modid = BloodMagic.MODID, name = BloodMagic.NAME, version = BloodMagic.VERSION)
|
||||
public class BloodMagic {
|
||||
|
||||
public static final String MODID = "bloodmagic";
|
||||
public static final String NAME = "Blood Magic: Alchemical Wizardry";
|
||||
public static final String VERSION = "${VERSION}";
|
||||
public static final List<Pair<IBloodMagicPlugin, BloodMagicPlugin>> PLUGINS = Lists.newArrayList();
|
||||
public static final CreativeTabs TAB_BM = new CreativeTabs(MODID) {
|
||||
@Override
|
||||
public ItemStack createIcon() {
|
||||
return new ItemStack(RegistrarBloodMagicBlocks.BLOOD_ALTAR);
|
||||
}
|
||||
};
|
||||
|
||||
@SidedProxy(clientSide = "com.wayoftime.bloodmagic.proxy.ClientProxy", serverSide = "com.wayoftime.bloodmagic.proxy.ServerProxy")
|
||||
public static IProxy PROXY;
|
||||
@Mod.Instance(value = MODID)
|
||||
public static BloodMagic INSTANCE;
|
||||
public static File configDir;
|
||||
|
||||
static {
|
||||
FluidRegistry.enableUniversalBucket();
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
configDir = new File(event.getModConfigurationDirectory(), BloodMagic.MODID);
|
||||
if (!configDir.exists())
|
||||
configDir.mkdirs();
|
||||
|
||||
PLUGINS.addAll(PluginUtil.gatherPlugins(event.getAsmData()));
|
||||
PluginUtil.injectAPIInstances(PluginUtil.gatherInjections(event.getAsmData()));
|
||||
|
||||
PROXY.preInit(); // TODO - Remove proxy. Switch altar model to json
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void init(FMLInitializationEvent event) {
|
||||
PluginUtil.handlePluginStep(PluginUtil.RegistrationStep.PLUGIN_REGISTER);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.wayoftime.bloodmagic.api.impl;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicAPI;
|
||||
import com.wayoftime.bloodmagic.core.type.ComponentType;
|
||||
import com.wayoftime.bloodmagic.core.util.BMLog;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class BloodMagicAPI implements IBloodMagicAPI {
|
||||
|
||||
public static final BloodMagicAPI INSTANCE = new BloodMagicAPI();
|
||||
|
||||
private final BloodMagicBlacklist blacklist;
|
||||
private final BloodMagicRecipeRegistrar recipeRegistrar;
|
||||
private final BloodMagicValueManager valueManager;
|
||||
private final Multimap<ComponentType, IBlockState> altarComponents;
|
||||
|
||||
public BloodMagicAPI() {
|
||||
this.blacklist = new BloodMagicBlacklist();
|
||||
this.recipeRegistrar = new BloodMagicRecipeRegistrar();
|
||||
this.valueManager = new BloodMagicValueManager();
|
||||
this.altarComponents = ArrayListMultimap.create();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public BloodMagicBlacklist getBlacklist() {
|
||||
return blacklist;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public BloodMagicRecipeRegistrar getRecipeRegistrar() {
|
||||
return recipeRegistrar;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public BloodMagicValueManager getValueManager() {
|
||||
return valueManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAltarComponent(@Nonnull IBlockState state, @Nonnull String componentType) {
|
||||
ComponentType component = null;
|
||||
for (ComponentType type : ComponentType.VALUES) {
|
||||
if (type.name().equalsIgnoreCase(componentType)) {
|
||||
component = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (component != null) {
|
||||
BMLog.API_VERBOSE.info("Registered {} as a {} altar component.", state, componentType);
|
||||
altarComponents.put(component, state);
|
||||
} else BMLog.API.warn("Invalid Altar component type: {}.", componentType);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<IBlockState> getComponentStates(ComponentType component) {
|
||||
return (List<IBlockState>) altarComponents.get(component);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package com.wayoftime.bloodmagic.api.impl;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicBlacklist;
|
||||
import com.wayoftime.bloodmagic.core.util.BMLog;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
|
||||
public class BloodMagicBlacklist implements IBloodMagicBlacklist {
|
||||
|
||||
private final Set<IBlockState> teleposer;
|
||||
private final Set<ResourceLocation> teleposerEntities;
|
||||
private final Set<IBlockState> transposition;
|
||||
private final Set<IBlockState> greenGrove;
|
||||
private final Set<ResourceLocation> sacrifice;
|
||||
|
||||
public BloodMagicBlacklist() {
|
||||
this.teleposer = Sets.newHashSet();
|
||||
this.teleposerEntities = Sets.newHashSet();
|
||||
this.transposition = Sets.newHashSet();
|
||||
this.greenGrove = Sets.newHashSet();
|
||||
this.sacrifice = Sets.newHashSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTeleposer(@Nonnull IBlockState state) {
|
||||
if (!teleposer.contains(state)) {
|
||||
BMLog.API_VERBOSE.info("Blacklist: Added {} to the Teleposer blacklist.", state);
|
||||
teleposer.add(state);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTeleposer(@Nonnull Block block) {
|
||||
for (IBlockState state : block.getBlockState().getValidStates())
|
||||
addTeleposer(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTeleposer(@Nonnull ResourceLocation entityId) {
|
||||
if (!teleposerEntities.contains(entityId)) {
|
||||
BMLog.API_VERBOSE.info("Blacklist: Added {} to the Teleposer blacklist.", entityId);
|
||||
teleposerEntities.add(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransposition(@Nonnull IBlockState state) {
|
||||
if (!transposition.contains(state)) {
|
||||
BMLog.API_VERBOSE.info("Blacklist: Added {} to the Transposition blacklist.", state);
|
||||
transposition.add(state);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTransposition(@Nonnull Block block) {
|
||||
for (IBlockState state : block.getBlockState().getValidStates())
|
||||
addTransposition(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGreenGrove(@Nonnull IBlockState state) {
|
||||
if (!greenGrove.contains(state)) {
|
||||
BMLog.API_VERBOSE.info("Blacklist: Added {} to the Green Grove blacklist.", state);
|
||||
greenGrove.add(state);
|
||||
}
|
||||
}
|
||||
|
||||
public void addGreenGrove(@Nonnull Block block) {
|
||||
for (IBlockState state : block.getBlockState().getValidStates())
|
||||
addGreenGrove(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWellOfSuffering(@Nonnull ResourceLocation entityId) {
|
||||
if (!sacrifice.contains(entityId)) {
|
||||
BMLog.API_VERBOSE.info("Blacklist: Added {} to the Well of Suffering blacklist.", entityId);
|
||||
sacrifice.add(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
// Internal use getters
|
||||
|
||||
public Set<IBlockState> getTeleposer() {
|
||||
return ImmutableSet.copyOf(teleposer);
|
||||
}
|
||||
|
||||
public Set<ResourceLocation> getTeleposerEntities() {
|
||||
return ImmutableSet.copyOf(teleposerEntities);
|
||||
}
|
||||
|
||||
public Set<IBlockState> getTransposition() {
|
||||
return ImmutableSet.copyOf(transposition);
|
||||
}
|
||||
|
||||
public Set<IBlockState> getGreenGrove() {
|
||||
return ImmutableSet.copyOf(greenGrove);
|
||||
}
|
||||
|
||||
public Set<ResourceLocation> getSacrifice() {
|
||||
return ImmutableSet.copyOf(sacrifice);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package com.wayoftime.bloodmagic.api.impl;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.api.BloodMagicPlugin;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicAPI;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicPlugin;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicRecipeRegistrar;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicBlocks;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicRecipes;
|
||||
import com.wayoftime.bloodmagic.core.type.ComponentType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.registry.ForgeRegistries;
|
||||
|
||||
@BloodMagicPlugin
|
||||
public class BloodMagicCorePlugin implements IBloodMagicPlugin {
|
||||
|
||||
@Override
|
||||
public void register(IBloodMagicAPI apiInterface) {
|
||||
BloodMagicAPI api = (BloodMagicAPI) apiInterface;
|
||||
// Add forced blacklistings
|
||||
// api.getBlacklist().addTeleposer(RegistrarBloodMagicBlocks.INPUT_ROUTING_NODE);
|
||||
// api.getBlacklist().addTransposition(RegistrarBloodMagicBlocks.INPUT_ROUTING_NODE);
|
||||
// api.getBlacklist().addTeleposer(RegistrarBloodMagicBlocks.OUTPUT_ROUTING_NODE);
|
||||
// api.getBlacklist().addTransposition(RegistrarBloodMagicBlocks.OUTPUT_ROUTING_NODE);
|
||||
// api.getBlacklist().addTeleposer(RegistrarBloodMagicBlocks.ITEM_ROUTING_NODE);
|
||||
// api.getBlacklist().addTransposition(RegistrarBloodMagicBlocks.ITEM_ROUTING_NODE);
|
||||
// api.getBlacklist().addTeleposer(RegistrarBloodMagicBlocks.MASTER_ROUTING_NODE);
|
||||
// api.getBlacklist().addTransposition(RegistrarBloodMagicBlocks.MASTER_ROUTING_NODE);
|
||||
// api.getBlacklist().addTeleposer(RegistrarBloodMagicBlocks.DEMON_CRYSTAL);
|
||||
// api.getBlacklist().addTransposition(RegistrarBloodMagicBlocks.DEMON_CRYSTAL);
|
||||
// api.getBlacklist().addTeleposer(RegistrarBloodMagicBlocks.INVERSION_PILLAR);
|
||||
// api.getBlacklist().addTransposition(RegistrarBloodMagicBlocks.INVERSION_PILLAR);
|
||||
api.getBlacklist().addWellOfSuffering(new ResourceLocation("armor_stand"));
|
||||
api.getBlacklist().addWellOfSuffering(new ResourceLocation(BloodMagic.MODID, "sentient_specter"));
|
||||
|
||||
api.getValueManager().setSacrificialValue(new ResourceLocation("armor_stand"), 0);
|
||||
api.getValueManager().setSacrificialValue(new ResourceLocation(BloodMagic.MODID, "sentient_specter"), 0);
|
||||
|
||||
// api.getValueManager().setTranquility(Blocks.LAVA, new TranquilityStack(EnumTranquilityType.LAVA, 1.2D));
|
||||
// api.getValueManager().setTranquility(Blocks.FLOWING_LAVA, new TranquilityStack(EnumTranquilityType.LAVA, 1.2D));
|
||||
// api.getValueManager().setTranquility(Blocks.WATER, new TranquilityStack(EnumTranquilityType.WATER, 1.0D));
|
||||
// api.getValueManager().setTranquility(Blocks.FLOWING_WATER, new TranquilityStack(EnumTranquilityType.WATER, 1.0D));
|
||||
// api.getValueManager().setTranquility(RegistrarBloodMagicBlocks.LIFE_ESSENCE, new TranquilityStack(EnumTranquilityType.WATER, 1.5D));
|
||||
// api.getValueManager().setTranquility(Blocks.NETHERRACK, new TranquilityStack(EnumTranquilityType.FIRE, 0.5D));
|
||||
// api.getValueManager().setTranquility(Blocks.DIRT, new TranquilityStack(EnumTranquilityType.EARTHEN, 0.25D));
|
||||
// api.getValueManager().setTranquility(Blocks.FARMLAND, new TranquilityStack(EnumTranquilityType.EARTHEN, 1.0D));
|
||||
// api.getValueManager().setTranquility(Blocks.POTATOES, new TranquilityStack(EnumTranquilityType.CROP, 1.0D));
|
||||
// api.getValueManager().setTranquility(Blocks.CARROTS, new TranquilityStack(EnumTranquilityType.CROP, 1.0D));
|
||||
// api.getValueManager().setTranquility(Blocks.WHEAT, new TranquilityStack(EnumTranquilityType.CROP, 1.0D));
|
||||
// api.getValueManager().setTranquility(Blocks.NETHER_WART, new TranquilityStack(EnumTranquilityType.CROP, 1.0D));
|
||||
// api.getValueManager().setTranquility(Blocks.BEETROOTS, new TranquilityStack(EnumTranquilityType.CROP, 1.0D));
|
||||
|
||||
handleConfigValues(api);
|
||||
|
||||
// Add standard blocks for altar components
|
||||
api.registerAltarComponent(Blocks.GLOWSTONE.getDefaultState(), ComponentType.GLOWSTONE.name());
|
||||
api.registerAltarComponent(Blocks.SEA_LANTERN.getDefaultState(), ComponentType.GLOWSTONE.name());
|
||||
api.registerAltarComponent(Blocks.BEACON.getDefaultState(), ComponentType.BEACON.name());
|
||||
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOODSTONE_BRICK.getDefaultState(), ComponentType.BLOODSTONE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOODSTONE_TILE.getDefaultState(), ComponentType.BLOODSTONE.name());
|
||||
// api.registerAltarComponent(decorative.getDefaultState().withProperty(decorative.getProperty(), EnumDecorative.CRYSTAL_BRICK), ComponentType.CRYSTAL.name());
|
||||
// api.registerAltarComponent(decorative.getDefaultState().withProperty(decorative.getProperty(), EnumDecorative.CRYSTAL_TILE), ComponentType.CRYSTAL.name());
|
||||
|
||||
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_BLANK.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_ACCELERATION.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_CAPACITY.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_AUGMENTED_CAPACITY.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_CHARGING.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_DISPLACEMENT.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_EFFICIENCY.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_ORB.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_SACRIFICE.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_SELF_SACRIFICE.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
api.registerAltarComponent(RegistrarBloodMagicBlocks.BLOOD_RUNE_SPEED.getDefaultState(), ComponentType.BLOOD_RUNE.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRecipes(IBloodMagicRecipeRegistrar recipeRegistrar) {
|
||||
RegistrarBloodMagicRecipes.registerAltarRecipes((BloodMagicRecipeRegistrar) recipeRegistrar);
|
||||
// RegistrarBloodMagicRecipes.registerAlchemyTableRecipes((BloodMagicRecipeRegistrar) recipeRegistrar);
|
||||
// RegistrarBloodMagicRecipes.registerTartaricForgeRecipes((BloodMagicRecipeRegistrar) recipeRegistrar);
|
||||
// RegistrarBloodMagicRecipes.registerAlchemyArrayRecipes((BloodMagicRecipeRegistrar) recipeRegistrar);
|
||||
// RegistrarBloodMagicRecipes.registerSacrificeCraftRecipes((BloodMagicRecipeRegistrar) recipeRegistrar);
|
||||
}
|
||||
|
||||
private static void handleConfigValues(BloodMagicAPI api) {
|
||||
// for (String value : ConfigHandler.values.sacrificialValues)
|
||||
// {
|
||||
// String[] split = value.split(";");
|
||||
// if (split.length != 2) // Not valid format
|
||||
// continue;
|
||||
//
|
||||
// api.getValueManager().setSacrificialValue(new ResourceLocation(split[0]), Integer.parseInt(split[1]));
|
||||
// }
|
||||
//
|
||||
// for (String value : ConfigHandler.blacklist.teleposer)
|
||||
// {
|
||||
// EntityEntry entityEntry = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(value));
|
||||
// if (entityEntry == null)
|
||||
// { // It's not an entity (or at least not a valid one), so let's try a block.
|
||||
// String[] blockData = value.split("\\[");
|
||||
// Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(blockData[0]));
|
||||
// if (block == Blocks.AIR || block == null) // Not a valid block either
|
||||
// continue;
|
||||
//
|
||||
// if (blockData.length > 1)
|
||||
// { // We have properties listed, so let's build a state.
|
||||
// api.getBlacklist().addTeleposer(parseState(value));
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// api.getBlacklist().addTeleposer(block);
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// api.getBlacklist().addTeleposer(entityEntry.getRegistryName());
|
||||
// }
|
||||
//
|
||||
// for (String value : ConfigHandler.blacklist.transposer)
|
||||
// {
|
||||
// String[] blockData = value.split("\\[");
|
||||
// Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(blockData[0]));
|
||||
// if (block == Blocks.AIR || block == null) // Not a valid block
|
||||
// continue;
|
||||
//
|
||||
// if (blockData.length > 1)
|
||||
// { // We have properties listed, so let's build a state.
|
||||
// api.getBlacklist().addTeleposer(parseState(value));
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// api.getBlacklist().addTeleposer(block);
|
||||
// }
|
||||
//
|
||||
// for (String value : ConfigHandler.blacklist.wellOfSuffering)
|
||||
// {
|
||||
// EntityEntry entityEntry = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(value));
|
||||
// if (entityEntry == null) // Not a valid entity
|
||||
// continue;
|
||||
//
|
||||
// api.getBlacklist().addWellOfSuffering(entityEntry.getRegistryName());
|
||||
// }
|
||||
}
|
||||
|
||||
private static IBlockState parseState(String blockInfo) {
|
||||
String[] split = blockInfo.split("\\[");
|
||||
split[1] = split[1].substring(0, split[1].lastIndexOf("]")); // Make sure brackets are removed from state
|
||||
|
||||
Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(split[0])); // Find the block
|
||||
if (block == Blocks.AIR)
|
||||
return Blocks.AIR.getDefaultState(); // The block is air, so we're looking at invalid data
|
||||
|
||||
BlockStateContainer blockState = block.getBlockState();
|
||||
IBlockState returnState = blockState.getBaseState();
|
||||
|
||||
// Force our values into the state
|
||||
String[] stateValues = split[1].split(","); // Splits up each value
|
||||
for (String value : stateValues) {
|
||||
String[] valueSplit = value.split("="); // Separates property and value
|
||||
IProperty property = blockState.getProperty(valueSplit[0]);
|
||||
if (property != null)
|
||||
returnState = returnState.withProperty(property, (Comparable) property.parseValue(valueSplit[1]).get()); // Force the property into the state
|
||||
}
|
||||
|
||||
return returnState;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,357 @@
|
|||
package com.wayoftime.bloodmagic.api.impl;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicRecipeRegistrar;
|
||||
import com.wayoftime.bloodmagic.api.impl.recipe.*;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarTier;
|
||||
import com.wayoftime.bloodmagic.core.network.IBloodOrb;
|
||||
import com.wayoftime.bloodmagic.core.recipe.IngredientBloodOrb;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.crafting.CraftingHelper;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class BloodMagicRecipeRegistrar implements IBloodMagicRecipeRegistrar {
|
||||
|
||||
private final Set<RecipeBloodAltar> altarRecipes;
|
||||
private final Set<RecipeAlchemyTable> alchemyRecipes;
|
||||
private final Set<RecipeTartaricForge> tartaricForgeRecipes;
|
||||
private final Set<RecipeAlchemyArray> alchemyArrayRecipes;
|
||||
private final Set<RecipeSacrificeCraft> sacrificeCraftRecipes;
|
||||
|
||||
public BloodMagicRecipeRegistrar() {
|
||||
this.altarRecipes = Sets.newHashSet();
|
||||
this.alchemyRecipes = Sets.newHashSet();
|
||||
this.tartaricForgeRecipes = Sets.newHashSet();
|
||||
this.alchemyArrayRecipes = Sets.newHashSet();
|
||||
this.sacrificeCraftRecipes = Sets.newHashSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBloodAltar(@Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnegative int minimumTier, @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative.");
|
||||
Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative.");
|
||||
Preconditions.checkArgument(consumeRate >= 0, "consumeRate cannot be negative.");
|
||||
Preconditions.checkArgument(drainRate >= 0, "drainRate cannot be negative.");
|
||||
|
||||
altarRecipes.add(new RecipeBloodAltar(input, output, minimumTier, syphon, consumeRate, drainRate));
|
||||
}
|
||||
|
||||
public void addBloodAltar(@Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnull AltarTier tier, @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate) {
|
||||
addBloodAltar(input, output, tier.ordinal(), syphon, consumeRate, drainRate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean removeBloodAltar(@Nonnull ItemStack input) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
|
||||
return altarRecipes.remove(getBloodAltar(input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAlchemyTable(@Nonnull ItemStack output, @Nonnegative int syphon, @Nonnegative int ticks, @Nonnegative int minimumTier, @Nonnull Ingredient... input) {
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative.");
|
||||
Preconditions.checkArgument(ticks >= 0, "ticks cannot be negative.");
|
||||
Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative.");
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
|
||||
NonNullList<Ingredient> inputs = NonNullList.from(Ingredient.EMPTY, input);
|
||||
alchemyRecipes.add(new RecipeAlchemyTable(inputs, output, syphon, ticks, minimumTier));
|
||||
}
|
||||
|
||||
public void addAlchemyTable(@Nonnull ItemStack output, @Nonnegative int syphon, @Nonnegative int ticks, @Nonnegative int minimumTier, @Nonnull Object... input) {
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative.");
|
||||
Preconditions.checkArgument(ticks >= 0, "ticks cannot be negative.");
|
||||
Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative.");
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
|
||||
List<Ingredient> ingredients = Lists.newArrayList();
|
||||
for (Object object : input) {
|
||||
if (object instanceof ItemStack && ((ItemStack) object).getItem() instanceof IBloodOrb) {
|
||||
ingredients.add(new IngredientBloodOrb(((IBloodOrb) ((ItemStack) object).getItem()).getOrb((ItemStack) object)));
|
||||
continue;
|
||||
}
|
||||
|
||||
ingredients.add(CraftingHelper.getIngredient(object));
|
||||
}
|
||||
|
||||
addAlchemyTable(output, syphon, ticks, minimumTier, ingredients.toArray(new Ingredient[0]));
|
||||
}
|
||||
|
||||
public void addAlchemyTable(RecipeAlchemyTable recipe) {
|
||||
alchemyRecipes.add(recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAlchemyTable(@Nonnull ItemStack... input) {
|
||||
Preconditions.checkNotNull(input, "inputs cannot be null.");
|
||||
|
||||
for (ItemStack stack : input)
|
||||
Preconditions.checkNotNull(stack, "input cannot be null.");
|
||||
|
||||
return alchemyRecipes.remove(getAlchemyTable(Lists.newArrayList(input)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTartaricForge(@Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain, @Nonnull Ingredient... input) {
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(minimumSouls >= 0, "minimumSouls cannot be negative.");
|
||||
Preconditions.checkArgument(soulDrain >= 0, "soulDrain cannot be negative.");
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
|
||||
NonNullList<Ingredient> inputs = NonNullList.from(Ingredient.EMPTY, input);
|
||||
tartaricForgeRecipes.add(new RecipeTartaricForge(inputs, output, minimumSouls, soulDrain));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeTartaricForge(@Nonnull ItemStack... input) {
|
||||
Preconditions.checkNotNull(input, "inputs cannot be null.");
|
||||
|
||||
for (ItemStack stack : input)
|
||||
Preconditions.checkNotNull(stack, "input cannot be null.");
|
||||
|
||||
return tartaricForgeRecipes.remove(getTartaricForge(Lists.newArrayList(input)));
|
||||
}
|
||||
|
||||
public void addTartaricForge(@Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain, @Nonnull Object... input) {
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(minimumSouls >= 0, "minimumSouls cannot be negative.");
|
||||
Preconditions.checkArgument(soulDrain >= 0, "soulDrain cannot be negative.");
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
|
||||
List<Ingredient> ingredients = Lists.newArrayList();
|
||||
for (Object object : input) {
|
||||
if (object instanceof ItemStack && ((ItemStack) object).getItem() instanceof IBloodOrb) {
|
||||
ingredients.add(new IngredientBloodOrb(((IBloodOrb) ((ItemStack) object).getItem()).getOrb((ItemStack) object)));
|
||||
continue;
|
||||
}
|
||||
|
||||
ingredients.add(CraftingHelper.getIngredient(object));
|
||||
}
|
||||
|
||||
addTartaricForge(output, minimumSouls, soulDrain, ingredients.toArray(new Ingredient[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAlchemyArray(@Nonnull Ingredient input, @Nonnull Ingredient catalyst, @Nonnull ItemStack output, @Nullable ResourceLocation circleTexture) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(catalyst, "catalyst cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
|
||||
alchemyArrayRecipes.add(new RecipeAlchemyArray(input, catalyst, output, circleTexture));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAlchemyArray(@Nonnull ItemStack input, @Nonnull ItemStack catalyst) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(catalyst, "catalyst cannot be null.");
|
||||
|
||||
return alchemyArrayRecipes.remove(getAlchemyArray(input, catalyst));
|
||||
}
|
||||
|
||||
public void addAlchemyArray(@Nonnull ItemStack input, @Nonnull ItemStack catalyst, @Nonnull ItemStack output, @Nullable ResourceLocation circleTexture) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(catalyst, "catalyst cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
|
||||
addAlchemyArray(Ingredient.fromStacks(input), Ingredient.fromStacks(catalyst), output, circleTexture);
|
||||
}
|
||||
|
||||
public void addSacrificeCraft(@Nonnull ItemStack output, @Nonnegative double healthRequired, @Nonnull Object... input) {
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(healthRequired >= 0, "healthRequired cannot be negative.");
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
|
||||
List<Ingredient> ingredients = Lists.newArrayList();
|
||||
for (Object object : input) {
|
||||
if (object instanceof ItemStack && ((ItemStack) object).getItem() instanceof IBloodOrb) {
|
||||
ingredients.add(new IngredientBloodOrb(((IBloodOrb) ((ItemStack) object).getItem()).getOrb((ItemStack) object)));
|
||||
continue;
|
||||
}
|
||||
|
||||
ingredients.add(CraftingHelper.getIngredient(object));
|
||||
}
|
||||
|
||||
addSacrificeCraft(output, healthRequired, ingredients.toArray(new Ingredient[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSacrificeCraft(@Nonnull ItemStack... input) {
|
||||
Preconditions.checkNotNull(input, "inputs cannot be null.");
|
||||
|
||||
for (ItemStack stack : input)
|
||||
Preconditions.checkNotNull(stack, "input cannot be null.");
|
||||
|
||||
return sacrificeCraftRecipes.remove(getSacrificeCraft(Lists.newArrayList(input)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSacrificeCraft(@Nonnull ItemStack output, @Nonnegative double healthRequired, @Nonnull Ingredient... input) {
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(healthRequired >= 0, "healthRequired cannot be negative.");
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
|
||||
NonNullList<Ingredient> inputs = NonNullList.from(Ingredient.EMPTY, input);
|
||||
sacrificeCraftRecipes.add(new RecipeSacrificeCraft(inputs, output, healthRequired));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RecipeBloodAltar getBloodAltar(@Nonnull ItemStack input) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
if (input.isEmpty())
|
||||
return null;
|
||||
|
||||
for (RecipeBloodAltar recipe : altarRecipes)
|
||||
if (recipe.getInput().test(input))
|
||||
return recipe;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RecipeAlchemyTable getAlchemyTable(@Nonnull List<ItemStack> input) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
if (input.isEmpty())
|
||||
return null;
|
||||
|
||||
mainLoop:
|
||||
for (RecipeAlchemyTable recipe : alchemyRecipes) {
|
||||
if (recipe.getInput().size() != input.size())
|
||||
continue;
|
||||
|
||||
List<Ingredient> recipeInput = new ArrayList<>(recipe.getInput());
|
||||
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
boolean matched = false;
|
||||
for (int j = 0; j < recipeInput.size(); j++) {
|
||||
Ingredient ingredient = recipeInput.get(j);
|
||||
if (ingredient.apply(input.get(i))) {
|
||||
matched = true;
|
||||
recipeInput.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched)
|
||||
continue mainLoop;
|
||||
}
|
||||
|
||||
return recipe;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RecipeTartaricForge getTartaricForge(@Nonnull List<ItemStack> input) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
if (input.isEmpty())
|
||||
return null;
|
||||
|
||||
mainLoop:
|
||||
for (RecipeTartaricForge recipe : tartaricForgeRecipes) {
|
||||
if (recipe.getInput().size() != input.size())
|
||||
continue;
|
||||
|
||||
List<Ingredient> recipeInput = new ArrayList<>(recipe.getInput());
|
||||
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
boolean matched = false;
|
||||
for (int j = 0; j < recipeInput.size(); j++) {
|
||||
Ingredient ingredient = recipeInput.get(j);
|
||||
if (ingredient.apply(input.get(i))) {
|
||||
matched = true;
|
||||
recipeInput.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched)
|
||||
continue mainLoop;
|
||||
}
|
||||
|
||||
return recipe;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RecipeSacrificeCraft getSacrificeCraft(@Nonnull List<ItemStack> input) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
if (input.isEmpty())
|
||||
return null;
|
||||
|
||||
mainLoop:
|
||||
for (RecipeSacrificeCraft recipe : sacrificeCraftRecipes) {
|
||||
if (recipe.getInput().size() != input.size())
|
||||
continue;
|
||||
|
||||
List<Ingredient> recipeInput = new ArrayList<>(recipe.getInput());
|
||||
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
boolean matched = false;
|
||||
for (int j = 0; j < recipeInput.size(); j++) {
|
||||
Ingredient ingredient = recipeInput.get(j);
|
||||
if (ingredient.apply(input.get(i))) {
|
||||
matched = true;
|
||||
recipeInput.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched)
|
||||
continue mainLoop;
|
||||
}
|
||||
|
||||
return recipe;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RecipeAlchemyArray getAlchemyArray(@Nonnull ItemStack input, @Nonnull ItemStack catalyst) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
if (input.isEmpty())
|
||||
return null;
|
||||
|
||||
for (RecipeAlchemyArray recipe : alchemyArrayRecipes)
|
||||
if (recipe.getInput().test(input) && recipe.getCatalyst().test(catalyst))
|
||||
return recipe;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<RecipeBloodAltar> getAltarRecipes() {
|
||||
return ImmutableSet.copyOf(altarRecipes);
|
||||
}
|
||||
|
||||
public Set<RecipeAlchemyTable> getAlchemyRecipes() {
|
||||
return ImmutableSet.copyOf(alchemyRecipes);
|
||||
}
|
||||
|
||||
public Set<RecipeTartaricForge> getTartaricForgeRecipes() {
|
||||
return ImmutableSet.copyOf(tartaricForgeRecipes);
|
||||
}
|
||||
|
||||
public Set<RecipeAlchemyArray> getAlchemyArrayRecipes() {
|
||||
return ImmutableSet.copyOf(alchemyArrayRecipes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.wayoftime.bloodmagic.api.impl;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicValueManager;
|
||||
import com.wayoftime.bloodmagic.core.util.BMLog;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
|
||||
public class BloodMagicValueManager implements IBloodMagicValueManager {
|
||||
|
||||
private final Map<ResourceLocation, Integer> sacrificial;
|
||||
// private final Map<IBlockState, TranquilityStack> tranquility; // TODO - Tranquility
|
||||
|
||||
public BloodMagicValueManager() {
|
||||
this.sacrificial = Maps.newHashMap();
|
||||
// this.tranquility = Maps.newHashMap(); // TODO - Tranquility
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSacrificialValue(@Nonnull ResourceLocation entityId, int value) {
|
||||
BMLog.API_VERBOSE.info("Value Manager: Set sacrificial value of {} to {}.", entityId, value);
|
||||
sacrificial.put(entityId, value);
|
||||
}
|
||||
|
||||
// TODO - Tranquility
|
||||
@Override
|
||||
public void setTranquility(@Nonnull IBlockState state, @Nonnull String tranquilityType, double value) {
|
||||
// EnumTranquilityType tranquility = null;
|
||||
// for (EnumTranquilityType type : EnumTranquilityType.values()) {
|
||||
// if (type.name().equalsIgnoreCase(tranquilityType)) {
|
||||
// tranquility = type;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (tranquility != null) {
|
||||
// BMLog.API_VERBOSE.info("Value Manager: Set tranquility value of {} to {} @ {}", state, tranquilityType, value);
|
||||
// this.tranquility.put(state, new TranquilityStack(tranquility, value));
|
||||
// } else BMLog.API.warn("Invalid tranquility type: {}.", tranquilityType);
|
||||
}
|
||||
|
||||
// TODO - Tranquility
|
||||
// public void setTranquility(Block block, TranquilityStack tranquilityStack) {
|
||||
// for (IBlockState state : block.getBlockState().getValidStates()) {
|
||||
// BMLog.API_VERBOSE.info("Value Manager: Set tranquility value of {} to {} @ {}", state, tranquilityStack.type, tranquilityStack.value);
|
||||
// tranquility.put(state, tranquilityStack);
|
||||
// }
|
||||
// }
|
||||
|
||||
public Map<ResourceLocation, Integer> getSacrificial() {
|
||||
return ImmutableMap.copyOf(sacrificial);
|
||||
}
|
||||
|
||||
// TODO - Tranquility
|
||||
// public Map<IBlockState, TranquilityStack> getTranquility() {
|
||||
// return ImmutableMap.copyOf(tranquility);
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.wayoftime.bloodmagic.api.impl.recipe;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RecipeAlchemyArray {
|
||||
|
||||
@Nonnull
|
||||
private final Ingredient input;
|
||||
@Nonnull
|
||||
private final Ingredient catalyst;
|
||||
@Nonnull
|
||||
private final ItemStack output;
|
||||
@Nonnull
|
||||
private final ResourceLocation circleTexture;
|
||||
|
||||
public RecipeAlchemyArray(@Nonnull Ingredient input, @Nonnull Ingredient catalyst, @Nonnull ItemStack output, @Nullable ResourceLocation circleTexture) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(catalyst, "catalyst cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
|
||||
this.input = input;
|
||||
this.catalyst = catalyst;
|
||||
this.output = output;
|
||||
this.circleTexture = circleTexture == null ? new ResourceLocation(BloodMagic.MODID, "textures/models/AlchemyArrays/WIPArray.png") : circleTexture;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Ingredient getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Ingredient getCatalyst() {
|
||||
return catalyst;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemStack getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ResourceLocation getCircleTexture() {
|
||||
return circleTexture;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.wayoftime.bloodmagic.api.impl.recipe;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.util.NonNullList;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RecipeAlchemyTable {
|
||||
|
||||
@Nonnull
|
||||
private final NonNullList<Ingredient> input;
|
||||
@Nonnull
|
||||
private final ItemStack output;
|
||||
@Nonnegative
|
||||
private final int syphon;
|
||||
@Nonnegative
|
||||
private final int ticks;
|
||||
@Nonnegative
|
||||
private final int minimumTier;
|
||||
|
||||
public RecipeAlchemyTable(@Nonnull NonNullList<Ingredient> input, @Nonnull ItemStack output, int syphon, int ticks, int minimumTier) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative.");
|
||||
Preconditions.checkArgument(ticks >= 0, "ticks cannot be negative.");
|
||||
Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative.");
|
||||
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.syphon = syphon;
|
||||
this.ticks = ticks;
|
||||
this.minimumTier = minimumTier;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final NonNullList<Ingredient> getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final ItemStack getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public final int getSyphon() {
|
||||
return syphon;
|
||||
}
|
||||
|
||||
public final int getTicks() {
|
||||
return ticks;
|
||||
}
|
||||
|
||||
public final int getMinimumTier() {
|
||||
return minimumTier;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.wayoftime.bloodmagic.api.impl.recipe;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarTier;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RecipeBloodAltar {
|
||||
|
||||
@Nonnull
|
||||
private final Ingredient input;
|
||||
@Nonnull
|
||||
private final ItemStack output;
|
||||
@Nonnull
|
||||
private final AltarTier minimumTier;
|
||||
@Nonnegative
|
||||
private final int syphon;
|
||||
@Nonnegative
|
||||
private final int consumeRate;
|
||||
@Nonnegative
|
||||
private final int drainRate;
|
||||
|
||||
public RecipeBloodAltar(@Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnegative int minimumTier, @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative.");
|
||||
Preconditions.checkArgument(minimumTier <= AltarTier.values().length, "minimumTier cannot be higher than max tier");
|
||||
Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative.");
|
||||
Preconditions.checkArgument(consumeRate >= 0, "consumeRate cannot be negative.");
|
||||
Preconditions.checkArgument(drainRate >= 0, "drain cannot be negative.");
|
||||
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.minimumTier = AltarTier.values()[minimumTier];
|
||||
this.syphon = syphon;
|
||||
this.consumeRate = consumeRate;
|
||||
this.drainRate = drainRate;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final Ingredient getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final ItemStack getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AltarTier getMinimumTier() {
|
||||
return minimumTier;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public final int getSyphon() {
|
||||
return syphon;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public final int getConsumeRate() {
|
||||
return consumeRate;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public final int getDrainRate() {
|
||||
return drainRate;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.wayoftime.bloodmagic.api.impl.recipe;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.util.NonNullList;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RecipeSacrificeCraft {
|
||||
@Nonnull
|
||||
private final NonNullList<Ingredient> input;
|
||||
@Nonnull
|
||||
private final ItemStack output;
|
||||
@Nonnegative
|
||||
private final double healthRequired;
|
||||
|
||||
public RecipeSacrificeCraft(@Nonnull NonNullList<Ingredient> input, @Nonnull ItemStack output, @Nonnegative double healthRequired) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(healthRequired >= 0, "healthRequired cannot be negative.");
|
||||
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.healthRequired = healthRequired;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final NonNullList<Ingredient> getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final ItemStack getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public final double getHealthRequired() {
|
||||
return healthRequired;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.wayoftime.bloodmagic.api.impl.recipe;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.util.NonNullList;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RecipeTartaricForge {
|
||||
|
||||
@Nonnull
|
||||
private final NonNullList<Ingredient> input;
|
||||
@Nonnull
|
||||
private final ItemStack output;
|
||||
@Nonnegative
|
||||
private final double minimumSouls;
|
||||
@Nonnegative
|
||||
private final double soulDrain;
|
||||
|
||||
public RecipeTartaricForge(@Nonnull NonNullList<Ingredient> input, @Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain) {
|
||||
Preconditions.checkNotNull(input, "input cannot be null.");
|
||||
Preconditions.checkNotNull(output, "output cannot be null.");
|
||||
Preconditions.checkArgument(minimumSouls >= 0, "minimumSouls cannot be negative.");
|
||||
Preconditions.checkArgument(soulDrain >= 0, "soulDrain cannot be negative.");
|
||||
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.minimumSouls = minimumSouls;
|
||||
this.soulDrain = soulDrain;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final NonNullList<Ingredient> getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final ItemStack getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public final double getMinimumSouls() {
|
||||
return minimumSouls;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public final double getSoulDrain() {
|
||||
return soulDrain;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package com.wayoftime.bloodmagic.block;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.altar.IAltarManipulator;
|
||||
import com.wayoftime.bloodmagic.core.util.register.IItemProvider;
|
||||
import com.wayoftime.bloodmagic.tile.TileBloodAltar;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.SoundType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockBloodAltar extends Block implements IItemProvider {
|
||||
|
||||
public BlockBloodAltar() {
|
||||
super(Material.ROCK);
|
||||
|
||||
setTranslationKey(BloodMagic.MODID + ":blood_altar");
|
||||
setCreativeTab(BloodMagic.TAB_BM);
|
||||
setHardness(2.0F);
|
||||
setResistance(5.0F);
|
||||
setSoundType(SoundType.STONE);
|
||||
setHarvestLevel("pickaxe", 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
if (!(tile instanceof TileBloodAltar) || !tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null))
|
||||
return false;
|
||||
|
||||
IItemHandler altarInv = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
|
||||
if (altarInv == null)
|
||||
return false;
|
||||
|
||||
if (player.isSneaking()) {
|
||||
ItemStack extracted = altarInv.extractItem(0, altarInv.getSlotLimit(0), false);
|
||||
if (extracted.isEmpty())
|
||||
return false;
|
||||
|
||||
ItemHandlerHelper.giveItemToPlayer(player, extracted);
|
||||
tile.markDirty();
|
||||
return true;
|
||||
} else {
|
||||
ItemStack held = player.getHeldItem(hand);
|
||||
if (held.isEmpty())
|
||||
return false;
|
||||
|
||||
if (held.getItem() instanceof IAltarManipulator && ((IAltarManipulator) held.getItem()).tryManipulate(player, held, world, pos))
|
||||
return false;
|
||||
|
||||
if (!altarInv.extractItem(0, 1, true).isEmpty())
|
||||
return false;
|
||||
|
||||
ItemStack insert = held.copy();
|
||||
insert.setCount(1);
|
||||
ItemHandlerHelper.insertItem(altarInv, insert, false);
|
||||
((TileBloodAltar) tile).resetProgress();
|
||||
tile.markDirty();
|
||||
if (!player.capabilities.isCreativeMode)
|
||||
held.shrink(1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void breakBlock(World world, BlockPos pos, IBlockState state) {
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
if (tile == null)
|
||||
return;
|
||||
|
||||
IItemHandler itemHandler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
|
||||
if (itemHandler != null)
|
||||
for (int i = 0; i < itemHandler.getSlots(); i++)
|
||||
InventoryHelper.spawnItemStack(world, pos.getX(), pos.getY(), pos.getZ(), itemHandler.getStackInSlot(i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalCube(IBlockState state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaqueCube(IBlockState state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean causesSuffocation(IBlockState state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullBlock(IBlockState state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullCube(IBlockState state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(IBlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TileEntity createTileEntity(World world, IBlockState state) {
|
||||
return new TileBloodAltar();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Item getItem() {
|
||||
return new ItemBlock(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.wayoftime.bloodmagic.block;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.type.BloodRunes;
|
||||
import net.minecraft.block.material.Material;
|
||||
|
||||
public class BlockBloodRune extends BlockMundane {
|
||||
|
||||
private final BloodRunes rune;
|
||||
|
||||
public BlockBloodRune(BloodRunes rune) {
|
||||
super(Material.ROCK, "blood_rune_" + rune.getName(), true);
|
||||
|
||||
this.rune = rune;
|
||||
}
|
||||
|
||||
public BloodRunes getRune() {
|
||||
return rune;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.wayoftime.bloodmagic.block;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.type.DemonWillType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockDemonDecor extends BlockMundane {
|
||||
|
||||
private final DemonWillType type;
|
||||
|
||||
public BlockDemonDecor(Material material, String decorType, DemonWillType type) {
|
||||
super(material, decorType + "_" + type.getName());
|
||||
|
||||
setTranslationKey(BloodMagic.MODID + ":" + decorType);
|
||||
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
|
||||
tooltip.add(I18n.format("tooltip.bloodmagic:demon_will_" + type.getName()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.wayoftime.bloodmagic.block;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.util.register.IItemProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// QoL default block
|
||||
public class BlockMundane extends Block implements IItemProvider {
|
||||
|
||||
private final boolean hasItem;
|
||||
|
||||
public BlockMundane(Material material, String name, boolean withItem) {
|
||||
super(material);
|
||||
|
||||
this.hasItem = withItem;
|
||||
|
||||
setTranslationKey(BloodMagic.MODID + ":" + name);
|
||||
setCreativeTab(BloodMagic.TAB_BM);
|
||||
setRegistryName(name);
|
||||
setDefaultState(getBlockState().getBaseState());
|
||||
}
|
||||
|
||||
public BlockMundane(Material material, String name) {
|
||||
this(material, name, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Item getItem() {
|
||||
return hasItem ? new ItemBlock(this) : null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.wayoftime.bloodmagic.block;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.util.register.IItemProvider;
|
||||
import com.wayoftime.bloodmagic.core.util.register.IVariantProvider;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.minecraft.block.BlockStairs;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// Because Mojang doesn't want us making our own stairs apparently
|
||||
public class BlockStairsExtended extends BlockStairs implements IItemProvider, IVariantProvider {
|
||||
|
||||
public BlockStairsExtended(IBlockState modelState) {
|
||||
super(modelState);
|
||||
|
||||
String name = modelState.getBlock().getRegistryName().getPath() + "_stairs";
|
||||
setRegistryName(name);
|
||||
setTranslationKey(BloodMagic.MODID + ":" + name);
|
||||
setCreativeTab(BloodMagic.TAB_BM);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Item getItem() {
|
||||
return new ItemBlock(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectVariants(Int2ObjectMap<String> variants) {
|
||||
variants.put(0, "facing=south,half=bottom,shape=straight");
|
||||
}
|
||||
}
|
56
src/main/java/com/wayoftime/bloodmagic/client/Sprite.java
Normal file
56
src/main/java/com/wayoftime/bloodmagic/client/Sprite.java
Normal file
|
@ -0,0 +1,56 @@
|
|||
package com.wayoftime.bloodmagic.client;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class Sprite {
|
||||
|
||||
private final ResourceLocation textureLocation;
|
||||
private final int textureX;
|
||||
private final int textureY;
|
||||
private final int textureWidth;
|
||||
private final int textureHeight;
|
||||
|
||||
public Sprite(ResourceLocation textureLocation, int textureX, int textureY, int textureWidth, int textureHeight) {
|
||||
this.textureLocation = textureLocation;
|
||||
this.textureX = textureX;
|
||||
this.textureY = textureY;
|
||||
this.textureWidth = textureWidth;
|
||||
this.textureHeight = textureHeight;
|
||||
}
|
||||
|
||||
public ResourceLocation getTextureLocation() {
|
||||
return textureLocation;
|
||||
}
|
||||
|
||||
public int getTextureX() {
|
||||
return textureX;
|
||||
}
|
||||
|
||||
public int getTextureY() {
|
||||
return textureY;
|
||||
}
|
||||
|
||||
public int getTextureWidth() {
|
||||
return textureWidth;
|
||||
}
|
||||
|
||||
public int getTextureHeight() {
|
||||
return textureHeight;
|
||||
}
|
||||
|
||||
public void draw(int x, int y) {
|
||||
float f = 0.00390625F;
|
||||
float f1 = 0.00390625F;
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(7, DefaultVertexFormats.POSITION_TEX);
|
||||
buffer.pos((double) x, (double) (y + getTextureHeight()), 1.0F).tex((double) ((float) (getTextureX()) * f), (double) ((float) (getTextureY() + getTextureHeight()) * f1)).endVertex();
|
||||
buffer.pos((double) (x + getTextureWidth()), (double) (y + getTextureHeight()), 1.0F).tex((double) ((float) (getTextureX() + getTextureWidth()) * f), (double) ((float) (getTextureY() + getTextureHeight()) * f1)).endVertex();
|
||||
buffer.pos((double) (x + getTextureWidth()), (double) (y), 1.0F).tex((double) ((float) (getTextureX() + getTextureWidth()) * f), (double) ((float) (getTextureY()) * f1)).endVertex();
|
||||
buffer.pos((double) x, (double) (y), 1.0F).tex((double) ((float) (getTextureX()) * f), (double) ((float) (getTextureY()) * f1)).endVertex();
|
||||
tessellator.draw();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.wayoftime.bloodmagic.client.render;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagic;
|
||||
import com.wayoftime.bloodmagic.tile.TileBloodAltar;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidTank;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
|
||||
public class TESRBloodAltar extends TileEntitySpecialRenderer<TileBloodAltar> {
|
||||
|
||||
private static final float MIN_HEIGHT = 0.499f;
|
||||
private static final float MAX_HEIGHT = 0.745f;
|
||||
private static final float SIZE = 0.8F;
|
||||
|
||||
@Override
|
||||
public void render(TileBloodAltar te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
|
||||
GlStateManager.pushMatrix();
|
||||
renderFluid(te, x, y, z);
|
||||
GlStateManager.popMatrix();
|
||||
GlStateManager.pushMatrix();
|
||||
renderItem(te, x, y, z);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private void renderFluid(TileBloodAltar te, double x, double y, double z) {
|
||||
FluidTank fluidTank = (FluidTank) te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null);
|
||||
float level = (float) fluidTank.getFluidAmount() / (float) fluidTank.getCapacity();
|
||||
if (level <= 0)
|
||||
return;
|
||||
|
||||
GlStateManager.translate(x, y, z);
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder builder = tessellator.getBuffer();
|
||||
TextureAtlasSprite stillImage = Minecraft.getMinecraft().getTextureMapBlocks().getTextureExtry(RegistrarBloodMagic.FLUID_LIFE_ESSENCE.getStill().toString());
|
||||
if (stillImage == null)
|
||||
return;
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
|
||||
setGLColorFromInt(RegistrarBloodMagic.FLUID_LIFE_ESSENCE.getColor());
|
||||
GlStateManager.translate(0.5, MIN_HEIGHT + ((MAX_HEIGHT - MIN_HEIGHT) * level), 0.5);
|
||||
|
||||
double uMin = (double) stillImage.getMinU();
|
||||
double uMax = (double) stillImage.getMaxU();
|
||||
double vMin = (double) stillImage.getMinV();
|
||||
double vMax = (double) stillImage.getMaxV();
|
||||
|
||||
builder.begin(7, DefaultVertexFormats.POSITION_TEX);
|
||||
builder.pos(SIZE / 2f, 0, SIZE / 2f).tex(uMax, vMax).endVertex();
|
||||
builder.pos(SIZE / 2f, 0, -SIZE / 2f).tex(uMax, vMin).endVertex();
|
||||
builder.pos(-SIZE / 2f, 0, -SIZE / 2f).tex(uMin, vMin).endVertex();
|
||||
builder.pos(-SIZE / 2f, 0, SIZE / 2f).tex(uMin, vMax).endVertex();
|
||||
tessellator.draw();
|
||||
}
|
||||
|
||||
private void renderItem(TileBloodAltar te, double x, double y, double z) {
|
||||
ItemStack contained = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(0);
|
||||
if (contained.isEmpty())
|
||||
return;
|
||||
|
||||
GlStateManager.translate(x, y, z);
|
||||
RenderItem itemRenderer = Minecraft.getMinecraft().getRenderItem();
|
||||
float rotation = 720.0F * (System.currentTimeMillis() & 0x3FFFL) / 0x3FFFL;
|
||||
|
||||
GlStateManager.translate(0.5F, 0.9F, 0.5F);
|
||||
GlStateManager.rotate(rotation, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
itemRenderer.renderItem(contained, ItemCameraTransforms.TransformType.GROUND);
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
}
|
||||
|
||||
private static void setGLColorFromInt(int color) {
|
||||
float red = (color >> 16 & 0xFF) / 255.0F;
|
||||
float green = (color >> 8 & 0xFF) / 255.0F;
|
||||
float blue = (color & 0xFF) / 255.0F;
|
||||
|
||||
GlStateManager.color(red, green, blue, 1.0F);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.wayoftime.bloodmagic.core;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import net.minecraftforge.common.config.Config;
|
||||
|
||||
@Config(modid = BloodMagic.MODID, name = BloodMagic.MODID + "/" + BloodMagic.MODID, category = "")
|
||||
public class BloodMagicConfiguration {
|
||||
|
||||
public static LoggingConfig logging = new LoggingConfig();
|
||||
|
||||
public static class LoggingConfig {
|
||||
@Config.Comment("Prints information like plugin detection and how long it takes plugins to load their various stages.")
|
||||
public boolean enableApiLogging = true;
|
||||
@Config.Comment("Extremely verbose logging for things like recipe addition.")
|
||||
public boolean enableVerboseApiLogging;
|
||||
@Config.Comment("Debug printing that may help with debugging certain issues.")
|
||||
public boolean enableDebugLogging;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.wayoftime.bloodmagic.core;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.util.BMLog;
|
||||
import com.wayoftime.bloodmagic.core.util.PluginUtil;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.event.RegistryEvent;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = BloodMagic.MODID)
|
||||
public class RegistrarBloodMagic {
|
||||
|
||||
public static final Fluid FLUID_LIFE_ESSENCE = new Fluid(BloodMagic.MODID + ":life_essence", new ResourceLocation(BloodMagic.MODID, "blocks/life_essence_flowing"), new ResourceLocation(BloodMagic.MODID, "blocks/life_essence_still"), 0x8C150C);
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerBlocks(RegistryEvent.Register<Block> event) {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
RegistrarBloodMagicBlocks.register(event.getRegistry());
|
||||
BMLog.DEBUG.info("Registered blocks in {}.", stopwatch.stop());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerItems(RegistryEvent.Register<Item> event) {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
RegistrarBloodMagicItems.register(event.getRegistry());
|
||||
BMLog.DEBUG.info("Registered items in {}.", stopwatch.stop());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerRecipes(RegistryEvent<IRecipe> event) {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
PluginUtil.handlePluginStep(PluginUtil.RegistrationStep.RECIPE_REGISTER);
|
||||
BMLog.DEBUG.info("Registered recipes in {}.", stopwatch.stop());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package com.wayoftime.bloodmagic.core;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.block.BlockBloodAltar;
|
||||
import com.wayoftime.bloodmagic.block.BlockBloodRune;
|
||||
import com.wayoftime.bloodmagic.block.BlockMundane;
|
||||
import com.wayoftime.bloodmagic.client.render.TESRBloodAltar;
|
||||
import com.wayoftime.bloodmagic.core.type.BloodRunes;
|
||||
import com.wayoftime.bloodmagic.tile.TileBloodAltar;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.client.renderer.block.statemap.StateMapperBase;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.ModelRegistryEvent;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.fluids.BlockFluidClassic;
|
||||
import net.minecraftforge.fluids.FluidRegistry;
|
||||
import net.minecraftforge.fml.client.registry.ClientRegistry;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GameRegistry.ObjectHolder(BloodMagic.MODID)
|
||||
@Mod.EventBusSubscriber(modid = BloodMagic.MODID)
|
||||
public class RegistrarBloodMagicBlocks {
|
||||
|
||||
public static final Block LIFE_ESSENCE = Blocks.AIR;
|
||||
public static final Block BLOOD_ALTAR = Blocks.AIR;
|
||||
public static final Block BLOODSTONE_BRICK= Blocks.AIR;
|
||||
public static final Block BLOODSTONE_TILE = Blocks.AIR;
|
||||
|
||||
public static final Block BLOOD_RUNE_BLANK = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_SPEED = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_EFFICIENCY = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_SACRIFICE = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_SELF_SACRIFICE = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_DISPLACEMENT = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_CAPACITY = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_AUGMENTED_CAPACITY = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_ORB = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_ACCELERATION = Blocks.AIR;
|
||||
public static final Block BLOOD_RUNE_CHARGING = Blocks.AIR;
|
||||
|
||||
static List<Block> blocks;
|
||||
|
||||
public static void register(IForgeRegistry<Block> registry) {
|
||||
GameRegistry.registerTileEntity(TileBloodAltar.class, new ResourceLocation(BloodMagic.MODID, "blood_altar"));
|
||||
FluidRegistry.addBucketForFluid(RegistrarBloodMagic.FLUID_LIFE_ESSENCE);
|
||||
|
||||
blocks = Lists.newArrayList(
|
||||
new BlockFluidClassic(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, Material.WATER).setTranslationKey(BloodMagic.MODID + ".life_essence").setRegistryName("life_essence"),
|
||||
new BlockBloodAltar().setRegistryName("blood_altar"),
|
||||
new BlockMundane(Material.ROCK, "bloodstone_brick"),
|
||||
new BlockMundane(Material.ROCK, "bloodstone_tile")
|
||||
);
|
||||
|
||||
for (BloodRunes rune : BloodRunes.values())
|
||||
blocks.add(new BlockBloodRune(rune));
|
||||
|
||||
// TODO - Re-enable whenever I feel like it
|
||||
// for (DemonWillType type : DemonWillType.VALUES) {
|
||||
// blocks.add(new BlockDemonDecor(Material.ROCK, "demon_stone", type));
|
||||
// blocks.add(new BlockDemonDecor(Material.ROCK, "demon_stone_polished", type));
|
||||
// Block brickBlock;
|
||||
// blocks.add(brickBlock = new BlockDemonDecor(Material.ROCK, "demon_brick", type));
|
||||
// blocks.add(new BlockDemonDecor(Material.ROCK, "demon_brick_small", type));
|
||||
// blocks.add(new BlockDemonDecor(Material.ROCK, "demon_tile", type));
|
||||
// blocks.add(new BlockDemonDecor(Material.ROCK, "demon_tile_special", type));
|
||||
// blocks.add(new BlockDemonDecor(Material.IRON, "demon_metal", type));
|
||||
// blocks.add(new BlockStairsExtended(brickBlock.getDefaultState()) {
|
||||
// @SideOnly(Side.CLIENT)
|
||||
// @Override
|
||||
// public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
|
||||
// tooltip.add(I18n.format("tooltip.bloodmagic:demon_will_" + type.getName()));
|
||||
// }
|
||||
// }.setTranslationKey(BloodMagic.MODID + ":demon_stairs"));
|
||||
// }
|
||||
|
||||
registry.registerAll(blocks.toArray(new Block[0]));
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@SubscribeEvent
|
||||
public static void registerModels(ModelRegistryEvent event) {
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileBloodAltar.class, new TESRBloodAltar());
|
||||
|
||||
ModelLoader.setCustomStateMapper(LIFE_ESSENCE, new StateMapperBase() {
|
||||
@Override
|
||||
protected ModelResourceLocation getModelResourceLocation(IBlockState state) {
|
||||
return new ModelResourceLocation(state.getBlock().getRegistryName(), "fluid");
|
||||
}
|
||||
});
|
||||
|
||||
for (Block block : blocks) {
|
||||
Item item = Item.getItemFromBlock(block);
|
||||
if (item == Items.AIR)
|
||||
continue;
|
||||
|
||||
boolean flag = RegistrarBloodMagicItems.handleModel(item);
|
||||
|
||||
|
||||
if (!flag) // If we haven't registered a model by now, we don't need any special handling so we'll just use the default model.
|
||||
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.getRegistryName(), "normal"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package com.wayoftime.bloodmagic.core;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.network.BloodOrb;
|
||||
import com.wayoftime.bloodmagic.core.type.DemonWillType;
|
||||
import com.wayoftime.bloodmagic.core.type.SlateType;
|
||||
import com.wayoftime.bloodmagic.core.util.register.IItemProvider;
|
||||
import com.wayoftime.bloodmagic.core.util.register.IVariantProvider;
|
||||
import com.wayoftime.bloodmagic.item.*;
|
||||
import com.wayoftime.bloodmagic.item.sigil.ItemSigil;
|
||||
import com.wayoftime.bloodmagic.item.sigil.SigilAir;
|
||||
import com.wayoftime.bloodmagic.item.sigil.SigilDivination;
|
||||
import com.wayoftime.bloodmagic.item.sigil.SigilFastMiner;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.ModelRegistryEvent;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GameRegistry.ObjectHolder(BloodMagic.MODID)
|
||||
@Mod.EventBusSubscriber(modid = BloodMagic.MODID)
|
||||
public class RegistrarBloodMagicItems {
|
||||
|
||||
public static final Item BLOOD_ORB_WEAK = Items.AIR;
|
||||
public static final Item BLOOD_ORB_APPRENTICE = Items.AIR;
|
||||
public static final Item BLOOD_ORB_MAGICIAN = Items.AIR;
|
||||
public static final Item BLOOD_ORB_MASTER = Items.AIR;
|
||||
public static final Item BLOOD_ORB_ARCHMAGE = Items.AIR;
|
||||
public static final Item BLOOD_ORB_TRANSCENDENT = Items.AIR;
|
||||
|
||||
public static final Item DAGGER_SELF_SACRIFICE = Items.AIR;
|
||||
public static final Item DAGGER_SELF_SACRIFICE_CREATIVE = Items.AIR;
|
||||
|
||||
public static final Item SLATE_BLANK = Items.AIR;
|
||||
public static final Item SLATE_REINFORCED = Items.AIR;
|
||||
public static final Item SLATE_IMBUED = Items.AIR;
|
||||
public static final Item SLATE_DEMONIC = Items.AIR;
|
||||
public static final Item SLATE_ETHEREAL = Items.AIR;
|
||||
|
||||
public static final Item SIGIL_DIVINATION = Items.AIR;
|
||||
public static final Item SIGIL_AIR = Items.AIR;
|
||||
public static final Item SIGIL_FAST_MINER = Items.AIR;
|
||||
|
||||
public static final Item LIVING_ARMOR_HEAD = Items.AIR;
|
||||
public static final Item LIVING_ARMOR_CHEST = Items.AIR;
|
||||
public static final Item LIVING_ARMOR_LEGS = Items.AIR;
|
||||
public static final Item LIVING_ARMOR_FEET = Items.AIR;
|
||||
public static final Item LIVING_TOME = Items.AIR;
|
||||
|
||||
public static final Item DEMON_WILL_CRYSTAL_RAW = Items.AIR;
|
||||
public static final Item DEMON_WILL_CRYSTAL_CORROSIVE = Items.AIR;
|
||||
public static final Item DEMON_WILL_CRYSTAL_DESTRUCTIVE = Items.AIR;
|
||||
public static final Item DEMON_WILL_CRYSTAL_VENGEFUL = Items.AIR;
|
||||
public static final Item DEMON_WILL_CRYSTAL_STEADFAST = Items.AIR;
|
||||
|
||||
static List<Item> items = Lists.newArrayList();
|
||||
|
||||
public static void register(IForgeRegistry<Item> registry) {
|
||||
for (Block block : RegistrarBloodMagicBlocks.blocks) {
|
||||
if (block instanceof IItemProvider) {
|
||||
Item item = ((IItemProvider) block).getItem();
|
||||
if (item != null)
|
||||
items.add(item.setRegistryName(block.getRegistryName()));
|
||||
}
|
||||
}
|
||||
|
||||
items.addAll(Lists.newArrayList(
|
||||
new ItemBloodOrb(new BloodOrb(new ResourceLocation(BloodMagic.MODID, "weak"), 1, 5000, 2)),
|
||||
new ItemBloodOrb(new BloodOrb(new ResourceLocation(BloodMagic.MODID, "apprentice"), 2, 25000, 5)),
|
||||
new ItemBloodOrb(new BloodOrb(new ResourceLocation(BloodMagic.MODID, "magician"), 3, 150000, 15)),
|
||||
new ItemBloodOrb(new BloodOrb(new ResourceLocation(BloodMagic.MODID, "master"), 4, 1000000, 25)),
|
||||
new ItemBloodOrb(new BloodOrb(new ResourceLocation(BloodMagic.MODID, "archmage"), 5, 10000000, 50)),
|
||||
new ItemBloodOrb(new BloodOrb(new ResourceLocation(BloodMagic.MODID, "transcendent"), 6, 30000000, 50)),
|
||||
new ItemDaggerSelfSacrifice(ItemDaggerSelfSacrifice.Type.NORMAL),
|
||||
new ItemDaggerSelfSacrifice(ItemDaggerSelfSacrifice.Type.CREATIVE),
|
||||
new ItemMundane("slate_" + SlateType.BLANK.getName()),
|
||||
new ItemMundane("slate_" + SlateType.REINFORCED.getName()),
|
||||
new ItemMundane("slate_" + SlateType.IMBUED.getName()),
|
||||
new ItemMundane("slate_" + SlateType.DEMONIC.getName()),
|
||||
new ItemMundane("slate_" + SlateType.ETHEREAL.getName()),
|
||||
new ItemSigil(new SigilDivination(), "divination"),
|
||||
new ItemSigil(new SigilAir(), "air"),
|
||||
new ItemSigil(new SigilFastMiner(), "fast_miner"),
|
||||
new ItemLivingArmor(EntityEquipmentSlot.HEAD),
|
||||
new ItemLivingArmor(EntityEquipmentSlot.CHEST),
|
||||
new ItemLivingArmor(EntityEquipmentSlot.LEGS),
|
||||
new ItemLivingArmor(EntityEquipmentSlot.FEET),
|
||||
new ItemLivingTome(),
|
||||
new ItemAltarBuilder()
|
||||
));
|
||||
|
||||
for (DemonWillType type : DemonWillType.VALUES)
|
||||
items.add(new ItemMundane("demon_will_crystal_" + type.getName()));
|
||||
|
||||
registry.registerAll(items.toArray(new Item[0]));
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@SubscribeEvent
|
||||
public static void registerModels(ModelRegistryEvent event) {
|
||||
for (Item item : items) {
|
||||
boolean flag = handleModel(item);
|
||||
|
||||
if (!flag) // If we haven't registered a model by now, we don't need any special handling so we'll just use the default model.
|
||||
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.getRegistryName(), item instanceof ItemBlock ? "normal" : "inventory"));
|
||||
}
|
||||
}
|
||||
|
||||
static boolean handleModel(Item item) {
|
||||
if (item instanceof IVariantProvider) {
|
||||
Int2ObjectMap<String> variants = new Int2ObjectOpenHashMap<>();
|
||||
((IVariantProvider) item).collectVariants(variants);
|
||||
for (Int2ObjectMap.Entry<String> entry : variants.int2ObjectEntrySet())
|
||||
ModelLoader.setCustomModelResourceLocation(item, entry.getIntKey(), new ModelResourceLocation(item.getRegistryName(), entry.getValue()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.wayoftime.bloodmagic.core;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.living.LivingUpgrade;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.event.RegistryEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* TODO - See checklist
|
||||
* - [-] Upgrades (Names pulled from 2.0 class names)
|
||||
* - [ ] Arrow Protect
|
||||
* - [ ] Arrow Shot
|
||||
* - [ ] Critical Strike
|
||||
* - [ ] Digging
|
||||
* - [ ] Elytra
|
||||
* - This will wait for Forge to add the ability to make them properly. I'm not adding that hacky shit back in.
|
||||
* - [ ] Experience
|
||||
* - [ ] Fall Protect
|
||||
* - [ ] Fire Resist
|
||||
* - [ ] Grave Digger
|
||||
* - [ ] Grim Reaper Sprint
|
||||
* - [ ] Health boost
|
||||
* - [-] Jump
|
||||
* - [ ] Knockback Resist
|
||||
* - [ ] Melee Damage
|
||||
* - [ ] Night Sight
|
||||
* - [ ] Physical Protect
|
||||
* - [ ] Poison Resist
|
||||
* - [ ] Repairing
|
||||
* - [ ] Self Sacrifice
|
||||
* - [ ] Solar Powered
|
||||
* - [ ] Speed
|
||||
* - [ ] Sprint Attack
|
||||
* - [ ] Step Assist
|
||||
* - [ ] Downgrades (Names pulled from 2.0 class names)
|
||||
* - [ ] Battle Hungry
|
||||
* - [ ] Crippled Arm
|
||||
* - [ ] Dig Slowdown
|
||||
* - [ ] Disoriented
|
||||
* - [ ] Melee Decrease
|
||||
* - [ ] Quenched
|
||||
* - [ ] Slippery
|
||||
* - [ ] Slow Heal
|
||||
* - [ ] Slowness
|
||||
* - [ ] Storm Trooper
|
||||
* - [-] Equipment
|
||||
* - [x] Living Helmet
|
||||
* - [x] Living Chestplate
|
||||
* - [x] Living Leggings
|
||||
* - [x] Living Boots
|
||||
* - [ ] Tools (Replacements for Bound equipment. Need their own (up|down)grade sets once implemented.)
|
||||
* - [ ] Living Sword
|
||||
* - [ ] Living Pickaxe
|
||||
* - [ ] Living Axe
|
||||
* - [ ] Living Shovel
|
||||
*/
|
||||
@Mod.EventBusSubscriber(modid = BloodMagic.MODID)
|
||||
public class RegistrarBloodMagicLivingArmor {
|
||||
|
||||
public static final Map<ResourceLocation, LivingUpgrade> UPGRADES = Maps.newHashMap();
|
||||
public static final LivingUpgrade JUMP = new LivingUpgrade(new ResourceLocation(BloodMagic.MODID, "jump"), levels -> {
|
||||
levels.add(new LivingUpgrade.UpgradeLevel(10, 1));
|
||||
levels.add(new LivingUpgrade.UpgradeLevel(20, 5));
|
||||
levels.add(new LivingUpgrade.UpgradeLevel(30, 25));
|
||||
levels.add(new LivingUpgrade.UpgradeLevel(40, 125));
|
||||
});
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerUpgrades(RegistryEvent.Register<Item> event) {
|
||||
addUpgrade(JUMP);
|
||||
}
|
||||
|
||||
private static void addUpgrade(LivingUpgrade upgrade) {
|
||||
UPGRADES.put(upgrade.getKey(), upgrade);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.wayoftime.bloodmagic.core;
|
||||
|
||||
import com.wayoftime.bloodmagic.api.impl.BloodMagicRecipeRegistrar;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarTier;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.FluidUtil;
|
||||
import net.minecraftforge.oredict.OreIngredient;
|
||||
|
||||
import static com.wayoftime.bloodmagic.core.RegistrarBloodMagicItems.*;
|
||||
|
||||
public class RegistrarBloodMagicRecipes {
|
||||
|
||||
public static void registerAltarRecipes(BloodMagicRecipeRegistrar registrar) {
|
||||
// Tier 1
|
||||
registrar.addBloodAltar(new OreIngredient("gemDiamond"), new ItemStack(BLOOD_ORB_WEAK), AltarTier.ONE, 2000, 2, 1);
|
||||
registrar.addBloodAltar(new OreIngredient("stone"), new ItemStack(SLATE_BLANK), AltarTier.ONE, 1000, 5, 5);
|
||||
registrar.addBloodAltar(Ingredient.fromItem(Items.BUCKET), FluidUtil.getFilledBucket(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, 1000)), AltarTier.ONE, 1000, 5, 5);
|
||||
|
||||
// Tier 2
|
||||
registrar.addBloodAltar(new OreIngredient("blockRedstone"), new ItemStack(BLOOD_ORB_APPRENTICE), AltarTier.TWO, 5000, 5, 5);
|
||||
registrar.addBloodAltar(Ingredient.fromItem(SLATE_BLANK), new ItemStack(SLATE_REINFORCED), AltarTier.TWO, 2000, 5, 5);
|
||||
|
||||
// Tier 3
|
||||
registrar.addBloodAltar(new OreIngredient("blockGold"), new ItemStack(BLOOD_ORB_MAGICIAN), AltarTier.THREE, 25000, 20, 20);
|
||||
registrar.addBloodAltar(Ingredient.fromItem(SLATE_REINFORCED), new ItemStack(SLATE_IMBUED), AltarTier.THREE, 5000, 15, 10);
|
||||
|
||||
// Tier 4
|
||||
registrar.addBloodAltar(new OreIngredient("ingotIron"), new ItemStack(BLOOD_ORB_MASTER), AltarTier.FOUR, 40000, 30, 50); // TODO - Blood Shard input
|
||||
registrar.addBloodAltar(Ingredient.fromItem(SLATE_IMBUED), new ItemStack(SLATE_DEMONIC), AltarTier.FOUR, 15000, 20, 20);
|
||||
|
||||
// Tier 5
|
||||
registrar.addBloodAltar(new OreIngredient("netherStar"), new ItemStack(BLOOD_ORB_ARCHMAGE), AltarTier.FIVE, 80000, 50, 100);
|
||||
registrar.addBloodAltar(Ingredient.fromItem(SLATE_DEMONIC), new ItemStack(SLATE_ETHEREAL), AltarTier.FIVE, 30000, 40, 100);
|
||||
|
||||
// Tier 6
|
||||
registrar.addBloodAltar(new OreIngredient("gemDiamond"), new ItemStack(BLOOD_ORB_TRANSCENDENT), AltarTier.SIX, 200000, 100, 200); // TODO - Whatever this input is supposed to be
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.wayoftime.bloodmagic.core.altar;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.type.ComponentType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class AltarComponent {
|
||||
|
||||
private final BlockPos offset;
|
||||
private final ComponentType type;
|
||||
private boolean upgradeSlot;
|
||||
|
||||
public AltarComponent(BlockPos offset, ComponentType type) {
|
||||
this.offset = offset;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public AltarComponent(BlockPos offset) {
|
||||
this(offset, ComponentType.NOT_AIR);
|
||||
}
|
||||
|
||||
public BlockPos getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public ComponentType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public AltarComponent asUpgradeSlot() {
|
||||
this.upgradeSlot = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isUpgradeSlot() {
|
||||
return upgradeSlot;
|
||||
}
|
||||
}
|
147
src/main/java/com/wayoftime/bloodmagic/core/altar/AltarTier.java
Normal file
147
src/main/java/com/wayoftime/bloodmagic/core/altar/AltarTier.java
Normal file
|
@ -0,0 +1,147 @@
|
|||
package com.wayoftime.bloodmagic.core.altar;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.wayoftime.bloodmagic.core.type.ComponentType.*;
|
||||
|
||||
public enum AltarTier {
|
||||
|
||||
ONE {
|
||||
@Override
|
||||
public void buildComponents(Consumer<AltarComponent> components) {
|
||||
// No-op
|
||||
}
|
||||
},
|
||||
TWO {
|
||||
@Override
|
||||
public void buildComponents(Consumer<AltarComponent> components) {
|
||||
components.accept(new AltarComponent(new BlockPos(-1, -1, -1), BLOOD_RUNE));
|
||||
components.accept(new AltarComponent(new BlockPos(0, -1, -1), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(1, -1, -1), BLOOD_RUNE));
|
||||
components.accept(new AltarComponent(new BlockPos(-1, -1, 0), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(1, -1, 0), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(-1, -1, 1), BLOOD_RUNE));
|
||||
components.accept(new AltarComponent(new BlockPos(0, -1, 1), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(1, -1, 1), BLOOD_RUNE));
|
||||
}
|
||||
},
|
||||
THREE {
|
||||
@Override
|
||||
public void buildComponents(Consumer<AltarComponent> components) {
|
||||
// Re-list the tier 2 non-upgrade components. Leaves out the upgradeable components so they aren't double counted
|
||||
components.accept(new AltarComponent(new BlockPos(-1, -1, -1), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(1, -1, -1), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(-1, -1, 1), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(1, -1, 1), BLOOD_RUNE).asUpgradeSlot());
|
||||
|
||||
components.accept(new AltarComponent(new BlockPos(-3, -1, -3)));
|
||||
components.accept(new AltarComponent(new BlockPos(-3, 0, -3)));
|
||||
components.accept(new AltarComponent(new BlockPos(3, -1, -3)));
|
||||
components.accept(new AltarComponent(new BlockPos(3, 0, -3)));
|
||||
components.accept(new AltarComponent(new BlockPos(-3, -1, 3)));
|
||||
components.accept(new AltarComponent(new BlockPos(-3, 0, 3)));
|
||||
components.accept(new AltarComponent(new BlockPos(3, -1, 3)));
|
||||
components.accept(new AltarComponent(new BlockPos(3, 0, 3)));
|
||||
components.accept(new AltarComponent(new BlockPos(-3, 1, -3), GLOWSTONE));
|
||||
components.accept(new AltarComponent(new BlockPos(3, 1, -3), GLOWSTONE));
|
||||
components.accept(new AltarComponent(new BlockPos(-3, 1, 3), GLOWSTONE));
|
||||
components.accept(new AltarComponent(new BlockPos(3, 1, 3), GLOWSTONE));
|
||||
|
||||
for (int i = -2; i <= 2; i++) {
|
||||
components.accept(new AltarComponent(new BlockPos(3, -2, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(-3, -2, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -2, 3), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -2, -3), BLOOD_RUNE).asUpgradeSlot());
|
||||
}
|
||||
}
|
||||
},
|
||||
FOUR {
|
||||
@Override
|
||||
public void buildComponents(Consumer<AltarComponent> components) {
|
||||
for (int i = -3; i <= 3; i++) {
|
||||
components.accept(new AltarComponent(new BlockPos(5, -3, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(-5, -3, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -3, 5), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -3, -5), BLOOD_RUNE).asUpgradeSlot());
|
||||
}
|
||||
|
||||
for (int i = -2; i <= 1; i++) {
|
||||
components.accept(new AltarComponent(new BlockPos(5, i, 5)));
|
||||
components.accept(new AltarComponent(new BlockPos(5, i, -5)));
|
||||
components.accept(new AltarComponent(new BlockPos(-5, i, -5)));
|
||||
components.accept(new AltarComponent(new BlockPos(-5, i, 5)));
|
||||
}
|
||||
|
||||
components.accept(new AltarComponent(new BlockPos(5, 2, 5), BLOODSTONE));
|
||||
components.accept(new AltarComponent(new BlockPos(5, 2, -5), BLOODSTONE));
|
||||
components.accept(new AltarComponent(new BlockPos(-5, 2, -5), BLOODSTONE));
|
||||
components.accept(new AltarComponent(new BlockPos(-5, 2, 5), BLOODSTONE));
|
||||
}
|
||||
},
|
||||
FIVE {
|
||||
@Override
|
||||
public void buildComponents(Consumer<AltarComponent> components) {
|
||||
components.accept(new AltarComponent(new BlockPos(-8, -3, 8), BEACON));
|
||||
components.accept(new AltarComponent(new BlockPos(-8, -3, -8), BEACON));
|
||||
components.accept(new AltarComponent(new BlockPos(8, -3, -8), BEACON));
|
||||
components.accept(new AltarComponent(new BlockPos(8, -3, 8), BEACON));
|
||||
|
||||
for (int i = -6; i <= 6; i++) {
|
||||
components.accept(new AltarComponent(new BlockPos(8, -4, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(-8, -4, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -4, 8), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -4, -8), BLOOD_RUNE).asUpgradeSlot());
|
||||
}
|
||||
}
|
||||
},
|
||||
SIX {
|
||||
@Override
|
||||
public void buildComponents(Consumer<AltarComponent> components) {
|
||||
for (int i = -4; i <= 2; i++) {
|
||||
components.accept(new AltarComponent(new BlockPos(11, i, 11)));
|
||||
components.accept(new AltarComponent(new BlockPos(-11, i, -11)));
|
||||
components.accept(new AltarComponent(new BlockPos(11, i, -11)));
|
||||
components.accept(new AltarComponent(new BlockPos(-11, i, 11)));
|
||||
}
|
||||
|
||||
components.accept(new AltarComponent(new BlockPos(11, 3, 11), CRYSTAL));
|
||||
components.accept(new AltarComponent(new BlockPos(-11, 3, -11), CRYSTAL));
|
||||
components.accept(new AltarComponent(new BlockPos(11, 3, -11), CRYSTAL));
|
||||
components.accept(new AltarComponent(new BlockPos(-11, 3, 11), CRYSTAL));
|
||||
|
||||
for (int i = -9; i <= 9; i++) {
|
||||
components.accept(new AltarComponent(new BlockPos(11, -5, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(-11, -5, i), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -5, 11), BLOOD_RUNE).asUpgradeSlot());
|
||||
components.accept(new AltarComponent(new BlockPos(i, -5, -11), BLOOD_RUNE).asUpgradeSlot());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static final AltarTier[] VALUES = values();
|
||||
|
||||
private final List<AltarComponent> components;
|
||||
private final int displayInt;
|
||||
|
||||
AltarTier() {
|
||||
List<AltarComponent> list = Lists.newArrayList();
|
||||
buildComponents(list::add);
|
||||
this.components = ImmutableList.copyOf(list);
|
||||
this.displayInt = ordinal() + 1;
|
||||
}
|
||||
|
||||
public abstract void buildComponents(Consumer<AltarComponent> components);
|
||||
|
||||
public List<AltarComponent> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public int getDisplayNumber() {
|
||||
return displayInt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.wayoftime.bloodmagic.core.altar;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.wayoftime.bloodmagic.core.type.BloodRunes;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import static com.wayoftime.bloodmagic.core.type.BloodRunes.*;
|
||||
|
||||
public class AltarUpgrades {
|
||||
|
||||
private final EnumMap<BloodRunes, Integer> upgrades;
|
||||
|
||||
public AltarUpgrades() {
|
||||
this.upgrades = Maps.newEnumMap(BloodRunes.class);
|
||||
}
|
||||
|
||||
public AltarUpgrades upgrade(BloodRunes runeType) {
|
||||
upgrades.compute(runeType, (k, v) -> v == null ? 1 : v + 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getAccelerationCount() {
|
||||
return getCount(ACCELERATION);
|
||||
}
|
||||
|
||||
public float getCapacityModifier() {
|
||||
return (float) ((1 * Math.pow(1.10, getCount(AUGMENTED_CAPACITY))) + 0.20 * getCount(CAPACITY));
|
||||
}
|
||||
|
||||
public int getChargingFrequency() {
|
||||
return Math.max(20 - getCount(ACCELERATION), 1);
|
||||
}
|
||||
|
||||
public int getChargingRate() {
|
||||
return (int) (10 * getCount(CHARGING) * (1 + getConsumptionModifier() / 2));
|
||||
}
|
||||
|
||||
public float getConsumptionModifier() {
|
||||
return (float) (0.20 * getCount(SPEED));
|
||||
}
|
||||
|
||||
public float getDislocationModifier() {
|
||||
return (float) (Math.pow(1.2, getCount(DISPLACEMENT)));
|
||||
}
|
||||
|
||||
public float getEfficiencyModifier() {
|
||||
return (float) Math.pow(0.85, getCount(EFFICIENCY));
|
||||
}
|
||||
|
||||
public int getMaxCharge() {
|
||||
return (int) (Fluid.BUCKET_VOLUME * Math.max(0.5 * getCapacityModifier(), 1) * getCount(CHARGING));
|
||||
}
|
||||
|
||||
public float getOrbCapacityModifier() {
|
||||
return (float) (1.02 * getCount(ORB));
|
||||
}
|
||||
|
||||
public float getSacrificeModifier() {
|
||||
return (float) (0.10 * getCount(SACRIFICE));
|
||||
}
|
||||
|
||||
public float getSelfSacrificeModifier() {
|
||||
return (float) (0.10 * getCount(SELF_SACRIFICE));
|
||||
}
|
||||
|
||||
public int getCount(BloodRunes rune) {
|
||||
return upgrades.getOrDefault(rune, 0);
|
||||
}
|
||||
}
|
153
src/main/java/com/wayoftime/bloodmagic/core/altar/AltarUtil.java
Normal file
153
src/main/java/com/wayoftime/bloodmagic/core/altar/AltarUtil.java
Normal file
|
@ -0,0 +1,153 @@
|
|||
package com.wayoftime.bloodmagic.core.altar;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.wayoftime.bloodmagic.api.impl.BloodMagicAPI;
|
||||
import com.wayoftime.bloodmagic.block.BlockBloodRune;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicBlocks;
|
||||
import com.wayoftime.bloodmagic.core.type.ComponentType;
|
||||
import com.wayoftime.bloodmagic.core.util.BooleanResult;
|
||||
import com.wayoftime.bloodmagic.event.SacrificeEvent;
|
||||
import com.wayoftime.bloodmagic.tile.TileBloodAltar;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
||||
public class AltarUtil {
|
||||
|
||||
private static final EnumMap<ComponentType, IBlockState> COMPONENT_DEFAULT_STATES;
|
||||
static {
|
||||
COMPONENT_DEFAULT_STATES = Maps.newEnumMap(ComponentType.class);
|
||||
COMPONENT_DEFAULT_STATES.put(ComponentType.GLOWSTONE, Blocks.GLOWSTONE.getDefaultState());
|
||||
COMPONENT_DEFAULT_STATES.put(ComponentType.BLOODSTONE, RegistrarBloodMagicBlocks.BLOODSTONE_BRICK.getDefaultState());
|
||||
COMPONENT_DEFAULT_STATES.put(ComponentType.BEACON, Blocks.BEACON.getDefaultState());
|
||||
COMPONENT_DEFAULT_STATES.put(ComponentType.BLOOD_RUNE, RegistrarBloodMagicBlocks.BLOOD_RUNE_BLANK.getDefaultState());
|
||||
COMPONENT_DEFAULT_STATES.put(ComponentType.CRYSTAL, Blocks.BEDROCK.getDefaultState()); // FIXME - Crystal
|
||||
COMPONENT_DEFAULT_STATES.put(ComponentType.NOT_AIR, Blocks.STONEBRICK.getDefaultState());
|
||||
}
|
||||
|
||||
public static BooleanResult<Integer> handleSacrifice(EntityLivingBase living, int baseAmount) {
|
||||
TileBloodAltar altar = findNearestAltar(living.getEntityWorld(), new BlockPos(living), 2);
|
||||
if (altar == null)
|
||||
return new BooleanResult<>(0, false);
|
||||
|
||||
boolean isPlayer = living instanceof EntityPlayer;
|
||||
AltarUpgrades upgrades = altar.getUpgrades();
|
||||
int modifiedAmount = (int) (baseAmount * (1 + (isPlayer ? upgrades.getSelfSacrificeModifier() : upgrades.getSacrificeModifier())));
|
||||
|
||||
SacrificeEvent event = isPlayer ? new SacrificeEvent.SelfSacrifice(living, baseAmount, modifiedAmount) : new SacrificeEvent(living, baseAmount, modifiedAmount);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
modifiedAmount = event.getModifiedAmount();
|
||||
|
||||
int filled = altar.getTank().fill(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, modifiedAmount), true);
|
||||
if (filled != 0)
|
||||
altar.markDirty();
|
||||
|
||||
return new BooleanResult<>(filled, true);
|
||||
}
|
||||
|
||||
public static BooleanResult<Integer> handleSacrifice(EntityLivingBase living) {
|
||||
boolean isPlayer = living instanceof EntityPlayer;
|
||||
int baseAmount = isPlayer ? 200 : BloodMagicAPI.INSTANCE.getValueManager().getSacrificial().getOrDefault(EntityList.getKey(living), 200);
|
||||
return handleSacrifice(living, baseAmount);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static AltarTier getTier(World world, BlockPos pos) {
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
if (!(tile instanceof TileBloodAltar))
|
||||
return AltarTier.ONE;
|
||||
|
||||
AltarTier lastCheck = AltarTier.ONE;
|
||||
for (AltarTier tier : AltarTier.VALUES) {
|
||||
for (AltarComponent component : tier.getComponents()) {
|
||||
List<IBlockState> validStates = BloodMagicAPI.INSTANCE.getComponentStates(component.getType());
|
||||
IBlockState worldState = world.getBlockState(pos.add(component.getOffset()));
|
||||
if (component.getType() == ComponentType.NOT_AIR && worldState.getMaterial() != Material.AIR)
|
||||
continue;
|
||||
|
||||
if (!validStates.contains(worldState))
|
||||
return lastCheck;
|
||||
}
|
||||
|
||||
lastCheck = tier;
|
||||
}
|
||||
|
||||
return lastCheck;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static AltarUpgrades getUpgrades(World world, BlockPos pos, AltarTier currentTier) {
|
||||
AltarUpgrades upgrades = new AltarUpgrades();
|
||||
|
||||
for (AltarTier tier : AltarTier.VALUES) {
|
||||
if (tier.ordinal() > currentTier.ordinal())
|
||||
break;
|
||||
|
||||
for (AltarComponent component : tier.getComponents()) {
|
||||
if (!component.isUpgradeSlot() || component.getType() != ComponentType.BLOOD_RUNE)
|
||||
continue;
|
||||
|
||||
IBlockState state = world.getBlockState(pos.add(component.getOffset()));
|
||||
if (state.getBlock() instanceof BlockBloodRune)
|
||||
upgrades.upgrade(((BlockBloodRune) state.getBlock()).getRune());
|
||||
}
|
||||
}
|
||||
|
||||
return upgrades;
|
||||
}
|
||||
|
||||
// FIXME - This does not search properly. It may provide an altar that isn't the closest
|
||||
@Nullable
|
||||
public static TileBloodAltar findNearestAltar(World world, BlockPos pos, int searchRadius) {
|
||||
BlockPos.MutableBlockPos offsetPos = new BlockPos.MutableBlockPos(pos);
|
||||
for (int x = -searchRadius; x < searchRadius; x++) {
|
||||
for (int y = -searchRadius; y < searchRadius; y++) {
|
||||
for (int z = -searchRadius; z < searchRadius; z++) {
|
||||
TileEntity tile = world.getTileEntity(offsetPos.setPos(pos.getX() + x, pos.getY() + y, pos.getZ() + z));
|
||||
if (tile instanceof TileBloodAltar)
|
||||
return (TileBloodAltar) tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void constructAltar(World world, BlockPos altarPos, AltarTier buildTo) {
|
||||
BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
|
||||
for (AltarTier tier : AltarTier.VALUES) {
|
||||
if (tier.ordinal() > buildTo.ordinal())
|
||||
return;
|
||||
|
||||
for (AltarComponent component : tier.getComponents()) {
|
||||
mutablePos.setPos(altarPos.getX() + component.getOffset().getX(), altarPos.getY() + component.getOffset().getY(), altarPos.getZ() + component.getOffset().getZ());
|
||||
world.setBlockState(mutablePos, COMPONENT_DEFAULT_STATES.get(component.getType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void destroyAltar(World world, BlockPos altarPos) {
|
||||
BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
|
||||
for (AltarTier tier : AltarTier.VALUES) {
|
||||
for (AltarComponent component : tier.getComponents()) {
|
||||
mutablePos.setPos(altarPos.getX() + component.getOffset().getX(), altarPos.getY() + component.getOffset().getY(), altarPos.getZ() + component.getOffset().getZ());
|
||||
world.setBlockToAir(mutablePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.wayoftime.bloodmagic.core.altar;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IAltarManipulator {
|
||||
|
||||
default boolean tryManipulate(EntityPlayer player, ItemStack stack, World world, BlockPos pos) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.wayoftime.bloodmagic.core.handler;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import com.wayoftime.bloodmagic.core.network.BloodOrb;
|
||||
import com.wayoftime.bloodmagic.core.network.IBloodOrb;
|
||||
import com.wayoftime.bloodmagic.core.network.SoulNetwork;
|
||||
import com.wayoftime.bloodmagic.event.BindingEvent;
|
||||
import com.wayoftime.bloodmagic.item.IBindable;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = BloodMagic.MODID)
|
||||
public class GenericEventHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onItemUse(PlayerInteractEvent.RightClickItem event) {
|
||||
if (event.getWorld().isRemote)
|
||||
return;
|
||||
|
||||
EntityPlayer player = event.getEntityPlayer();
|
||||
ItemStack clicked = event.getItemStack();
|
||||
if (player instanceof FakePlayer)
|
||||
return;
|
||||
|
||||
if (clicked.getItem() instanceof IBindable) {
|
||||
IBindable bindable = (IBindable) clicked.getItem();
|
||||
Binding binding = bindable.getBinding(clicked);
|
||||
if (binding == null && bindable.onBind(player, clicked)) {
|
||||
binding = new Binding(player);
|
||||
BindingEvent bindingEvent = new BindingEvent(clicked, binding, player);
|
||||
if (!MinecraftForge.EVENT_BUS.post(bindingEvent))
|
||||
IBindable.applyBinding(clicked, binding);
|
||||
}
|
||||
}
|
||||
|
||||
if (clicked.getItem() instanceof IBloodOrb) {
|
||||
BloodOrb orb = ((IBloodOrb) clicked.getItem()).getOrb(clicked);
|
||||
if (orb == null)
|
||||
return;
|
||||
|
||||
SoulNetwork network = SoulNetwork.get(player.getGameProfile().getId());
|
||||
if (orb.getTier() > network.getTier())
|
||||
network.setTier(orb.getTier(), orb.getCapacity());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.wayoftime.bloodmagic.core.living;
|
||||
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public interface ILivingContainer {
|
||||
|
||||
@Nullable
|
||||
default LivingStats getLivingStats(@Nonnull ItemStack stack) {
|
||||
if (!stack.hasTagCompound() || !stack.getTagCompound().hasKey("livingStats"))
|
||||
return null;
|
||||
|
||||
return LivingStats.fromNBT(stack.getTagCompound().getCompoundTag("livingStats"));
|
||||
}
|
||||
|
||||
default void updateLivingStates(@Nonnull ItemStack stack, @Nullable LivingStats stats) {
|
||||
if (stats == null) {
|
||||
if (stack.hasTagCompound())
|
||||
stack.getTagCompound().removeTag("livingStats");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stack.hasTagCompound())
|
||||
stack.setTagCompound(new NBTTagCompound());
|
||||
|
||||
stack.getTagCompound().setTag("livingStats", stats.serializeNBT());
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
static void appendLivingTooltip(LivingStats stats, List<String> tooltip, boolean trainable) {
|
||||
if (stats != null) {
|
||||
if (trainable)
|
||||
tooltip.add(I18n.format("tooltip.bloodmagic:living_points", stats.getUsedPoints(), stats.getMaxPoints()));
|
||||
|
||||
stats.getUpgrades().forEach((k, v) -> {
|
||||
if (k.getLevel(v) <= 0)
|
||||
return;
|
||||
|
||||
if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || k.getNextRequirement(v) == 0)
|
||||
tooltip.add(I18n.format(k.getUnlocalizedName()) + " " + I18n.format("enchantment.level." + k.getLevel(v)));
|
||||
else
|
||||
tooltip.add(I18n.format(k.getUnlocalizedName()) + ": " + v + "/" + k.getNextRequirement(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.wayoftime.bloodmagic.core.living;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraftforge.fml.common.eventhandler.Cancelable;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
|
||||
public class LivingEquipmentEvent extends Event {
|
||||
|
||||
private final EntityPlayer player;
|
||||
private final LivingStats stats;
|
||||
|
||||
public LivingEquipmentEvent(EntityPlayer player, LivingStats stats) {
|
||||
this.player = player;
|
||||
this.stats = stats;
|
||||
}
|
||||
|
||||
public EntityPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public LivingStats getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Cancelable
|
||||
public static class GainExperience extends LivingEquipmentEvent {
|
||||
|
||||
private final LivingUpgrade upgrade;
|
||||
private int experience;
|
||||
|
||||
public GainExperience(EntityPlayer player, LivingStats stats, LivingUpgrade upgrade, int experience) {
|
||||
super(player, stats);
|
||||
this.upgrade = upgrade;
|
||||
this.experience = experience;
|
||||
}
|
||||
|
||||
public LivingUpgrade getUpgrade() {
|
||||
return upgrade;
|
||||
}
|
||||
|
||||
public int getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
public void setExperience(int experience) {
|
||||
this.experience = experience;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LevelUp extends LivingEquipmentEvent {
|
||||
|
||||
private final LivingUpgrade upgrade;
|
||||
|
||||
public LevelUp(EntityPlayer player, LivingStats stats, LivingUpgrade upgrade) {
|
||||
super(player, stats);
|
||||
|
||||
this.upgrade = upgrade;
|
||||
}
|
||||
|
||||
public LivingUpgrade getUpgrade() {
|
||||
return upgrade;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package com.wayoftime.bloodmagic.core.living;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicLivingArmor;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
|
||||
public class LivingStats implements INBTSerializable<NBTTagCompound> {
|
||||
|
||||
public static final int DEFAULT_UPGRADE_POINTS = 100;
|
||||
|
||||
private final Map<LivingUpgrade, Integer> upgrades;
|
||||
private int maxPoints = DEFAULT_UPGRADE_POINTS;
|
||||
|
||||
public LivingStats(Map<LivingUpgrade, Integer> upgrades) {
|
||||
this.upgrades = upgrades;
|
||||
}
|
||||
|
||||
public LivingStats() {
|
||||
this(Maps.newHashMap());
|
||||
}
|
||||
|
||||
public Map<LivingUpgrade, Integer> getUpgrades() {
|
||||
return ImmutableMap.copyOf(upgrades);
|
||||
}
|
||||
|
||||
public LivingStats addExperience(ResourceLocation key, int experience) {
|
||||
LivingUpgrade upgrade = RegistrarBloodMagicLivingArmor.UPGRADES.get(key);
|
||||
int current = upgrades.getOrDefault(upgrade, 0);
|
||||
if (upgrade.getNextRequirement(current) == 0)
|
||||
return this;
|
||||
|
||||
upgrades.put(upgrade, current + experience);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getLevel(ResourceLocation key) {
|
||||
LivingUpgrade upgrade = RegistrarBloodMagicLivingArmor.UPGRADES.get(key);
|
||||
return upgrade.getLevel(upgrades.getOrDefault(upgrade, 0));
|
||||
}
|
||||
|
||||
public int getUsedPoints() {
|
||||
int total = 0;
|
||||
for (Map.Entry<LivingUpgrade, Integer> applied : upgrades.entrySet()) {
|
||||
int experience = applied.getValue();
|
||||
int level = applied.getKey().getLevel(experience);
|
||||
int cost = applied.getKey().getLevelCost(level);
|
||||
total += cost;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
public int getMaxPoints() {
|
||||
return maxPoints;
|
||||
}
|
||||
|
||||
public LivingStats setMaxPoints(int maxPoints) {
|
||||
this.maxPoints = maxPoints;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound serializeNBT() {
|
||||
NBTTagCompound compound = new NBTTagCompound();
|
||||
NBTTagList statList = new NBTTagList();
|
||||
upgrades.forEach((k, v) -> {
|
||||
NBTTagCompound upgrade = new NBTTagCompound();
|
||||
upgrade.setString("key", k.getKey().toString());
|
||||
upgrade.setInteger("exp", v);
|
||||
statList.appendTag(upgrade);
|
||||
});
|
||||
compound.setTag("upgrades", statList);
|
||||
|
||||
compound.setInteger("maxPoints", maxPoints);
|
||||
|
||||
return compound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(NBTTagCompound nbt) {
|
||||
NBTTagList statList = nbt.getTagList("upgrades", 10);
|
||||
|
||||
for (NBTBase base : statList) {
|
||||
if (!(base instanceof NBTTagCompound))
|
||||
continue;
|
||||
|
||||
LivingUpgrade upgrade = RegistrarBloodMagicLivingArmor.UPGRADES.get(new ResourceLocation(((NBTTagCompound) base).getString("key")));
|
||||
if (upgrade == null)
|
||||
continue;
|
||||
int experience = ((NBTTagCompound) base).getInteger("exp");
|
||||
upgrades.put(upgrade, experience);
|
||||
}
|
||||
|
||||
maxPoints = nbt.getInteger("maxPoints");
|
||||
}
|
||||
|
||||
public static LivingStats fromNBT(NBTTagCompound statTag) {
|
||||
LivingStats stats = new LivingStats();
|
||||
stats.deserializeNBT(statTag);
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static LivingStats fromPlayer(EntityPlayer player) {
|
||||
return fromPlayer(player, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static LivingStats fromPlayer(EntityPlayer player, boolean createNew) {
|
||||
if (!LivingUtil.hasFullSet(player))
|
||||
return null;
|
||||
|
||||
ItemStack chest = player.getItemStackFromSlot(EntityEquipmentSlot.CHEST);
|
||||
LivingStats stats = ((ILivingContainer) chest.getItem()).getLivingStats(chest);
|
||||
return stats == null && createNew ? new LivingStats() : stats;
|
||||
}
|
||||
|
||||
public static void toPlayer(EntityPlayer player, LivingStats stats) {
|
||||
if (!LivingUtil.hasFullSet(player))
|
||||
return;
|
||||
|
||||
ItemStack chest = player.getItemStackFromSlot(EntityEquipmentSlot.CHEST);
|
||||
((ILivingContainer) chest.getItem()).updateLivingStates(chest, stats);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.wayoftime.bloodmagic.core.living;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicLivingArmor;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = BloodMagic.MODID)
|
||||
public class LivingStatusWatcher {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onJump(LivingEvent.LivingJumpEvent event) {
|
||||
if (!(event.getEntity() instanceof EntityPlayer))
|
||||
return;
|
||||
|
||||
EntityPlayer player = (EntityPlayer) event.getEntity();
|
||||
LivingStats stats = LivingUtil.applyNewExperience(player, RegistrarBloodMagicLivingArmor.JUMP, 1);
|
||||
if (stats == null)
|
||||
return;
|
||||
|
||||
int level = stats.getLevel(RegistrarBloodMagicLivingArmor.JUMP.getKey());
|
||||
player.motionY += 0.05 * level;
|
||||
|
||||
if (level >= 3) {
|
||||
Vec3d lookVec = player.getLookVec();
|
||||
player.motionX += player.motionX == 0 ? 0 : lookVec.x * 0.07D * level;
|
||||
player.motionZ += player.motionZ == 0 ? 0 : lookVec.z * 0.07D * level;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package com.wayoftime.bloodmagic.core.living;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class LivingUpgrade {
|
||||
|
||||
private final ResourceLocation key;
|
||||
private final Set<ResourceLocation> incompatible;
|
||||
private final TreeMap<Integer, Integer> experienceToLevel;
|
||||
private final Map<Integer, Integer> levelToCost;
|
||||
private final boolean isNegative;
|
||||
private String unlocalizedName = null;
|
||||
private IAttributeProvider attributeProvider;
|
||||
private IArmorProvider armorProvider;
|
||||
|
||||
public LivingUpgrade(ResourceLocation key, Consumer<List<UpgradeLevel>> experienceMapper /* xp needed -> level */, boolean isNegative) {
|
||||
this.key = key;
|
||||
this.incompatible = Sets.newHashSet();
|
||||
this.experienceToLevel = Maps.newTreeMap();
|
||||
this.levelToCost = Maps.newHashMap();
|
||||
this.isNegative = isNegative;
|
||||
|
||||
List<UpgradeLevel> levels = Lists.newArrayList();
|
||||
experienceMapper.accept(levels);
|
||||
|
||||
for (int i = 0; i < levels.size(); i++) {
|
||||
UpgradeLevel level = levels.get(i);
|
||||
experienceToLevel.put(level.experienceNeeded, i + 1);
|
||||
levelToCost.put(i + 1, level.upgradeCost);
|
||||
}
|
||||
}
|
||||
|
||||
public LivingUpgrade(ResourceLocation key, Consumer<List<UpgradeLevel>> experienceMapper /* xp needed -> level */) {
|
||||
this(key, experienceMapper, false);
|
||||
}
|
||||
|
||||
public LivingUpgrade withAttributeProvider(IAttributeProvider attributeProvider) {
|
||||
this.attributeProvider = attributeProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IAttributeProvider getAttributeProvider() {
|
||||
return attributeProvider;
|
||||
}
|
||||
|
||||
public LivingUpgrade withArmorProvider(IArmorProvider armorProvider) {
|
||||
this.armorProvider = armorProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IArmorProvider getArmorProvider() {
|
||||
return armorProvider;
|
||||
}
|
||||
|
||||
public String getUnlocalizedName() {
|
||||
return unlocalizedName == null ? unlocalizedName = "upgrade." + key.getNamespace() + ":" + key.getPath() + ".name" : unlocalizedName;
|
||||
}
|
||||
|
||||
public boolean isNegative() {
|
||||
return isNegative;
|
||||
}
|
||||
|
||||
public boolean isCompatible(ResourceLocation otherUpgrade) {
|
||||
return !incompatible.contains(otherUpgrade);
|
||||
}
|
||||
|
||||
public LivingUpgrade addIncompatibility(ResourceLocation... otherKeys) {
|
||||
Collections.addAll(incompatible, otherKeys);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getLevel(int experience) {
|
||||
Map.Entry<Integer, Integer> floor = experienceToLevel.floorEntry(experience);
|
||||
return floor == null ? 0 : floor.getValue();
|
||||
}
|
||||
|
||||
public int getNextRequirement(int experience) {
|
||||
Integer ret = experienceToLevel.ceilingKey(experience + 1);
|
||||
return ret == null ? 0 : ret;
|
||||
}
|
||||
|
||||
public int getLevelCost(int level) {
|
||||
return levelToCost.getOrDefault(level, 0);
|
||||
}
|
||||
|
||||
public ResourceLocation getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return key.toString();
|
||||
}
|
||||
|
||||
public interface IAttributeProvider {
|
||||
void handleAttributes(LivingStats stats, Multimap<String, AttributeModifier> attributeMap, int level);
|
||||
}
|
||||
|
||||
public interface IArmorProvider {
|
||||
double getProtection(EntityPlayer player, DamageSource source, int level);
|
||||
}
|
||||
|
||||
public static class UpgradeLevel {
|
||||
private final int experienceNeeded;
|
||||
private final int upgradeCost;
|
||||
|
||||
public UpgradeLevel(int experienceNeeded, int upgradeCost) {
|
||||
this.experienceNeeded = experienceNeeded;
|
||||
this.upgradeCost = upgradeCost;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.wayoftime.bloodmagic.core.living;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class LivingUtil {
|
||||
|
||||
@Nullable
|
||||
public static LivingStats applyNewExperience(EntityPlayer player, LivingUpgrade upgrade, int experience) {
|
||||
LivingStats stats = LivingStats.fromPlayer(player, true);
|
||||
if (stats == null)
|
||||
return null;
|
||||
|
||||
LivingEquipmentEvent.GainExperience event = new LivingEquipmentEvent.GainExperience(player, stats, upgrade, experience);
|
||||
if (MinecraftForge.EVENT_BUS.post(event))
|
||||
return stats;
|
||||
|
||||
experience = event.getExperience();
|
||||
|
||||
int currentExperience = stats.getUpgrades().getOrDefault(upgrade, 0);
|
||||
int requiredForLevel = upgrade.getNextRequirement(currentExperience) - currentExperience;
|
||||
|
||||
// If we're going to level up from this, check points
|
||||
if (requiredForLevel <= experience) {
|
||||
int currentPoints = stats.getUsedPoints();
|
||||
// If we're already capped or somehow over the cap, we don't want to add experience
|
||||
if (currentPoints >= stats.getMaxPoints())
|
||||
return stats;
|
||||
|
||||
int nextPointCost = upgrade.getLevelCost(upgrade.getLevel(currentExperience) + 1);
|
||||
// If there's no more levels in this upgrade, we don't want to add experience
|
||||
if (nextPointCost == -1)
|
||||
return stats;
|
||||
|
||||
// If applying this new level will go over our cap, we don't want to add experience
|
||||
if (currentPoints + nextPointCost > stats.getMaxPoints())
|
||||
return stats;
|
||||
}
|
||||
|
||||
int newLevel = upgrade.getLevel(currentExperience + experience);
|
||||
if (upgrade.getLevel(currentExperience) != newLevel) {
|
||||
MinecraftForge.EVENT_BUS.post(new LivingEquipmentEvent.LevelUp(player, stats, upgrade));
|
||||
player.sendStatusMessage(new TextComponentTranslation("chat.bloodmagic:living_upgrade_level_increase", new TextComponentTranslation(upgrade.getUnlocalizedName()), newLevel), true);
|
||||
}
|
||||
|
||||
stats.addExperience(upgrade.getKey(), experience);
|
||||
LivingStats.toPlayer(player, stats);
|
||||
return stats;
|
||||
}
|
||||
|
||||
public static boolean hasFullSet(EntityPlayer player) {
|
||||
for (ItemStack stack : player.inventory.armorInventory)
|
||||
if (stack.isEmpty() || !(stack.getItem() instanceof ILivingContainer))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.wayoftime.bloodmagic.core.network;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Binding implements INBTSerializable<NBTTagCompound> {
|
||||
|
||||
private UUID uuid;
|
||||
private String name;
|
||||
|
||||
public Binding(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Binding(EntityPlayer player) {
|
||||
this(player.getGameProfile().getId(), player.getGameProfile().getName());
|
||||
}
|
||||
|
||||
private Binding() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound serializeNBT() {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setTag("id", NBTUtil.createUUIDTag(uuid));
|
||||
tag.setString("name", name);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(NBTTagCompound nbt) {
|
||||
this.uuid = NBTUtil.getUUIDFromTag(nbt.getCompoundTag("id"));
|
||||
this.name = nbt.getString("name");
|
||||
}
|
||||
|
||||
public UUID getOwnerId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public Binding setOwnerId(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getOwnerName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Binding setOwnerName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Binding fromStack(ItemStack stack) {
|
||||
if (!stack.hasTagCompound()) // Definitely hasn't been bound yet.
|
||||
return null;
|
||||
|
||||
NBTBase bindingTag = stack.getTagCompound().getTag("binding");
|
||||
if (bindingTag == null || bindingTag.getId() != 10 || bindingTag.isEmpty()) // Make sure it's both a tag compound and that it has actual data.
|
||||
return null;
|
||||
|
||||
Binding binding = new Binding();
|
||||
binding.deserializeNBT((NBTTagCompound) bindingTag);
|
||||
return binding;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.wayoftime.bloodmagic.core.network;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.util.OrbUtil;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
public class BloodOrb {
|
||||
|
||||
private final ResourceLocation name;
|
||||
private final int tier;
|
||||
private final int capacity;
|
||||
private final int fillRate;
|
||||
|
||||
public BloodOrb(ResourceLocation name, int tier, int capacity, int fillRate) {
|
||||
this.name = name;
|
||||
this.tier = tier;
|
||||
this.capacity = capacity;
|
||||
this.fillRate = fillRate;
|
||||
|
||||
OrbUtil.addOrb(this);
|
||||
}
|
||||
|
||||
public ResourceLocation getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getTier() {
|
||||
return tier;
|
||||
}
|
||||
|
||||
public int getCapacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public int getFillRate() {
|
||||
return fillRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("name", name)
|
||||
.append("tier", tier)
|
||||
.append("capacity", capacity)
|
||||
.append("fillRate", fillRate)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.wayoftime.bloodmagic.core.network;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface IBloodOrb {
|
||||
|
||||
@Nullable
|
||||
BloodOrb getOrb(@Nonnull ItemStack stack);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.wayoftime.bloodmagic.core.network;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class NetworkInteraction {
|
||||
|
||||
private static final ITextComponent EMPTY = new TextComponentString("");
|
||||
|
||||
private final ITextComponent description;
|
||||
private final int amount;
|
||||
private boolean syphon;
|
||||
|
||||
public NetworkInteraction(ITextComponent description, int amount) {
|
||||
this.description = description;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public NetworkInteraction(int amount) {
|
||||
this(EMPTY, amount);
|
||||
}
|
||||
|
||||
public boolean isSyphon() {
|
||||
return syphon || amount < 0;
|
||||
}
|
||||
|
||||
public ITextComponent getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public NetworkInteraction syphon() {
|
||||
this.syphon = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof NetworkInteraction)
|
||||
return ((NetworkInteraction) o).getDescription().equals(description);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return description.hashCode();
|
||||
}
|
||||
|
||||
public static NetworkInteraction asBlockInfo(World world, BlockPos pos, int amount) {
|
||||
return new NetworkInteraction(new TextComponentString("block|" + world.provider.getDimension() + "|" + pos.toLong()), amount);
|
||||
}
|
||||
|
||||
public static NetworkInteraction asItemInfo(ItemStack itemStack, World world, Entity entity, int amount) {
|
||||
return new NetworkInteraction(new TextComponentString("item|" + itemStack.getItem().getRegistryName() + "|" + world.provider.getDimension() + "|" + entity.getPersistentID()), amount);
|
||||
}
|
||||
|
||||
public static NetworkInteraction asItemInfo(ItemStack itemStack, World world, BlockPos pos, int amount) {
|
||||
return new NetworkInteraction(new TextComponentString("item|" + itemStack.getItem().getRegistryName() + "|" + world.provider.getDimension() + "|" + pos.toLong()), amount);
|
||||
}
|
||||
|
||||
public static NetworkInteraction asItemInfo(ItemStack itemStack, int amount) {
|
||||
return new NetworkInteraction(new TextComponentString("item|" + itemStack.getItem().getRegistryName()), amount);
|
||||
}
|
||||
|
||||
public static NetworkInteraction asCommandInfo(ICommandSender sender, String command, int amount) {
|
||||
return new NetworkInteraction(new TextComponentString("command|" + command + "|" + sender.getName()), amount);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.wayoftime.bloodmagic.core.network;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.storage.WorldSavedData;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SNSavedData extends WorldSavedData {
|
||||
|
||||
public static final String ID = "bloodmagic_soul_network_data";
|
||||
|
||||
private final Map<UUID, SoulNetwork> networks = Maps.newHashMap();
|
||||
|
||||
public SNSavedData(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public SNSavedData() {
|
||||
this(ID);
|
||||
}
|
||||
|
||||
public SoulNetwork getNetwork(EntityPlayer player) {
|
||||
return getNetwork(player.getGameProfile().getId());
|
||||
}
|
||||
|
||||
public SoulNetwork getNetwork(UUID uuid) {
|
||||
SoulNetwork network = networks.get(uuid);
|
||||
if (network == null) {
|
||||
networks.put(uuid, network = SoulNetwork.newEmpty(uuid).withParent(this));
|
||||
markDirty();
|
||||
}
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(NBTTagCompound nbt) {
|
||||
NBTTagList networks = nbt.getTagList("networks", 10);
|
||||
for (NBTBase tag : networks) {
|
||||
if (tag.getId() != 10) // Only compounds
|
||||
continue;
|
||||
|
||||
SoulNetwork network = SoulNetwork.fromNbt((NBTTagCompound) tag);
|
||||
network.withParent(this);
|
||||
this.networks.put(network.getOwnerId(), network);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
|
||||
NBTTagList networks = new NBTTagList();
|
||||
for (SoulNetwork network : this.networks.values())
|
||||
networks.appendTag(network.serializeNBT());
|
||||
|
||||
compound.setTag("networks", networks);
|
||||
return compound;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static SoulNetwork getSoulNetwork(UUID uuid) {
|
||||
World world = DimensionManager.getWorld(0);
|
||||
if (world == null || world.getMapStorage() == null)
|
||||
return new SNSavedData().getNetwork(uuid);
|
||||
|
||||
SNSavedData savedData = (SNSavedData) world.getMapStorage().getOrLoadData(SNSavedData.class, ID);
|
||||
if (savedData == null) {
|
||||
savedData = new SNSavedData();
|
||||
world.getMapStorage().setData(ID, savedData);
|
||||
}
|
||||
|
||||
return savedData.getNetwork(uuid);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
package com.wayoftime.bloodmagic.core.network;
|
||||
|
||||
import com.google.common.collect.EvictingQueue;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.util.BooleanResult;
|
||||
import com.wayoftime.bloodmagic.event.SoulNetworkEvent;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SoulNetwork implements INBTSerializable<NBTTagCompound> {
|
||||
|
||||
public static final DamageSource WEAK_SOUL = new DamageSource(BloodMagic.MODID + ":weak_soul").setDamageBypassesArmor().setDamageIsAbsolute().setMagicDamage();
|
||||
|
||||
private final Queue<NetworkInteraction> interactionHistory;
|
||||
private SNSavedData parent;
|
||||
private UUID ownerId;
|
||||
private int currentEssence;
|
||||
private int currentTier;
|
||||
private int maxForTier;
|
||||
|
||||
private SoulNetwork() {
|
||||
this.interactionHistory = EvictingQueue.create(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound serializeNBT() {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setString("owner", ownerId.toString());
|
||||
tag.setInteger("essence", currentEssence);
|
||||
tag.setInteger("tier", currentTier);
|
||||
tag.setInteger("maxForTier", maxForTier);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(NBTTagCompound nbt) {
|
||||
this.ownerId = UUID.fromString(nbt.getString("owner"));
|
||||
this.currentEssence = nbt.getInteger("essence");
|
||||
this.currentTier = nbt.getInteger("tier");
|
||||
this.maxForTier = nbt.getInteger("maxForTier");
|
||||
}
|
||||
|
||||
public SoulNetwork withParent(SNSavedData parent) {
|
||||
this.parent = parent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SNSavedData getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public UUID getOwnerId() {
|
||||
return ownerId;
|
||||
}
|
||||
|
||||
public BooleanResult<Integer> submitInteraction(NetworkInteraction interaction) {
|
||||
if (interaction.getAmount() == 0)
|
||||
return new BooleanResult<>(0, true);
|
||||
|
||||
if (!interaction.isSyphon()) {
|
||||
SoulNetworkEvent.Fill event = new SoulNetworkEvent.Fill(this, interaction, maxForTier);
|
||||
if (MinecraftForge.EVENT_BUS.post(event))
|
||||
return new BooleanResult<>(0, false);
|
||||
|
||||
if (currentEssence > event.getMaximum())
|
||||
return new BooleanResult<>(0, false);
|
||||
|
||||
int oldCurrent = currentEssence;
|
||||
currentEssence = Math.min(event.getMaximum(), currentEssence + event.getTicket().getAmount());
|
||||
markDirty();
|
||||
interactionHistory.remove(interaction); // Allows an existing interaction to be moved back up to the top with whatever new amount is changed
|
||||
interactionHistory.add(interaction);
|
||||
return new BooleanResult<>(currentEssence - oldCurrent, true);
|
||||
} else {
|
||||
SoulNetworkEvent.Syphon event = new SoulNetworkEvent.Syphon(this, interaction);
|
||||
if (MinecraftForge.EVENT_BUS.post(event))
|
||||
return new BooleanResult<>(0, false);
|
||||
|
||||
int newEssence = currentEssence - event.getTicket().getAmount();
|
||||
if (newEssence < 0) {
|
||||
currentEssence = 0;
|
||||
markDirty();
|
||||
return new BooleanResult<>(currentEssence, false);
|
||||
}
|
||||
|
||||
currentEssence -= event.getTicket().getAmount();
|
||||
markDirty();
|
||||
interactionHistory.remove(interaction);
|
||||
interactionHistory.add(interaction);
|
||||
return new BooleanResult<>(event.getTicket().getAmount(), true);
|
||||
}
|
||||
}
|
||||
|
||||
public int getEssence() {
|
||||
return currentEssence;
|
||||
}
|
||||
|
||||
public SoulNetwork setEssence(int essence) {
|
||||
this.currentEssence = Math.min(this.maxForTier, essence);
|
||||
markDirty();
|
||||
return this;
|
||||
}
|
||||
|
||||
public SoulNetwork setTier(int newTier, int maxForTier) {
|
||||
this.currentTier = newTier;
|
||||
this.maxForTier = maxForTier;
|
||||
markDirty();
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getTier() {
|
||||
return currentTier;
|
||||
}
|
||||
|
||||
public void markDirty() {
|
||||
if (parent != null)
|
||||
parent.markDirty();
|
||||
}
|
||||
|
||||
public static SoulNetwork get(UUID uuid) {
|
||||
return SNSavedData.getSoulNetwork(uuid);
|
||||
}
|
||||
|
||||
public static SoulNetwork newEmpty(UUID uuid) {
|
||||
SoulNetwork network = new SoulNetwork();
|
||||
network.ownerId = uuid;
|
||||
return network;
|
||||
}
|
||||
|
||||
public static SoulNetwork fromNbt(NBTTagCompound tag) {
|
||||
SoulNetwork network = new SoulNetwork();
|
||||
network.deserializeNBT(tag);
|
||||
return network;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.wayoftime.bloodmagic.core.recipe;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.core.network.BloodOrb;
|
||||
import com.wayoftime.bloodmagic.core.network.IBloodOrb;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntComparators;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.minecraft.client.util.RecipeItemHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class IngredientBloodOrb extends Ingredient {
|
||||
|
||||
private final BloodOrb orb;
|
||||
private NonNullList<ItemStack> orbs;
|
||||
private IntList itemIds = null;
|
||||
private ItemStack[] items;
|
||||
|
||||
public IngredientBloodOrb(BloodOrb orb) {
|
||||
super();
|
||||
|
||||
this.orb = orb;
|
||||
|
||||
// List<ItemStack> orbGet = OrbRegistry.getOrbsDownToTier(orb.getTier());
|
||||
List<ItemStack> orbGet = Lists.newArrayList();
|
||||
orbs = NonNullList.withSize(orbGet.size(), ItemStack.EMPTY);
|
||||
|
||||
for (int i = 0; i < orbGet.size(); i++)
|
||||
orbs.set(i, orbGet.get(i));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public ItemStack[] getMatchingStacks() {
|
||||
if (items == null)
|
||||
items = orbs.toArray(new ItemStack[0]);
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
@SideOnly(Side.CLIENT)
|
||||
public IntList getValidItemStacksPacked() {
|
||||
if (this.itemIds == null || itemIds.size() != orbs.size()) {
|
||||
this.itemIds = new IntArrayList(orbs.size());
|
||||
|
||||
for (ItemStack itemstack : orbs)
|
||||
this.itemIds.add(RecipeItemHelper.pack(itemstack));
|
||||
|
||||
this.itemIds.sort(IntComparators.NATURAL_COMPARATOR);
|
||||
}
|
||||
|
||||
return this.itemIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(@Nullable ItemStack input) {
|
||||
if (input == null || input.isEmpty())
|
||||
return false;
|
||||
|
||||
if (!input.hasTagCompound())
|
||||
return false;
|
||||
|
||||
if (!(input.getItem() instanceof IBloodOrb))
|
||||
return false;
|
||||
|
||||
BloodOrb orb = ((IBloodOrb) input.getItem()).getOrb(input);
|
||||
return orb != null && orb.getTier() >= this.orb.getTier();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidate() {
|
||||
this.itemIds = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.wayoftime.bloodmagic.core.recipe;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.crafting.IIngredientFactory;
|
||||
import net.minecraftforge.common.crafting.JsonContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class IngredientBloodOrbFactory implements IIngredientFactory {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Ingredient parse(JsonContext context, JsonObject json) {
|
||||
ResourceLocation orb = new ResourceLocation(JsonUtils.getString(json, "orb"));
|
||||
// return new IngredientBloodOrb(RegistrarBloodMagic.BLOOD_ORBS.getValue(orb));
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.wayoftime.bloodmagic.core.type;
|
||||
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum BloodRunes implements IStringSerializable {
|
||||
|
||||
BLANK,
|
||||
SPEED,
|
||||
EFFICIENCY,
|
||||
SACRIFICE,
|
||||
SELF_SACRIFICE,
|
||||
DISPLACEMENT,
|
||||
CAPACITY,
|
||||
AUGMENTED_CAPACITY,
|
||||
ORB,
|
||||
ACCELERATION,
|
||||
CHARGING,
|
||||
;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.wayoftime.bloodmagic.core.type;
|
||||
|
||||
public enum ComponentType {
|
||||
|
||||
GLOWSTONE,
|
||||
BLOODSTONE,
|
||||
BEACON,
|
||||
BLOOD_RUNE,
|
||||
CRYSTAL,
|
||||
NOT_AIR,
|
||||
;
|
||||
|
||||
public static final ComponentType[] VALUES = values();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.wayoftime.bloodmagic.core.type;
|
||||
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum DemonWillType implements IStringSerializable {
|
||||
|
||||
RAW,
|
||||
CORROSIVE,
|
||||
DESTRUCTIVE,
|
||||
VENGEFUL,
|
||||
STEADFAST,
|
||||
;
|
||||
|
||||
public static final DemonWillType[] VALUES = values();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.wayoftime.bloodmagic.core.type;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum SlateType {
|
||||
|
||||
BLANK,
|
||||
REINFORCED,
|
||||
IMBUED,
|
||||
DEMONIC,
|
||||
ETHEREAL,
|
||||
;
|
||||
|
||||
private final String name;
|
||||
|
||||
SlateType() {
|
||||
this.name = name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
61
src/main/java/com/wayoftime/bloodmagic/core/util/BMLog.java
Normal file
61
src/main/java/com/wayoftime/bloodmagic/core/util/BMLog.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
package com.wayoftime.bloodmagic.core.util;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.BloodMagicConfiguration;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public enum BMLog {
|
||||
|
||||
DEFAULT("Blood Magic") {
|
||||
@Override
|
||||
boolean enabled() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
DEBUG() {
|
||||
@Override
|
||||
boolean enabled() {
|
||||
return BloodMagicConfiguration.logging.enableDebugLogging;
|
||||
}
|
||||
},
|
||||
API() {
|
||||
@Override
|
||||
boolean enabled() {
|
||||
return BloodMagicConfiguration.logging.enableApiLogging;
|
||||
}
|
||||
},
|
||||
API_VERBOSE() {
|
||||
@Override
|
||||
boolean enabled() {
|
||||
return BloodMagicConfiguration.logging.enableVerboseApiLogging;
|
||||
}
|
||||
};
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
BMLog(String logName) {
|
||||
logger = LogManager.getLogger(logName);
|
||||
}
|
||||
|
||||
BMLog() {
|
||||
logger = LogManager.getLogger("Blood Magic|" + WordUtils.capitalizeFully(name().replace("_", " ")));
|
||||
}
|
||||
|
||||
abstract boolean enabled();
|
||||
|
||||
public void info(String input, Object... args) {
|
||||
if (enabled())
|
||||
logger.info(input, args);
|
||||
}
|
||||
|
||||
public void error(String input, Object... args) {
|
||||
if (enabled())
|
||||
logger.error(input, args);
|
||||
}
|
||||
|
||||
public void warn(String input, Object... args) {
|
||||
if (enabled())
|
||||
logger.warn(input, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.wayoftime.bloodmagic.core.util;
|
||||
|
||||
public class BooleanResult<T> {
|
||||
|
||||
private final T value;
|
||||
private final boolean success;
|
||||
|
||||
public BooleanResult(T value, boolean success) {
|
||||
this.value = value;
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
}
|
102
src/main/java/com/wayoftime/bloodmagic/core/util/JsonUtil.java
Normal file
102
src/main/java/com/wayoftime/bloodmagic/core/util/JsonUtil.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
package com.wayoftime.bloodmagic.core.util;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
|
||||
/**
|
||||
* A simple utility for reading and writing JSON files. To handle custom (de)serialization, use
|
||||
* {@link com.google.gson.annotations.JsonAdapter} on your types.
|
||||
*/
|
||||
public class JsonUtil {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().create();
|
||||
|
||||
/**
|
||||
* Reads a {@link T} back from the given file. If the file does not exist, a new file will be generated with the
|
||||
* provided default and the default will be returned.
|
||||
*
|
||||
* @param token The token type to use for deserialization.
|
||||
* @param file The file to read the JSON from.
|
||||
* @param def The default value to use if the file does not exist.
|
||||
* @param <T> The object type to give back.
|
||||
* @return a {@link T} that was read from the given file or {@code def} if the file did not exist.
|
||||
*/
|
||||
@Nonnull
|
||||
public static <T> T fromJson(@Nonnull TypeToken<T> token, @Nonnull File file, @Nonnull T def) {
|
||||
T ret = fromJson(token, file);
|
||||
if (ret == null) {
|
||||
toJson(def, token, file);
|
||||
ret = def;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a {@link T} back from the given file. If the file does not exist, {@code null} is returned. If an exception
|
||||
* is thrown during deserialization, {@code null} is also returned.
|
||||
*
|
||||
* @param token The token type to use for deserialization.
|
||||
* @param file - The file to read the JSON from.
|
||||
* @param <T> The object type to give back.
|
||||
* @return a {@link T} that was read from the given file, {@code null} if the file does not exist, or {@code null} if
|
||||
* an exception was thrown.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T fromJson(@Nonnull TypeToken<T> token, @Nonnull File file) {
|
||||
if (!file.exists())
|
||||
return null;
|
||||
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
return GSON.fromJson(reader, token.getType());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T fromJson(@Nonnull TypeToken<T> token, @Nonnull String json) {
|
||||
return GSON.fromJson(json, token.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link T} to JSON and writes it to file. If the file does not exist, a new one is created. If the file
|
||||
* does exist, the contents are overwritten with the new value.
|
||||
*
|
||||
* @param type The object to write to JSON.
|
||||
* @param token The token type to use for serialization.
|
||||
* @param file The file to write the JSON to.
|
||||
* @param <T> The object type to write.
|
||||
*/
|
||||
public static <T> void toJson(@Nonnull T type, @Nonnull TypeToken<T> token, @Nonnull File file) {
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
FileUtils.forceMkdirParent(file);
|
||||
file.createNewFile();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
writer.write(getJson(type, token));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> String getJson(@Nonnull T type, @Nonnull TypeToken<T> token) {
|
||||
return GSON.toJson(type, token.getType());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.wayoftime.bloodmagic.core.util;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.core.network.BloodOrb;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OrbUtil {
|
||||
|
||||
public static final List<BloodOrb> ORBS = Lists.newArrayList();
|
||||
public static final ArrayListMultimap<Integer, BloodOrb> TIERED = ArrayListMultimap.create();
|
||||
|
||||
public static void addOrb(BloodOrb orb) {
|
||||
ORBS.add(orb);
|
||||
|
||||
TIERED.put(orb.getTier(), orb);
|
||||
}
|
||||
|
||||
// TODO :LUL: This needs to be implemented before orb-related recipes can be added.
|
||||
public static List<BloodOrb> getOrbsMatching(int tier) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
}
|
137
src/main/java/com/wayoftime/bloodmagic/core/util/PluginUtil.java
Normal file
137
src/main/java/com/wayoftime/bloodmagic/core/util/PluginUtil.java
Normal file
|
@ -0,0 +1,137 @@
|
|||
package com.wayoftime.bloodmagic.core.util;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.api.BloodMagicPlugin;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicAPI;
|
||||
import com.wayoftime.bloodmagic.api.IBloodMagicPlugin;
|
||||
import com.wayoftime.bloodmagic.api.impl.BloodMagicAPI;
|
||||
import com.wayoftime.bloodmagic.api.impl.BloodMagicCorePlugin;
|
||||
import net.minecraftforge.common.util.EnumHelper;
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PluginUtil {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nonnull
|
||||
public static List<Pair<IBloodMagicPlugin, BloodMagicPlugin>> gatherPlugins(ASMDataTable dataTable) {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
List<Pair<IBloodMagicPlugin, BloodMagicPlugin>> discoveredAnnotations = Lists.newArrayList();
|
||||
Set<ASMDataTable.ASMData> discoveredPlugins = dataTable.getAll(BloodMagicPlugin.class.getName());
|
||||
|
||||
for (ASMDataTable.ASMData data : discoveredPlugins) {
|
||||
try {
|
||||
Class<?> asmClass = Class.forName(data.getClassName());
|
||||
Class<? extends IBloodMagicPlugin> pluginClass = asmClass.asSubclass(IBloodMagicPlugin.class);
|
||||
|
||||
IBloodMagicPlugin instance = pluginClass.newInstance();
|
||||
|
||||
BMLog.API.info("Discovered plugin at {}", data.getClassName());
|
||||
discoveredAnnotations.add(Pair.of(instance, pluginClass.getAnnotation(BloodMagicPlugin.class)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Bring core plugin up to top
|
||||
discoveredAnnotations.sort((o1, o2) -> {
|
||||
if (o1.getLeft().getClass() == BloodMagicCorePlugin.class)
|
||||
return -1;
|
||||
|
||||
return o1.getClass().getCanonicalName().compareToIgnoreCase(o2.getClass().getCanonicalName());
|
||||
});
|
||||
BMLog.API.info("Discovered {} potential plugin(s) in {}", discoveredAnnotations.size(), stopwatch.stop());
|
||||
return discoveredAnnotations;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static List<Field> gatherInjections(ASMDataTable dataTable) {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
List<Field> injectees = Lists.newArrayList();
|
||||
Set<ASMDataTable.ASMData> discoveredInjectees = dataTable.getAll(BloodMagicPlugin.Inject.class.getName());
|
||||
|
||||
for (ASMDataTable.ASMData data : discoveredInjectees) {
|
||||
try {
|
||||
Class<?> asmClass = Class.forName(data.getClassName());
|
||||
Field toInject = asmClass.getDeclaredField(data.getObjectName());
|
||||
if (toInject.getType() != IBloodMagicAPI.class) {
|
||||
BMLog.API.error("Mod requested API injection on field {}.{} which is an invalid type.", data.getClassName(), data.getObjectName());
|
||||
continue;
|
||||
}
|
||||
|
||||
BMLog.API.info("Discovered injection request at {}.{}", data.getClassName(), data.getObjectName());
|
||||
injectees.add(toInject);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
BMLog.API.info("Discovered {} potential API injection(s) in {}", injectees.size(), stopwatch.stop());
|
||||
return injectees;
|
||||
}
|
||||
|
||||
public static void handlePluginStep(RegistrationStep step) {
|
||||
Stopwatch total = Stopwatch.createStarted();
|
||||
int errors = 0;
|
||||
for (Pair<IBloodMagicPlugin, BloodMagicPlugin> plugin : BloodMagic.PLUGINS) {
|
||||
Stopwatch per = Stopwatch.createStarted();
|
||||
try {
|
||||
step.getConsumer().accept(plugin);
|
||||
} catch (Exception e) {
|
||||
errors++;
|
||||
BMLog.DEFAULT.error("Error handling plugin step {} at {}: {}: {}", step, plugin.getLeft().getClass(), e.getClass().getSimpleName(), e.getMessage());
|
||||
}
|
||||
BMLog.API.info("Handled plugin step {} at {} in {}", step, plugin.getLeft().getClass(), per.stop());
|
||||
}
|
||||
|
||||
BMLog.API.info("Handled {} plugin(s) at step {} with {} errors in {}", BloodMagic.PLUGINS.size() - errors, step, errors, total.stop());
|
||||
}
|
||||
|
||||
public static void injectAPIInstances(List<Field> injectees) {
|
||||
Stopwatch total = Stopwatch.createStarted();
|
||||
int errors = 0;
|
||||
|
||||
for (Field injectee : injectees) {
|
||||
Stopwatch per = Stopwatch.createStarted();
|
||||
if (!Modifier.isStatic(injectee.getModifiers()))
|
||||
continue;
|
||||
|
||||
try {
|
||||
EnumHelper.setFailsafeFieldValue(injectee, null, BloodMagicAPI.INSTANCE);
|
||||
} catch (Exception e) {
|
||||
errors++;
|
||||
BMLog.DEFAULT.error("Error injecting API instance at {}.{}", injectee.getDeclaringClass().getCanonicalName(), injectee.getName());
|
||||
}
|
||||
BMLog.API.info("Injected API instance at {}.{} in {}", injectee.getDeclaringClass().getCanonicalName(), injectee.getName(), per.stop());
|
||||
}
|
||||
|
||||
BMLog.API.info("Injected API {} times with {} errors in {}", injectees.size() - errors, errors, total.stop());
|
||||
}
|
||||
|
||||
public enum RegistrationStep {
|
||||
|
||||
PLUGIN_REGISTER(p -> p.getLeft().register(BloodMagicAPI.INSTANCE)),
|
||||
RECIPE_REGISTER(p -> p.getLeft().registerRecipes(BloodMagicAPI.INSTANCE.getRecipeRegistrar()))
|
||||
;
|
||||
|
||||
private final Consumer<Pair<IBloodMagicPlugin, BloodMagicPlugin>> consumer;
|
||||
|
||||
RegistrationStep(Consumer<Pair<IBloodMagicPlugin, BloodMagicPlugin>> consumer) {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Consumer<Pair<IBloodMagicPlugin, BloodMagicPlugin>> getConsumer() {
|
||||
return consumer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.wayoftime.bloodmagic.core.util;
|
||||
|
||||
import net.minecraftforge.common.util.EnumHelper;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public final class RegistryAddCallbackWrapper<T extends IForgeRegistryEntry<T>> {
|
||||
|
||||
private static final Field CALLBACK_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
CALLBACK_FIELD = ForgeRegistry.class.getDeclaredField("add");
|
||||
CALLBACK_FIELD.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException("Could not find AddCallback field.");
|
||||
}
|
||||
}
|
||||
|
||||
private final Class<T> registryType;
|
||||
private final BiConsumer<T, T> addCheck;
|
||||
private final Runnable postCallback;
|
||||
|
||||
public RegistryAddCallbackWrapper(@Nonnull Class<T> registryType, @Nonnull BiConsumer<T, T> addCheck, @Nonnull Runnable postCallback) {
|
||||
this.registryType = registryType;
|
||||
this.addCheck = addCheck;
|
||||
this.postCallback = postCallback;
|
||||
}
|
||||
|
||||
public void wrapParent() throws Exception {
|
||||
ForgeRegistry<T> registry = (ForgeRegistry<T>) GameRegistry.findRegistry(registryType);
|
||||
//noinspection unchecked
|
||||
IForgeRegistry.AddCallback<T> oldCallback = (IForgeRegistry.AddCallback<T>) CALLBACK_FIELD.get(registry);
|
||||
EnumHelper.setFailsafeFieldValue(CALLBACK_FIELD, registry, (IForgeRegistry.AddCallback<T>) (owner, stage, id, obj, oldObj) -> {
|
||||
oldCallback.onAdd(owner, stage, id, obj, oldObj);
|
||||
addCheck.accept(obj, oldObj);
|
||||
});
|
||||
BMLog.DEBUG.info("Wrapped add callback for {} registry.", registry.getRegistrySuperType().getSimpleName());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Runnable getPostCallback() {
|
||||
return postCallback;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.wayoftime.bloodmagic.core.util.register;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface IItemProvider {
|
||||
|
||||
@Nullable
|
||||
default Item getItem() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.wayoftime.bloodmagic.core.util.register;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
|
||||
public interface IVariantProvider {
|
||||
|
||||
/**
|
||||
* A mapping of meta -> state variant
|
||||
*
|
||||
* @param variants A map to populate with all variants
|
||||
*/
|
||||
default void collectVariants(Int2ObjectMap<String> variants) {
|
||||
variants.put(0, "inventory");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.wayoftime.bloodmagic.event;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fml.common.eventhandler.Cancelable;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
|
||||
@Cancelable
|
||||
public class BindingEvent extends Event {
|
||||
|
||||
private final ItemStack stack;
|
||||
private final Binding binding;
|
||||
private final EntityPlayer player;
|
||||
|
||||
public BindingEvent(ItemStack stack, Binding binding, EntityPlayer player) {
|
||||
this.stack = stack;
|
||||
this.binding = binding;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public ItemStack getStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public Binding getBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
public EntityPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.wayoftime.bloodmagic.event;
|
||||
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
|
||||
public class SacrificeEvent extends Event {
|
||||
|
||||
protected final EntityLivingBase sacrificed;
|
||||
private final int baseAmount;
|
||||
private int modifiedAmount;
|
||||
|
||||
public SacrificeEvent(EntityLivingBase sacrificed, int baseAmount, int modifiedAmount) {
|
||||
this.sacrificed = sacrificed;
|
||||
this.baseAmount = baseAmount;
|
||||
this.modifiedAmount = modifiedAmount;
|
||||
}
|
||||
|
||||
public EntityLivingBase getSacrificed() {
|
||||
return sacrificed;
|
||||
}
|
||||
|
||||
public int getBaseAmount() {
|
||||
return baseAmount;
|
||||
}
|
||||
|
||||
public int getModifiedAmount() {
|
||||
return modifiedAmount;
|
||||
}
|
||||
|
||||
public void setModifiedAmount(int modifiedAmount) {
|
||||
this.modifiedAmount = modifiedAmount;
|
||||
}
|
||||
|
||||
public static class SelfSacrifice extends SacrificeEvent {
|
||||
|
||||
public SelfSacrifice(EntityLivingBase sacrificed, int baseAmount, int modifiedAmount) {
|
||||
super(sacrificed, baseAmount, modifiedAmount);
|
||||
}
|
||||
|
||||
public EntityPlayer getPlayer() {
|
||||
return (EntityPlayer) sacrificed;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package com.wayoftime.bloodmagic.event;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.SoulNetwork;
|
||||
import com.wayoftime.bloodmagic.core.network.NetworkInteraction;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fml.common.eventhandler.Cancelable;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
|
||||
public class SoulNetworkEvent extends Event {
|
||||
|
||||
private final SoulNetwork network;
|
||||
private NetworkInteraction ticket;
|
||||
|
||||
public SoulNetworkEvent(SoulNetwork network, NetworkInteraction ticket) {
|
||||
this.network = network;
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public SoulNetwork getNetwork() {
|
||||
return network;
|
||||
}
|
||||
|
||||
public NetworkInteraction getTicket() {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(NetworkInteraction ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
@Cancelable
|
||||
public static class Syphon extends SoulNetworkEvent {
|
||||
|
||||
private boolean shouldDamage;
|
||||
|
||||
public Syphon(SoulNetwork network, NetworkInteraction ticket) {
|
||||
super(network, ticket);
|
||||
}
|
||||
|
||||
public boolean shouldDamage() {
|
||||
return shouldDamage;
|
||||
}
|
||||
|
||||
public void setShouldDamage(boolean shouldDamage) {
|
||||
this.shouldDamage = shouldDamage;
|
||||
}
|
||||
|
||||
public static class Item extends Syphon {
|
||||
|
||||
private final ItemStack stack;
|
||||
|
||||
public Item(SoulNetwork network, NetworkInteraction ticket, ItemStack stack) {
|
||||
super(network, ticket);
|
||||
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public ItemStack getStack() {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
public static class User extends Syphon {
|
||||
|
||||
private final EntityPlayer user;
|
||||
|
||||
public User(SoulNetwork network, NetworkInteraction ticket, EntityPlayer user) {
|
||||
super(network, ticket);
|
||||
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public EntityPlayer getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Cancelable
|
||||
public static class Fill extends SoulNetworkEvent {
|
||||
|
||||
private int maximum;
|
||||
|
||||
public Fill(SoulNetwork network, NetworkInteraction ticket, int maximum) {
|
||||
super(network, ticket);
|
||||
|
||||
this.maximum = maximum;
|
||||
}
|
||||
|
||||
public int getMaximum() {
|
||||
return maximum;
|
||||
}
|
||||
|
||||
public void setMaximum(int maximum) {
|
||||
this.maximum = maximum;
|
||||
}
|
||||
}
|
||||
}
|
36
src/main/java/com/wayoftime/bloodmagic/guide/Category.java
Normal file
36
src/main/java/com/wayoftime/bloodmagic/guide/Category.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
package com.wayoftime.bloodmagic.guide;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Category {
|
||||
|
||||
private final Guide owner;
|
||||
private final String name;
|
||||
private final Map<String, Entry> entries;
|
||||
|
||||
public Category(Guide owner, String name, Consumer<Category> $) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
entries = Maps.newLinkedHashMap();
|
||||
|
||||
$.accept(this);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void draw(Minecraft minecraft, ScaledResolution resolution, FontRenderer font) {
|
||||
|
||||
}
|
||||
|
||||
public Entry addEntry(Entry entry) {
|
||||
entries.put(entry.getId(), entry);
|
||||
return entry;
|
||||
}
|
||||
}
|
29
src/main/java/com/wayoftime/bloodmagic/guide/Entry.java
Normal file
29
src/main/java/com/wayoftime/bloodmagic/guide/Entry.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
package com.wayoftime.bloodmagic.guide;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.guide.page.PageComponent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Entry {
|
||||
|
||||
private final String id;
|
||||
private final List<PageComponent> components;
|
||||
|
||||
public Entry(String id, Consumer<Entry> $) {
|
||||
this.id = id;
|
||||
this.components = Lists.newArrayList();
|
||||
|
||||
$.accept(this);
|
||||
}
|
||||
|
||||
public PageComponent appendComponent(PageComponent component) {
|
||||
components.add(component);
|
||||
return component;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
34
src/main/java/com/wayoftime/bloodmagic/guide/Guide.java
Normal file
34
src/main/java/com/wayoftime/bloodmagic/guide/Guide.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
package com.wayoftime.bloodmagic.guide;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Guide {
|
||||
|
||||
private final ResourceLocation id;
|
||||
private final List<Category> categories;
|
||||
|
||||
public Guide(ResourceLocation id, Consumer<Guide> $) {
|
||||
this.id = id;
|
||||
this.categories = Lists.newArrayList();
|
||||
|
||||
$.accept(this);
|
||||
}
|
||||
|
||||
public Category addCategory(String name, Consumer<Category> category) {
|
||||
Category cat = new Category(this, name, category);
|
||||
categories.add(cat);
|
||||
return cat;
|
||||
}
|
||||
|
||||
public ResourceLocation getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<Category> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.wayoftime.bloodmagic.guide.page;
|
||||
|
||||
import com.wayoftime.bloodmagic.guide.Guide;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PageComponent {
|
||||
|
||||
private final int height;
|
||||
private IComponentSplitter splitter;
|
||||
private IViewingRequirement viewingRequirement;
|
||||
|
||||
public PageComponent(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void draw(Minecraft minecraft, ScaledResolution resolution, FontRenderer font) {
|
||||
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IComponentSplitter getSplitter() {
|
||||
return splitter;
|
||||
}
|
||||
|
||||
public PageComponent withComponentSplitter(IComponentSplitter splitter) {
|
||||
this.splitter = splitter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IViewingRequirement getViewingRequirement() {
|
||||
return viewingRequirement;
|
||||
}
|
||||
|
||||
public PageComponent withViewingRequirement(IViewingRequirement viewingRequirement) {
|
||||
this.viewingRequirement = viewingRequirement;
|
||||
return this;
|
||||
}
|
||||
|
||||
public interface IComponentSplitter {
|
||||
void split(Consumer<PageComponent> components, int currentPosition, int pageHeight);
|
||||
}
|
||||
|
||||
public interface IViewingRequirement {
|
||||
boolean canView(EntityPlayer player, World world, ItemStack guideStack, Guide guide);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.wayoftime.bloodmagic.guide.page;
|
||||
|
||||
public class PageComponentFiller extends PageComponent {
|
||||
|
||||
public PageComponentFiller() {
|
||||
super(-1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.wayoftime.bloodmagic.guide.page;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.vecmath.Point2i;
|
||||
|
||||
public class PageComponentImage extends PageComponent {
|
||||
|
||||
private final Sprite sprite;
|
||||
|
||||
public PageComponentImage(Sprite sprite) {
|
||||
super(sprite.size.y);
|
||||
|
||||
this.sprite = sprite;
|
||||
}
|
||||
|
||||
public static class Sprite {
|
||||
private final ResourceLocation location;
|
||||
private final Point2i startPosition;
|
||||
private final Point2i size;
|
||||
|
||||
public Sprite(ResourceLocation location, Point2i startPosition, Point2i size) {
|
||||
this.location = location;
|
||||
this.startPosition = startPosition;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void draw(int x, int y) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.wayoftime.bloodmagic.guide.page;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class PageComponentItem extends PageComponent {
|
||||
|
||||
private final ItemStack item;
|
||||
|
||||
public PageComponentItem(ItemStack item) {
|
||||
super(18);
|
||||
|
||||
this.item = item;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.wayoftime.bloodmagic.guide.page;
|
||||
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.registry.ForgeRegistries;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PageComponentRecipe extends PageComponent {
|
||||
|
||||
private final Supplier<IRecipe> recipeGetter;
|
||||
private IRecipe recipe;
|
||||
|
||||
public PageComponentRecipe(ResourceLocation recipe) {
|
||||
super(60);
|
||||
|
||||
this.recipeGetter = () -> ForgeRegistries.RECIPES.getValue(recipe);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.wayoftime.bloodmagic.guide.page;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.FurnaceRecipes;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PageComponentSmelting extends PageComponent {
|
||||
|
||||
private final ItemStack output;
|
||||
private final Supplier<ItemStack> inputGetter;
|
||||
private ItemStack input;
|
||||
|
||||
public PageComponentSmelting(ItemStack output) {
|
||||
super(20);
|
||||
|
||||
this.output = output;
|
||||
this.inputGetter = () -> FurnaceRecipes.instance().getSmeltingResult(output);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.wayoftime.bloodmagic.guide.page;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PageComponentText extends PageComponent {
|
||||
|
||||
private final ITextComponent textComponent;
|
||||
|
||||
public PageComponentText(ITextComponent text) {
|
||||
super(-1);
|
||||
|
||||
this.textComponent = text;
|
||||
withComponentSplitter(new StringSplitter(textComponent));
|
||||
}
|
||||
|
||||
private static class StringSplitter implements IComponentSplitter {
|
||||
|
||||
private final ITextComponent component;
|
||||
|
||||
public StringSplitter(ITextComponent component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void split(Consumer<PageComponent> components, int currentPosition, int pageHeight) {
|
||||
String fullText = component.getFormattedText();
|
||||
FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer;
|
||||
List<String> lines = fontRenderer.listFormattedStringToWidth(fullText, 300);
|
||||
int remainingSpace = pageHeight - currentPosition;
|
||||
for (String line : lines) {
|
||||
List<String> componentLines = Lists.newArrayList();
|
||||
if (remainingSpace >= fontRenderer.FONT_HEIGHT + 3) {
|
||||
componentLines.add(line);
|
||||
remainingSpace += fontRenderer.FONT_HEIGHT + 3;
|
||||
} else {
|
||||
remainingSpace = pageHeight;
|
||||
components.accept(new PageComponentText(new TextComponentString(String.join(" ", componentLines))));
|
||||
componentLines.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.wayoftime.bloodmagic.guide.test;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wayoftime.bloodmagic.guide.Entry;
|
||||
import com.wayoftime.bloodmagic.guide.Guide;
|
||||
import com.wayoftime.bloodmagic.guide.page.PageComponentFiller;
|
||||
import com.wayoftime.bloodmagic.guide.page.PageComponentItem;
|
||||
import com.wayoftime.bloodmagic.guide.page.PageComponentText;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraftforge.event.RegistryEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mod(modid = "test_guide")
|
||||
@Mod.EventBusSubscriber(modid = "test_guide")
|
||||
public class GuideTest {
|
||||
|
||||
public static final List<Guide> GUIDES = Lists.newArrayList();
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
GUIDES.add(new Guide(new ResourceLocation("guide_test", "test"), guide -> {
|
||||
guide.addCategory("test_cat_1", category -> {
|
||||
category.addEntry(new Entry("test_entry_1", test1 -> {
|
||||
test1.appendComponent(new PageComponentText(new TextComponentString("doot")));
|
||||
}));
|
||||
});
|
||||
|
||||
guide.addCategory("test_cat_2", category -> {
|
||||
category.addEntry(new Entry("test_entry_2", test2 -> {
|
||||
test2.appendComponent(new PageComponentText(new TextComponentString("what's up bud")));
|
||||
test2.appendComponent(new PageComponentItem(new ItemStack(Items.DIAMOND)));
|
||||
test2.appendComponent(new PageComponentFiller());
|
||||
}));
|
||||
|
||||
category.addEntry(new Entry("test_entry_3", test3 -> {
|
||||
test3.appendComponent(new PageComponentFiller());
|
||||
test3.appendComponent(new PageComponentFiller());
|
||||
}));
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerItems(RegistryEvent.Register<Item> event) {
|
||||
for (Guide guide : GUIDES)
|
||||
event.getRegistry().register(new ItemGuide(guide));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.wayoftime.bloodmagic.guide.test;
|
||||
|
||||
import com.wayoftime.bloodmagic.guide.Guide;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
public class ItemGuide extends Item {
|
||||
|
||||
public ItemGuide(Guide guide) {
|
||||
setRegistryName(guide.getId().toString().replace(":", "_"));
|
||||
setTranslationKey(guide.getId().toString());
|
||||
setMaxStackSize(1);
|
||||
setCreativeTab(CreativeTabs.MISC);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.wayoftime.bloodmagic.guide.test.gui;
|
||||
|
||||
import com.wayoftime.bloodmagic.guide.Category;
|
||||
import com.wayoftime.bloodmagic.guide.Entry;
|
||||
|
||||
public class Bookmark {
|
||||
|
||||
private Category category;
|
||||
private Entry entry;
|
||||
|
||||
public Bookmark atPosition(Category category, Entry entry) {
|
||||
this.category = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Category getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public Entry getEntry() {
|
||||
return entry;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.wayoftime.bloodmagic.guide.test.gui;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.wayoftime.bloodmagic.guide.Guide;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GuiGuide extends GuiScreen {
|
||||
|
||||
private static final Map<Guide, GuiGuide> SCREENS = Maps.newHashMap();
|
||||
|
||||
private final Guide guide;
|
||||
private final Bookmark bookmark;
|
||||
|
||||
public GuiGuide(Guide guide) {
|
||||
this.guide = guide;
|
||||
this.bookmark = new Bookmark();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
// TODO update bookmark
|
||||
super.onGuiClosed();
|
||||
}
|
||||
|
||||
public static GuiGuide getGui(Guide guide) {
|
||||
return SCREENS.compute(guide, (k, v) -> v == null ? new GuiGuide(guide) : v);
|
||||
}
|
||||
}
|
58
src/main/java/com/wayoftime/bloodmagic/item/IBindable.java
Normal file
58
src/main/java/com/wayoftime/bloodmagic/item/IBindable.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implement this interface on any Item that can be bound to a player.
|
||||
*/
|
||||
public interface IBindable {
|
||||
|
||||
/**
|
||||
* Gets an object that stores who this item is bound to.
|
||||
* <p>
|
||||
* If the item is not bound, this will be null.
|
||||
*
|
||||
* @param stack - The owned ItemStack
|
||||
* @return - The binding object
|
||||
*/
|
||||
@Nullable
|
||||
default Binding getBinding(ItemStack stack) {
|
||||
Binding binding = Binding.fromStack(stack);
|
||||
return !stack.isEmpty() && binding != null ? binding : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the player attempts to bind the item.
|
||||
*
|
||||
* @param player - The Player attempting to bind the item
|
||||
* @param stack - The ItemStack to attempt binding
|
||||
* @return If binding was successful.
|
||||
*/
|
||||
default boolean onBind(EntityPlayer player, ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void applyBinding(ItemStack stack, EntityPlayer player) {
|
||||
Binding binding = new Binding(player);
|
||||
applyBinding(stack, binding);
|
||||
}
|
||||
|
||||
static void applyBinding(ItemStack stack, Binding binding) {
|
||||
if (!stack.hasTagCompound())
|
||||
stack.setTagCompound(new NBTTagCompound());
|
||||
|
||||
stack.getTagCompound().setTag("binding", binding.serializeNBT());
|
||||
}
|
||||
|
||||
static void appendTooltip(Binding binding, List<String> tooltip) {
|
||||
if (binding != null)
|
||||
tooltip.add(I18n.format("tooltip.bloodmagic:bound_owner", binding.getOwnerName()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.wayoftime.bloodmagic.block.BlockBloodAltar;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarTier;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarUtil;
|
||||
import com.wayoftime.bloodmagic.core.altar.IAltarManipulator;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemAltarBuilder extends ItemMundane implements IAltarManipulator {
|
||||
|
||||
public ItemAltarBuilder() {
|
||||
super("altar_builder");
|
||||
|
||||
setMaxStackSize(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
|
||||
if (world.isRemote)
|
||||
return ActionResult.newResult(EnumActionResult.PASS, player.getHeldItem(hand));
|
||||
|
||||
if (player.isSneaking()) {
|
||||
ItemStack held = player.getHeldItem(hand);
|
||||
AltarTier newTier = cycleTier(held);
|
||||
player.sendStatusMessage(new TextComponentTranslation("chat.bloodmagic:altar_builder_cycled", new TextComponentTranslation("enchantment.level." + newTier.getDisplayNumber())), true);
|
||||
return ActionResult.newResult(EnumActionResult.SUCCESS, held);
|
||||
}
|
||||
|
||||
return super.onItemRightClick(world, player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
|
||||
IBlockState state = world.getBlockState(pos);
|
||||
if (state.getBlock() instanceof BlockBloodAltar) {
|
||||
AltarUtil.constructAltar(world, pos, getCurrentTier(player.getHeldItem(hand)));
|
||||
return EnumActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return super.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
|
||||
tooltip.add(I18n.format("tooltip.bloodmagic:tier", I18n.format("enchantment.level." + getCurrentTier(stack).getDisplayNumber())));
|
||||
}
|
||||
|
||||
private AltarTier getCurrentTier(ItemStack stack) {
|
||||
if (!stack.hasTagCompound())
|
||||
return AltarTier.ONE;
|
||||
|
||||
return AltarTier.VALUES[Math.min(AltarTier.VALUES.length - 1, Math.max(0, stack.getTagCompound().getInteger("altar_tier")))];
|
||||
}
|
||||
|
||||
private AltarTier cycleTier(ItemStack stack) {
|
||||
AltarTier current = getCurrentTier(stack);
|
||||
int nextOrdinal = current.ordinal() + 1;
|
||||
if (nextOrdinal >= AltarTier.VALUES.length)
|
||||
nextOrdinal = 0;
|
||||
|
||||
NBTTagCompound tag = stack.getTagCompound();
|
||||
if (tag == null)
|
||||
stack.setTagCompound(tag = new NBTTagCompound());
|
||||
|
||||
tag.setInteger("altar_tier", nextOrdinal);
|
||||
return AltarTier.VALUES[nextOrdinal];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemBindable extends ItemMundane implements IBindable {
|
||||
|
||||
public ItemBindable(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
|
||||
Binding binding = getBinding(stack);
|
||||
if (binding == null)
|
||||
return;
|
||||
|
||||
tooltip.add(I18n.format("tooltip.bloodmagic:bound_owner", binding.getOwnerName()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.*;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemBloodOrb extends ItemBindable implements IBloodOrb {
|
||||
|
||||
private final BloodOrb orb;
|
||||
|
||||
public ItemBloodOrb(BloodOrb orb) {
|
||||
super("blood_orb_" + orb.getName().getPath());
|
||||
|
||||
this.orb = orb;
|
||||
|
||||
setMaxStackSize(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
|
||||
ItemStack held = player.getHeldItem(hand);
|
||||
Binding binding = getBinding(held);
|
||||
if (binding != null) {
|
||||
SoulNetwork network = SoulNetwork.get(binding.getOwnerId());
|
||||
if (player.capabilities.isCreativeMode || player.attackEntityFrom(SoulNetwork.WEAK_SOUL, 1.0F))
|
||||
network.submitInteraction(NetworkInteraction.asItemInfo(held, world, player, 200));
|
||||
}
|
||||
|
||||
return super.onItemRightClick(world, player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
|
||||
super.addInformation(stack, world, tooltip, flag);
|
||||
|
||||
BloodOrb orb = getOrb(stack);
|
||||
if (orb != null && flag.isAdvanced())
|
||||
tooltip.add(I18n.format("tooltip.bloodmagic:object_owner", orb.getName().getNamespace()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BloodOrb getOrb(@Nonnull ItemStack stack) {
|
||||
return orb;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarUtil;
|
||||
import com.wayoftime.bloodmagic.core.network.SoulNetwork;
|
||||
import com.wayoftime.bloodmagic.core.util.BooleanResult;
|
||||
import com.wayoftime.bloodmagic.tile.TileBloodAltar;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class ItemDaggerSelfSacrifice extends ItemMundane {
|
||||
|
||||
private final Type type;
|
||||
|
||||
public ItemDaggerSelfSacrifice(Type sacrifice) {
|
||||
super("dagger_self_sacrifice" + (sacrifice == Type.CREATIVE ? "_creative" : ""));
|
||||
|
||||
setMaxStackSize(1);
|
||||
|
||||
this.type = sacrifice;
|
||||
|
||||
if (sacrifice != Type.CREATIVE)
|
||||
addPropertyOverride(new ResourceLocation(BloodMagic.MODID, "charged"), (stack, worldIn, entityIn) -> stack.hasTagCompound() && stack.getTagCompound().hasKey("charge") ? 1.0F : 0.0F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
|
||||
player.attackEntityFrom(SoulNetwork.WEAK_SOUL, 2.0F);
|
||||
BooleanResult<Integer> fillResult = AltarUtil.handleSacrifice(player, type.amount);
|
||||
if (!fillResult.isSuccess())
|
||||
return ActionResult.newResult(EnumActionResult.PASS, player.getHeldItem(hand));
|
||||
|
||||
return ActionResult.newResult(EnumActionResult.SUCCESS, player.getHeldItem(hand));
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
NORMAL(200),
|
||||
CREATIVE(Integer.MAX_VALUE),
|
||||
;
|
||||
|
||||
private final int amount;
|
||||
|
||||
Type(int amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
}
|
163
src/main/java/com/wayoftime/bloodmagic/item/ItemLivingArmor.java
Normal file
163
src/main/java/com/wayoftime/bloodmagic/item/ItemLivingArmor.java
Normal file
|
@ -0,0 +1,163 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicItems;
|
||||
import com.wayoftime.bloodmagic.core.living.ILivingContainer;
|
||||
import com.wayoftime.bloodmagic.core.living.LivingStats;
|
||||
import com.wayoftime.bloodmagic.core.living.LivingUpgrade;
|
||||
import com.wayoftime.bloodmagic.core.living.LivingUtil;
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import com.wayoftime.bloodmagic.core.network.SoulNetwork;
|
||||
import com.wayoftime.bloodmagic.core.network.NetworkInteraction;
|
||||
import com.wayoftime.bloodmagic.core.util.BooleanResult;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||
import net.minecraft.item.ItemArmor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.ISpecialArmor;
|
||||
import net.minecraftforge.common.util.EnumHelper;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemLivingArmor extends ItemArmor implements ILivingContainer, ISpecialArmor, IBindable {
|
||||
|
||||
public static final ArmorMaterial MATERIAL = EnumHelper.addArmorMaterial("living", "living", 100, new int[]{1, 2, 3, 4}, 3, SoundEvents.ITEM_ARMOR_EQUIP_IRON, 2.0F);
|
||||
|
||||
public ItemLivingArmor(EntityEquipmentSlot slot) {
|
||||
super(MATERIAL, 0, slot);
|
||||
|
||||
setTranslationKey(BloodMagic.MODID + ":living_armor_" + slot.getName());
|
||||
setRegistryName("living_armor_" + slot.getName());
|
||||
setCreativeTab(BloodMagic.TAB_BM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onArmorTick(World world, EntityPlayer player, ItemStack stack) {
|
||||
if (getBinding(stack) == null)
|
||||
IBindable.applyBinding(stack, player);
|
||||
|
||||
super.onArmorTick(world, player, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap<String, AttributeModifier> getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) {
|
||||
Multimap<String, AttributeModifier> modifiers = super.getAttributeModifiers(slot, stack);
|
||||
if (slot != EntityEquipmentSlot.CHEST)
|
||||
return modifiers;
|
||||
|
||||
LivingStats stats = getLivingStats(stack);
|
||||
if (stats == null)
|
||||
return modifiers;
|
||||
|
||||
stats.getUpgrades().forEach((k, v) -> {
|
||||
if (k.getAttributeProvider() != null)
|
||||
k.getAttributeProvider().handleAttributes(stats, modifiers, k.getLevel(v));
|
||||
});
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArmorProperties getProperties(EntityLivingBase player, @Nonnull ItemStack armor, DamageSource source, double damage, int slot) {
|
||||
if (source == DamageSource.DROWN || source == DamageSource.OUT_OF_WORLD)
|
||||
return new ArmorProperties(-1, 0D, 0);
|
||||
|
||||
double armorReduction;
|
||||
double damageAmount = 0.25;
|
||||
double armorPenetrationReduction = 0;
|
||||
int maxAbsorption = 100000;
|
||||
|
||||
if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_FEET || armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_HEAD)
|
||||
damageAmount = 3d / 20d * 0.6;
|
||||
else if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_LEGS)
|
||||
damageAmount = 6d / 20d * 0.6;
|
||||
else if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_CHEST)
|
||||
damageAmount = 0.64;
|
||||
|
||||
if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_CHEST) {
|
||||
armorReduction = 0.24 / 0.64; // This values puts it at iron level
|
||||
|
||||
if (!LivingUtil.hasFullSet((EntityPlayer) player))
|
||||
return new ArmorProperties(-1, damageAmount * armorReduction, maxAbsorption);
|
||||
|
||||
LivingStats stats = getLivingStats(armor);
|
||||
double protection = 1.0D;
|
||||
if (stats != null)
|
||||
for (Map.Entry<LivingUpgrade, Integer> entry : stats.getUpgrades().entrySet())
|
||||
if (entry.getKey().getArmorProvider() != null)
|
||||
protection *= 1 - entry.getKey().getArmorProvider().getProtection((EntityPlayer) player, source, entry.getKey().getLevel(entry.getValue()));
|
||||
|
||||
armorReduction += (1 - protection) * (1 - armorReduction);
|
||||
damageAmount *= armorReduction;
|
||||
return new ArmorProperties(-1, source.isUnblockable() ? 1 - protection : damageAmount, maxAbsorption);
|
||||
} else if (source.isUnblockable())
|
||||
return new ArmorProperties(-1, damageAmount * armorPenetrationReduction, maxAbsorption);
|
||||
|
||||
return new ArmorProperties(-1, damageAmount, maxAbsorption);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArmorDisplay(EntityPlayer player, @Nonnull ItemStack armor, int slot) {
|
||||
if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_HEAD)
|
||||
return 3;
|
||||
if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_CHEST)
|
||||
return 8;
|
||||
if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_LEGS)
|
||||
return 6;
|
||||
if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_FEET)
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getArmorTexture(ItemStack stack, Entity entity, EntityEquipmentSlot slot, String type) {
|
||||
if (this == RegistrarBloodMagicItems.LIVING_ARMOR_CHEST || this == RegistrarBloodMagicItems.LIVING_ARMOR_HEAD || this == RegistrarBloodMagicItems.LIVING_ARMOR_FEET)
|
||||
return "bloodmagic:textures/models/armor/living_armor_layer_1.png";
|
||||
|
||||
if (this == RegistrarBloodMagicItems.LIVING_ARMOR_LEGS)
|
||||
return "bloodmagic:textures/models/armor/living_armor_layer_2.png";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damageArmor(EntityLivingBase entity, @Nonnull ItemStack stack, DamageSource source, int damage, int slot) {
|
||||
if (stack.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_CHEST && damage > getMaxDamage(stack) - getDamage(stack)) {
|
||||
Binding binding = getBinding(stack);
|
||||
if (binding == null) {
|
||||
entity.attackEntityFrom(SoulNetwork.WEAK_SOUL, 2.0F);
|
||||
return;
|
||||
}
|
||||
|
||||
BooleanResult<Integer> result = SoulNetwork.get(binding.getOwnerId()).submitInteraction(NetworkInteraction.asItemInfo(stack, entity.getEntityWorld(), entity, damage * 100).syphon());
|
||||
if (!result.isSuccess())
|
||||
entity.attackEntityFrom(SoulNetwork.WEAK_SOUL, 2.0F);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
stack.damageItem(damage, entity);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
|
||||
ILivingContainer.appendLivingTooltip(getLivingStats(stack), tooltip, true);
|
||||
IBindable.appendTooltip(getBinding(stack), tooltip);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicLivingArmor;
|
||||
import com.wayoftime.bloodmagic.core.living.ILivingContainer;
|
||||
import com.wayoftime.bloodmagic.core.living.LivingStats;
|
||||
import com.wayoftime.bloodmagic.core.living.LivingUtil;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemLivingTome extends ItemMundane implements ILivingContainer {
|
||||
|
||||
public ItemLivingTome() {
|
||||
super("living_tome");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer player, EnumHand hand) {
|
||||
ItemStack held = player.getHeldItem(hand);
|
||||
|
||||
LivingStats armorStats = LivingStats.fromPlayer(player, true);
|
||||
if (armorStats == null)
|
||||
return ActionResult.newResult(EnumActionResult.PASS, held);
|
||||
|
||||
LivingStats tomeStats = getLivingStats(held);
|
||||
if (tomeStats == null)
|
||||
return ActionResult.newResult(EnumActionResult.PASS, held);
|
||||
|
||||
tomeStats.getUpgrades().forEach((k, v) -> LivingUtil.applyNewExperience(player, k, v));
|
||||
// LivingStats.toPlayer(player, armorStats);
|
||||
held.shrink(1);
|
||||
return ActionResult.newResult(EnumActionResult.SUCCESS, held);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> items) {
|
||||
if (!isInCreativeTab(tab))
|
||||
return;
|
||||
|
||||
RegistrarBloodMagicLivingArmor.UPGRADES.values().forEach(upgrade -> {
|
||||
int exp = 0;
|
||||
while ((exp = upgrade.getNextRequirement(exp)) != 0) {
|
||||
ItemStack tome = new ItemStack(this);
|
||||
updateLivingStates(tome, new LivingStats().setMaxPoints(upgrade.getLevelCost(exp)).addExperience(upgrade.getKey(), exp));
|
||||
items.add(tome);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
|
||||
ILivingContainer.appendLivingTooltip(getLivingStats(stack), tooltip, false);
|
||||
}
|
||||
}
|
13
src/main/java/com/wayoftime/bloodmagic/item/ItemMundane.java
Normal file
13
src/main/java/com/wayoftime/bloodmagic/item/ItemMundane.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
package com.wayoftime.bloodmagic.item;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
public class ItemMundane extends Item {
|
||||
|
||||
public ItemMundane(String name) {
|
||||
setTranslationKey(BloodMagic.MODID + ":" + name);
|
||||
setCreativeTab(BloodMagic.TAB_BM);
|
||||
setRegistryName(name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.wayoftime.bloodmagic.item.sigil;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface ISigil {
|
||||
|
||||
@Nonnull
|
||||
default EnumActionResult onRightClick(@Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull EnumHand hand, @Nonnull Binding binding) {
|
||||
return EnumActionResult.PASS;
|
||||
}
|
||||
|
||||
default EnumActionResult onInteract(@Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side, @Nonnull EnumHand hand, @Nonnull Binding binding) {
|
||||
return EnumActionResult.PASS;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
int getCost();
|
||||
|
||||
interface Toggle extends ISigil {
|
||||
|
||||
default void onToggle(boolean active, @Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull EnumHand hand, @Nonnull Binding binding) {
|
||||
|
||||
}
|
||||
|
||||
default void onUpdate(@Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnegative int itemSlot, boolean isHeld, @Nonnull Binding binding) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
interface Holding extends ISigil {
|
||||
|
||||
int getSize(ItemStack stack);
|
||||
|
||||
int getEquippedSigil(ItemStack stack);
|
||||
|
||||
NonNullList<ItemStack> getHeldSigils(ItemStack stack);
|
||||
|
||||
void setHeldSigils(ItemStack stack, NonNullList<ItemStack> inventory);
|
||||
}
|
||||
}
|
176
src/main/java/com/wayoftime/bloodmagic/item/sigil/ItemSigil.java
Normal file
176
src/main/java/com/wayoftime/bloodmagic/item/sigil/ItemSigil.java
Normal file
|
@ -0,0 +1,176 @@
|
|||
package com.wayoftime.bloodmagic.item.sigil;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import com.wayoftime.bloodmagic.core.network.SoulNetwork;
|
||||
import com.wayoftime.bloodmagic.core.network.NetworkInteraction;
|
||||
import com.wayoftime.bloodmagic.core.util.BooleanResult;
|
||||
import com.wayoftime.bloodmagic.core.util.register.IVariantProvider;
|
||||
import com.wayoftime.bloodmagic.item.IBindable;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.IItemPropertyGetter;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* TODO - See checklist
|
||||
* - [-] Sigils
|
||||
* - [x] Divination
|
||||
* - [x] Air
|
||||
* - [x] Fast Miner
|
||||
* - [-] Haste
|
||||
* - [ ] Water
|
||||
* - [ ] Lava
|
||||
* - [ ] Void
|
||||
* - [ ] Green Grove
|
||||
* - [ ] Blood Light
|
||||
* - [ ] Elemental Affinity
|
||||
* - [ ] Magnetism
|
||||
* - [ ] Suppression
|
||||
* - [ ] Seer
|
||||
* - Perhaps this could be modified to show network interaction history instead of additional altar data?
|
||||
* - [ ] Ender Severance
|
||||
* - [ ] Whirlwind
|
||||
* - [ ] Phantom Bridge
|
||||
* - [ ] Compression
|
||||
* - [ ] Holding
|
||||
* - [ ] Teleposition
|
||||
* - [ ] Transposition
|
||||
* - [ ] Claw
|
||||
* - [ ] Bounce
|
||||
* - [ ] Frost
|
||||
*/
|
||||
public class ItemSigil extends Item implements IBindable, IVariantProvider {
|
||||
|
||||
private final ISigil sigil;
|
||||
|
||||
public ItemSigil(ISigil sigil, String name) {
|
||||
this.sigil = sigil;
|
||||
|
||||
setCreativeTab(BloodMagic.TAB_BM);
|
||||
setTranslationKey(BloodMagic.MODID + ":sigil_" + name);
|
||||
setRegistryName("sigil_" + name);
|
||||
setMaxStackSize(1);
|
||||
|
||||
if (sigil instanceof ISigil.Toggle) {
|
||||
addPropertyOverride(new ResourceLocation(BloodMagic.MODID, "toggled"), new IItemPropertyGetter() {
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) {
|
||||
return isActive(stack) ? 1.0F : 0.0F;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
|
||||
if (player instanceof FakePlayer)
|
||||
return ActionResult.newResult(EnumActionResult.FAIL, player.getHeldItem(hand));
|
||||
|
||||
ItemStack sigilStack = getSigilStack(player, hand);
|
||||
Binding binding = getBinding(sigilStack);
|
||||
if (binding == null || binding.getOwnerId() == null)
|
||||
return ActionResult.newResult(EnumActionResult.FAIL, player.getHeldItem(hand));
|
||||
|
||||
if (sigil instanceof ISigil.Toggle && player.isSneaking()) {
|
||||
boolean newState = toggleState(sigilStack);
|
||||
((ISigil.Toggle) sigil).onToggle(newState, sigilStack, player, world, hand, binding);
|
||||
return ActionResult.newResult(EnumActionResult.SUCCESS, player.getHeldItem(hand));
|
||||
}
|
||||
|
||||
EnumActionResult result = sigil.onRightClick(sigilStack, player, world, hand, binding);
|
||||
if (result == EnumActionResult.SUCCESS) {
|
||||
BooleanResult<Integer> syphonResult = SoulNetwork.get(binding.getOwnerId()).submitInteraction(NetworkInteraction.asItemInfo(sigilStack, world, player, sigil.getCost()).syphon());
|
||||
if (!syphonResult.isSuccess())
|
||||
player.attackEntityFrom(SoulNetwork.WEAK_SOUL, 2.0F);
|
||||
}
|
||||
|
||||
return ActionResult.newResult(result, player.getHeldItem(hand));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
|
||||
if (player instanceof FakePlayer)
|
||||
return EnumActionResult.FAIL;
|
||||
|
||||
ItemStack stack = getSigilStack(player, hand);
|
||||
Binding binding = getBinding(stack);
|
||||
if (binding == null)
|
||||
return EnumActionResult.FAIL;
|
||||
|
||||
return sigil.onInteract(stack, player, world, pos, facing, hand, binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(ItemStack stack, World world, Entity entity, int itemSlot, boolean isSelected) {
|
||||
if (!(entity instanceof EntityPlayer) || entity instanceof FakePlayer)
|
||||
return;
|
||||
|
||||
ItemStack sigilStack = getSigilStack(stack);
|
||||
if (sigil instanceof ISigil.Toggle) {
|
||||
Binding binding = getBinding(sigilStack);
|
||||
if (binding != null && isActive(sigilStack)) {
|
||||
((ISigil.Toggle) sigil).onUpdate(sigilStack, (EntityPlayer) entity, world, itemSlot, isSelected, binding);
|
||||
if (world.getTotalWorldTime() % 100 == 0) {
|
||||
BooleanResult<Integer> result = SoulNetwork.get(binding.getOwnerId()).submitInteraction(NetworkInteraction.asItemInfo(sigilStack, world, entity, sigil.getCost()).syphon());
|
||||
if (!result.isSuccess())
|
||||
entity.attackEntityFrom(SoulNetwork.WEAK_SOUL, 1.0F);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
|
||||
IBindable.appendTooltip(getBinding(stack), tooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return slotChanged;
|
||||
}
|
||||
|
||||
public ISigil getSigil() {
|
||||
return sigil;
|
||||
}
|
||||
|
||||
public ItemStack getSigilStack(EntityPlayer player, EnumHand hand) {
|
||||
return getSigilStack(player.getHeldItem(hand));
|
||||
}
|
||||
|
||||
public ItemStack getSigilStack(ItemStack sigilStack) {
|
||||
if (sigil instanceof ISigil.Holding) {
|
||||
ISigil.Holding holding = (ISigil.Holding) sigil;
|
||||
int current = holding.getEquippedSigil(sigilStack);
|
||||
return holding.getHeldSigils(sigilStack).get(current);
|
||||
}
|
||||
|
||||
return sigilStack;
|
||||
}
|
||||
|
||||
public boolean toggleState(ItemStack stack) {
|
||||
if (!stack.hasTagCompound())
|
||||
return false;
|
||||
|
||||
boolean newState = !isActive(stack);
|
||||
stack.getTagCompound().setBoolean("active", newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
public boolean isActive(ItemStack stack) {
|
||||
return stack.hasTagCompound() && stack.getTagCompound().getBoolean("active");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.wayoftime.bloodmagic.item.sigil;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SigilAir implements ISigil {
|
||||
|
||||
@Override
|
||||
public int getCost() {
|
||||
return 50;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public EnumActionResult onRightClick(@Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull EnumHand hand, Binding binding) {
|
||||
if (world.isRemote) {
|
||||
Vec3d vec = player.getLookVec();
|
||||
double wantedVelocity = 1.7;
|
||||
|
||||
// TODO - Revisit after potions
|
||||
// if (player.isPotionActive(RegistrarBloodMagic.BOOST)) {
|
||||
// int amplifier = player.getActivePotionEffect(RegistrarBloodMagic.BOOST).getAmplifier();
|
||||
// wantedVelocity += (1 + amplifier) * (0.35);
|
||||
// }
|
||||
|
||||
player.motionX = vec.x * wantedVelocity;
|
||||
player.motionY = vec.y * wantedVelocity;
|
||||
player.motionZ = vec.z * wantedVelocity;
|
||||
world.playSound(null, player.posX, player.posY, player.posZ, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
|
||||
}
|
||||
|
||||
if (!world.isRemote)
|
||||
player.fallDistance = 0;
|
||||
|
||||
return EnumActionResult.SUCCESS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.wayoftime.bloodmagic.item.sigil;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import com.wayoftime.bloodmagic.core.network.SoulNetwork;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SigilDivination implements ISigil {
|
||||
|
||||
@Override
|
||||
public int getCost() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public EnumActionResult onRightClick(@Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull EnumHand hand, Binding binding) {
|
||||
player.sendStatusMessage(new TextComponentString("Current Essence: " + SoulNetwork.get(binding.getOwnerId()).getEssence()), true);
|
||||
return EnumActionResult.PASS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.wayoftime.bloodmagic.item.sigil;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SigilFastMiner implements ISigil.Toggle {
|
||||
|
||||
@Override
|
||||
public int getCost() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(@Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, int itemSlot, boolean isHeld, @Nonnull Binding binding) {
|
||||
player.addPotionEffect(new PotionEffect(MobEffects.HASTE, 2, 0, true, false));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.wayoftime.bloodmagic.item.sigil;
|
||||
|
||||
import com.wayoftime.bloodmagic.core.network.Binding;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SigilHaste implements ISigil.Toggle {
|
||||
|
||||
@Override
|
||||
public int getCost() {
|
||||
return 250;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(@Nonnull ItemStack stack, @Nonnull EntityPlayer player, @Nonnull World world, int itemSlot, boolean isHeld, @Nonnull Binding binding) {
|
||||
player.addPotionEffect(new PotionEffect(MobEffects.SPEED, 2, 0, true, false)); // TODO - RegistrarBloodMagic.BOOST
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.wayoftime.bloodmagic.proxy;
|
||||
|
||||
import com.wayoftime.bloodmagic.BloodMagic;
|
||||
import net.minecraftforge.client.model.obj.OBJLoader;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
public class ClientProxy implements IProxy {
|
||||
|
||||
@Override
|
||||
public void preInit() {
|
||||
OBJLoader.INSTANCE.addDomain(BloodMagic.MODID);
|
||||
|
||||
Display.setTitle("Basically 1.13"); // TODO - :BigThink:
|
||||
}
|
||||
}
|
8
src/main/java/com/wayoftime/bloodmagic/proxy/IProxy.java
Normal file
8
src/main/java/com/wayoftime/bloodmagic/proxy/IProxy.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.wayoftime.bloodmagic.proxy;
|
||||
|
||||
public interface IProxy {
|
||||
|
||||
default void preInit() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package com.wayoftime.bloodmagic.proxy;
|
||||
|
||||
public class ServerProxy implements IProxy {
|
||||
}
|
268
src/main/java/com/wayoftime/bloodmagic/tile/TileBloodAltar.java
Normal file
268
src/main/java/com/wayoftime/bloodmagic/tile/TileBloodAltar.java
Normal file
|
@ -0,0 +1,268 @@
|
|||
package com.wayoftime.bloodmagic.tile;
|
||||
|
||||
import com.wayoftime.bloodmagic.api.event.BloodMagicCraftedEvent;
|
||||
import com.wayoftime.bloodmagic.api.impl.BloodMagicAPI;
|
||||
import com.wayoftime.bloodmagic.api.impl.recipe.RecipeBloodAltar;
|
||||
import com.wayoftime.bloodmagic.core.RegistrarBloodMagic;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarTier;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarUpgrades;
|
||||
import com.wayoftime.bloodmagic.core.altar.AltarUtil;
|
||||
import com.wayoftime.bloodmagic.core.network.*;
|
||||
import com.wayoftime.bloodmagic.item.IBindable;
|
||||
import com.wayoftime.bloodmagic.tile.base.TileBase;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.ITickable;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.FluidTank;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fml.common.registry.ForgeRegistries;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/*
|
||||
* TODO - See checklist
|
||||
* - [-] Upgrades
|
||||
* - [x] Self Sacrifice
|
||||
* - [x] Sacrifice
|
||||
* - [x] Capacity
|
||||
* - [x] Augmented Capacity
|
||||
* - [ ] Speed
|
||||
* - [ ] Displacement
|
||||
* - [ ] Orb
|
||||
* - [ ] Acceleration
|
||||
* - [ ] Charging
|
||||
* - [-] Tanks
|
||||
* - [x] Main tank keeps buffer filled
|
||||
* - [ ] Buffer fills main tank
|
||||
*/
|
||||
public class TileBloodAltar extends TileBase implements ITickable {
|
||||
|
||||
private FluidTank tank = new FluidTank(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, 0), 10000);
|
||||
private FluidTank buffer = new FluidTank(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, 0), 1000); // Buffer has 10% the capacity of the tank
|
||||
private ItemStackHandler itemHandler = new ItemStackHandler(1);
|
||||
private AltarTier currentTier = AltarTier.ONE;
|
||||
private AltarUpgrades upgrades = new AltarUpgrades();
|
||||
private float progress;
|
||||
private RecipeBloodAltar recipe = null;
|
||||
private int drained;
|
||||
private long lastCompletionTime;
|
||||
|
||||
public TileBloodAltar() {
|
||||
tank.setTileEntity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
if (getWorld().getTotalWorldTime() % 20 == 0) {
|
||||
currentTier = AltarUtil.getTier(getWorld(), getPos());
|
||||
upgrades = AltarUtil.getUpgrades(getWorld(), pos, currentTier);
|
||||
handleTankUpdates();
|
||||
}
|
||||
|
||||
if (getWorld().getTotalWorldTime() - lastCompletionTime > 20)
|
||||
handleRecipe();
|
||||
}
|
||||
|
||||
protected void handleTankUpdates() {
|
||||
tank.setCapacity((int) (Fluid.BUCKET_VOLUME * 10 * upgrades.getCapacityModifier()));
|
||||
if (tank.getCapacity() < tank.getFluidAmount())
|
||||
tank.setFluid(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, tank.getCapacity()));
|
||||
|
||||
buffer.setCapacity((int) (tank.getCapacity() * 0.1D));
|
||||
if (buffer.getCapacity() < buffer.getFluidAmount())
|
||||
buffer.setFluid(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, buffer.getCapacity()));
|
||||
|
||||
if (buffer.getCapacity() > buffer.getFluidAmount() && tank.getFluidAmount() > 0) {
|
||||
FluidStack drained = tank.drain(100, true);
|
||||
if (drained != null)
|
||||
buffer.fill(drained, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleRecipe() {
|
||||
ItemStack inputItem = itemHandler.getStackInSlot(0);
|
||||
if (inputItem.isEmpty())
|
||||
return;
|
||||
|
||||
// Only look for a recipe if the altar currently has blood in it as well as the current recipe is null or the item doesn't match the recipe input
|
||||
if (tank.getFluidAmount() > 0 && (recipe == null || !recipe.getInput().apply(inputItem))) {
|
||||
RecipeBloodAltar newRecipe = BloodMagicAPI.INSTANCE.getRecipeRegistrar().getBloodAltar(inputItem);
|
||||
if (newRecipe != null && newRecipe.getMinimumTier().ordinal() <= currentTier.ordinal())
|
||||
recipe = newRecipe;
|
||||
}
|
||||
|
||||
// Match orbs
|
||||
if (recipe == null) {
|
||||
if (inputItem.getItem() instanceof IBloodOrb && inputItem.getItem() instanceof IBindable) {
|
||||
BloodOrb orb = ((IBloodOrb) inputItem.getItem()).getOrb(inputItem);
|
||||
Binding binding = ((IBindable) inputItem.getItem()).getBinding(inputItem);
|
||||
if (orb != null && binding != null) {
|
||||
if (currentTier.ordinal() < orb.getTier())
|
||||
return;
|
||||
|
||||
SoulNetwork network = SoulNetwork.get(binding.getOwnerId());
|
||||
if (network.getEssence() < orb.getCapacity()) {
|
||||
FluidStack drained = tank.drain(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, orb.getFillRate()), true);
|
||||
if (drained != null)
|
||||
network.submitInteraction(NetworkInteraction.asItemInfo(inputItem, world, pos, drained.amount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Check tier
|
||||
if (recipe.getMinimumTier().ordinal() > currentTier.ordinal())
|
||||
return;
|
||||
|
||||
// Check and handle progress loss
|
||||
if (tank.getFluidAmount() <= 0) {
|
||||
progress = Math.max(0, progress - (recipe.getDrainRate() / (recipe.getSyphon() * inputItem.getCount())));
|
||||
if (getWorld() instanceof WorldServer)
|
||||
((WorldServer) getWorld()).spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, 1, 0.1, 0, 0.1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
FluidStack tankDrain = tank.drain(new FluidStack(RegistrarBloodMagic.FLUID_LIFE_ESSENCE, recipe.getConsumeRate()), true);
|
||||
if (tankDrain == null)
|
||||
return;
|
||||
|
||||
if (getWorld() instanceof WorldServer)
|
||||
((WorldServer) getWorld()).spawnParticle(EnumParticleTypes.REDSTONE, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, 1, 0.2, 0, 0.2, 0);
|
||||
|
||||
drained += tankDrain.amount;
|
||||
progress = (float) drained / (Math.max(recipe.getSyphon() * inputItem.getCount(), 1));
|
||||
|
||||
if (progress >= 1.0F) {
|
||||
BloodMagicCraftedEvent.Altar event = new BloodMagicCraftedEvent.Altar(recipe.getOutput(), inputItem);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
|
||||
if (getWorld() instanceof WorldServer)
|
||||
((WorldServer) getWorld()).spawnParticle(EnumParticleTypes.REDSTONE, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, 40, 0.3, 0, 0.3, 0);
|
||||
|
||||
itemHandler.setStackInSlot(0, event.getOutput());
|
||||
lastCompletionTime = getWorld().getTotalWorldTime();
|
||||
resetProgress();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(NBTTagCompound tag) {
|
||||
tank.readFromNBT(tag.getCompoundTag("tank"));
|
||||
tank.setTileEntity(this);
|
||||
itemHandler.deserializeNBT(tag.getCompoundTag("inventory"));
|
||||
progress = tag.getFloat("progress");
|
||||
currentTier = AltarTier.VALUES[tag.getInteger("tier")];
|
||||
drained = tag.getInteger("drained");
|
||||
lastCompletionTime = tag.getLong("lastCompletionTime");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(NBTTagCompound tag) {
|
||||
tag.setTag("tank", tank.writeToNBT(new NBTTagCompound()));
|
||||
tag.setTag("inventory", itemHandler.serializeNBT());
|
||||
tag.setFloat("progress", progress);
|
||||
tag.setInteger("tier", currentTier.ordinal());
|
||||
tag.setInteger("drained", drained);
|
||||
tag.setLong("lastCompletionTime", lastCompletionTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
|
||||
return super.hasCapability(capability, facing) || capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY || capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
|
||||
if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
|
||||
return facing == null ? (T) tank : (T) buffer;
|
||||
|
||||
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
||||
return (T) itemHandler;
|
||||
|
||||
return super.getCapability(capability, facing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound getUpdateTag() {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
writeToNBT(tag);
|
||||
ItemStack contained = itemHandler.getStackInSlot(0);
|
||||
if (!contained.isEmpty()) {
|
||||
NBTTagCompound itemTag = new NBTTagCompound();
|
||||
itemTag.setString("item", contained.getItem().getRegistryName().toString());
|
||||
itemTag.setInteger("count", contained.getCount());
|
||||
itemTag.setInteger("data", contained.getMetadata());
|
||||
NBTTagCompound shareTag = contained.getItem().getNBTShareTag(contained);
|
||||
if (shareTag != null)
|
||||
itemTag.setTag("nbt", shareTag);
|
||||
|
||||
tag.setTag("item", itemTag);
|
||||
}
|
||||
|
||||
tag.setTag("tank", tank.writeToNBT(new NBTTagCompound()));
|
||||
tag.setFloat("progress", progress);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpdateTag(NBTTagCompound tag) {
|
||||
readCurrentPos(tag);
|
||||
if (tag.hasKey("item")) {
|
||||
Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(tag.getString("item")));
|
||||
int count = tag.getInteger("count");
|
||||
int meta = tag.getInteger("data");
|
||||
NBTTagCompound nbt = null;
|
||||
if (tag.hasKey("nbt"))
|
||||
nbt = tag.getCompoundTag("nbt");
|
||||
|
||||
ItemStack stack = new ItemStack(item, count, meta);
|
||||
if (nbt != null)
|
||||
stack.deserializeNBT(nbt);
|
||||
itemHandler.setStackInSlot(0, stack);
|
||||
} else {
|
||||
itemHandler.setStackInSlot(0, ItemStack.EMPTY);
|
||||
}
|
||||
tank.readFromNBT(tag.getCompoundTag("tank"));
|
||||
progress = tag.getFloat("progress");
|
||||
}
|
||||
|
||||
public void resetProgress() {
|
||||
recipe = null;
|
||||
drained = 0;
|
||||
progress = 0.0F;
|
||||
}
|
||||
|
||||
public FluidTank getTank() {
|
||||
return tank;
|
||||
}
|
||||
|
||||
public boolean isCrafting() {
|
||||
return recipe != null;
|
||||
}
|
||||
|
||||
public AltarTier getCurrentTier() {
|
||||
return currentTier;
|
||||
}
|
||||
|
||||
public float getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public AltarUpgrades getUpgrades() {
|
||||
return upgrades;
|
||||
}
|
||||
}
|
127
src/main/java/com/wayoftime/bloodmagic/tile/base/TileBase.java
Normal file
127
src/main/java/com/wayoftime/bloodmagic/tile/base/TileBase.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
package com.wayoftime.bloodmagic.tile.base;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Base tile class.
|
||||
* <p>
|
||||
* Handles data syncing and core data writing/reading.
|
||||
*/
|
||||
public class TileBase extends TileEntity {
|
||||
|
||||
@Override
|
||||
public final void readFromNBT(NBTTagCompound compound) {
|
||||
super.readFromNBT(compound);
|
||||
|
||||
if (compound.hasKey("baseData"))
|
||||
deserializeBase(compound.getCompoundTag("baseData"));
|
||||
|
||||
deserialize(compound.getCompoundTag("tileData"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final NBTTagCompound writeToNBT(NBTTagCompound compound) {
|
||||
super.writeToNBT(compound);
|
||||
|
||||
NBTTagCompound base = serializeBase();
|
||||
if (base != null)
|
||||
compound.setTag("baseData", base);
|
||||
|
||||
NBTTagCompound tileData = new NBTTagCompound();
|
||||
serialize(tileData);
|
||||
compound.setTag("tileData", tileData);
|
||||
return compound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #readFromNBT(NBTTagCompound)}
|
||||
* <p>
|
||||
* Internal data (such as coordinates) are handled for you. Just read the data you need.
|
||||
*
|
||||
* @param tagCompound - The tag compound to read from
|
||||
*/
|
||||
public void deserialize(NBTTagCompound tagCompound) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private method for reading base data from the tag compound.
|
||||
*
|
||||
* @param tagCompound - The tag compound to read from
|
||||
*/
|
||||
void deserializeBase(NBTTagCompound tagCompound) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #writeToNBT(NBTTagCompound)}
|
||||
* <p>
|
||||
* Internal data (such as coordinates) are handled for you. Just read the data you need.
|
||||
*
|
||||
* @param tagCompound - The tag compound to write to.
|
||||
* @return the modified tag compound
|
||||
*/
|
||||
public void serialize(NBTTagCompound tagCompound) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private method for writing base data to the tag compound.
|
||||
*
|
||||
* @return the modified tag compound
|
||||
*/
|
||||
NBTTagCompound serializeBase() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected final NBTTagCompound writeCurrentPos(NBTTagCompound compound) {
|
||||
compound.setString("id", getKey(getClass()).toString());
|
||||
compound.setInteger("x", this.pos.getX());
|
||||
compound.setInteger("y", this.pos.getY());
|
||||
compound.setInteger("z", this.pos.getZ());
|
||||
return compound;
|
||||
}
|
||||
|
||||
protected final void readCurrentPos(NBTTagCompound tag) {
|
||||
this.pos = new BlockPos(tag.getInteger("x"), tag.getInteger("y"), tag.getInteger("z"));
|
||||
}
|
||||
|
||||
public void notifyUpdate() {
|
||||
IBlockState state = world.getBlockState(pos);
|
||||
getWorld().notifyBlockUpdate(pos, state, state, 3);
|
||||
}
|
||||
|
||||
// Data syncing
|
||||
|
||||
@Override
|
||||
public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newState) {
|
||||
return oldState.getBlock() != newState.getBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SPacketUpdateTileEntity getUpdatePacket() {
|
||||
return new SPacketUpdateTileEntity(getPos(), -999, writeToNBT(new NBTTagCompound()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) {
|
||||
super.onDataPacket(net, pkt);
|
||||
readFromNBT(pkt.getNbtCompound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound getUpdateTag() {
|
||||
return writeToNBT(new NBTTagCompound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpdateTag(NBTTagCompound tag) {
|
||||
readFromNBT(tag);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue