Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement meter and dynamic remainder #1

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@

package net.wovenmc.woven.api.item.settings;

import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;

/**
* Represents a dummy class as template for API.
* <p>
* This should not be present in any module.
* An interface for handling the equipment slots of non-armor items.
*/
public class TemplateAPI {
@FunctionalInterface
public interface EquipmentHandler {
/**
* @param stack The stack to equip.
* @return The slot the stack should be equipped to.
*/
EquipmentSlot getEquipmentSlot(ItemStack stack);
}
130 changes: 130 additions & 0 deletions src/main/java/net/wovenmc/woven/api/item/settings/MeterComponent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2020 WovenMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.wovenmc.woven.api.item.settings;

import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;

/**
* A component that displays a colored meter on an item in a GUI, similar to the vanilla damage bar.
*/
public class MeterComponent {
repulica marked this conversation as resolved.
Show resolved Hide resolved
private final LevelHandler levelHandler;
private final ColorHandler colorHandler;
private final boolean displayAtFull;

private MeterComponent(LevelHandler levelHandler, ColorHandler colorHandler,
boolean displayAtFull) {
this.levelHandler = levelHandler;
this.colorHandler = colorHandler;
this.displayAtFull = displayAtFull;
}

/**
* Get the current level of the meter.
* @param stack The item stack to get the level for.
* @return The current level, as a float between 0 and 1 inclusive.
*/
public float getLevel(ItemStack stack) {
return levelHandler.getLevel(stack);
}

/**
* Get the current color of the meter.
* @param stack The item stack to get the color for.
* @return The current color as an RGB value.
*/
public int getColor(ItemStack stack) {
return colorHandler.getColor(stack, levelHandler.getLevel(stack));
}

/**
* @return true if the meter should be rendered when the value is 1.
*/
public boolean displayAtFull() {
return displayAtFull;
}

/**
* A builder for meter components.
*/
public static class Builder {
private LevelHandler levelHandler = stack ->
(stack.getMaxDamage() - stack.getDamage()) / (float) stack.getMaxDamage();
private ColorHandler colorHandler = (stack, level) ->
MathHelper.hsvToRgb(level / 3F, 1F, 1F);
private boolean displayAtFull = false;

/**
* @param handler The handler for getting the current level of a meter.
* @return The builder with the handler set.
*/
public Builder levelFunction(LevelHandler handler) {
this.levelHandler = handler;
return this;
}

/**
* @param handler The handler for getting the current color of a meter.
* @return The builder with the handler set.
*/
public Builder colorHandler(ColorHandler handler) {
this.colorHandler = handler;
return this;
}

/**
* @return The builder with the flag for displaying at full set.
*/
public Builder displayAtFull() {
this.displayAtFull = true;
return this;
}

/**
* @return A built meter component.
*/
public MeterComponent build() {
return new MeterComponent(levelHandler, colorHandler, displayAtFull);
}
}

/**
* An interface for determining the level of a meter.
*/
@FunctionalInterface
public interface LevelHandler {
/**
* @param stack The stack to get the meter level for.
* @return The level of the meter, as a float from 0 to 1 inclusive.
*/
float getLevel(ItemStack stack);
}

/**
* An interface for determining the color of a meter.
*/
@FunctionalInterface
public interface ColorHandler {
/**
* @param stack The stack to get the meter color for.
* @param value The current level of the meter.
* @return The color to use as an RGB value.
*/
int getColor(ItemStack stack, float value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2020 WovenMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.wovenmc.woven.api.item.settings;

import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;

/**
* An interface for dynamically handling recipe remainders.
*/
@FunctionalInterface
public interface RecipeRemainderHandler {
/**
* @param original The original item stack used in the recipe.
* @param recipeId The identifier of the original recipe. Hardcoded to {@code minecraft:brewing} for brewing and {@code minecraft:furnace_fuel} for furnace fuel.
* @return The item stack that should remain after crafting.
*/
ItemStack getRemainder(ItemStack original, Identifier recipeId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* Copyright (c) 2020 WovenMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.wovenmc.woven.api.item.settings;

import net.wovenmc.woven.mixin.item.settings.MixinItem;
import org.jetbrains.annotations.Nullable;

import net.minecraft.item.FoodComponent;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.util.Rarity;

/**
* An extension to {@link Item.Settings} providing additional hooks for items.
*/
public class WovenItemSettings extends Item.Settings {
repulica marked this conversation as resolved.
Show resolved Hide resolved
private MeterComponent meterComponent = null;
private RecipeRemainderHandler dynamicRecipeRemainder = null;
private EquipmentHandler equipmentHandler = null;
private boolean selfRemainder = false;

/**
* @param meterComponent The {@link MeterComponent} for this item.
* @return The item settings with the component added.
*/
public WovenItemSettings meter(MeterComponent meterComponent) {
this.meterComponent = meterComponent;
return this;
}

/**
* Incompatible with {@link WovenItemSettings#selfRemainder} and {@link WovenItemSettings#recipeRemainder(Item)}.
* @param remainder A handler for determining the remainder of an item stack when crafting dynamically.
* @return The item settings with the handler added.
*/
public WovenItemSettings recipeRemainder(RecipeRemainderHandler remainder) {
if (selfRemainder) {
throw new RuntimeException("Unable to have dynamic recipe remainder AND self recipe remainder.");
} else if (((MixinItem.ItemSettingsAccessor) this).getRecipeRemainder() != null) {
throw new RuntimeException("Unable to have dynamic recipe remainder AND static recipe remainder.");
} else {
this.dynamicRecipeRemainder = remainder;
return this;
}
}

/**
* Incompatible with {@link WovenItemSettings#recipeRemainder(RecipeRemainderHandler)} and {@link Item.Settings#recipeRemainder(Item)}.
* Flags an item to return itself as a recipe remainder without a dynamic remainder handler.
* @return The item settings with the flag set.
*/
public WovenItemSettings selfRemainder() {
if (dynamicRecipeRemainder != null) {
throw new RuntimeException("Unable to have self recipe remainder AND dynamic recipe remainder.");
} else if (((MixinItem.ItemSettingsAccessor) this).getRecipeRemainder() != null) {
throw new RuntimeException("Unable to have self recipe remainder AND static recipe remainder.");
} else {
this.selfRemainder = true;
return this;
}
}

/**
* @param equipmentHandler A handler for determining the equipment slot an item stack should go in.
* @return The item settings with the handler added.
*/
public WovenItemSettings equipmentHandler(EquipmentHandler equipmentHandler) {
this.equipmentHandler = equipmentHandler;
return this;
}

@Override
public WovenItemSettings group(ItemGroup group) {
super.group(group);
return this;
}

@Override
public WovenItemSettings rarity(Rarity rarity) {
super.rarity(rarity);
return this;
}

/**
* Incompatible with {@link WovenItemSettings#recipeRemainder(RecipeRemainderHandler)} and {@link WovenItemSettings#selfRemainder}.
*/
@Override
public WovenItemSettings recipeRemainder(Item recipeRemainder) {
if (dynamicRecipeRemainder != null) {
throw new RuntimeException("Unable to have static recipe remainder AND dynamic recipe remainder.");
} else if (selfRemainder) {
throw new RuntimeException("Unable to have static recipe remainder AND self recipe remainder.");
} else {
super.recipeRemainder(recipeRemainder);
return this;
}
}

@Override
public WovenItemSettings maxDamage(int maxDamage) {
super.maxDamage(maxDamage);
return this;
}

@Override
public WovenItemSettings maxDamageIfAbsent(int maxDamage) {
super.maxDamageIfAbsent(maxDamage);
return this;
}

@Override
public WovenItemSettings maxCount(int maxCount) {
super.maxCount(maxCount);
return this;
}

@Override
public WovenItemSettings food(FoodComponent foodComponent) {
super.food(foodComponent);
return this;
}

@Override
public WovenItemSettings fireproof() {
super.fireproof();
return this;
}

/**
* For internal use.
* @return The set meter component, or null if none was set.
*/
@Nullable
public MeterComponent getMeterComponent() {
return meterComponent;
}

/**
* For internal use.
* @return The set dynamic recipe remainder, or null if none was set.
*/
@Nullable
public RecipeRemainderHandler getRecipeRemainder() {
return dynamicRecipeRemainder;
}

/**
* For internal use.
* @return Whether the self-remainder flag was set.
*/
public boolean remainsSelf() {
return selfRemainder;
}

/**
* For internal use.
* @return The set equipment handler, or null if none was set
*/
@Nullable
public EquipmentHandler getEquipmentHandler() {
return equipmentHandler;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@

package net.wovenmc.woven.impl.item.settings;

import org.apache.logging.log4j.LogManager;
import net.wovenmc.woven.api.item.settings.EquipmentHandler;
import net.wovenmc.woven.api.item.settings.MeterComponent;
import net.wovenmc.woven.api.item.settings.RecipeRemainderHandler;
import org.jetbrains.annotations.Nullable;

import net.fabricmc.api.ModInitializer;
public interface WovenItemSettingsHolder {
@Nullable
MeterComponent woven$getMeterComponent();

public class TemplateModInitializer implements ModInitializer {
@Override
public void onInitialize() {
LogManager.getLogger("woven_module_template").info("Woven Module Template initialized.");
}
@Nullable
RecipeRemainderHandler woven$getDynamicRecipeRemainder();

@Nullable
EquipmentHandler woven$getEquipmentHandler();
}
Loading