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
108 changes: 108 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,108 @@
/*
* 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 java.util.function.BiFunction;
import java.util.function.Function;

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 Function<ItemStack, Float> levelFunc;
private final BiFunction<ItemStack, Float, Integer> colorFunc;
private final boolean displayAtFull;

private MeterComponent(Function<ItemStack, Float> levelFunc, BiFunction<ItemStack, Float, Integer> colorFunc,
boolean displayAtFull) {
this.levelFunc = levelFunc;
this.colorFunc = colorFunc;
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 levelFunc.apply(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 colorFunc.apply(stack, levelFunc.apply(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 Function<ItemStack, Float> levelFunc = stack ->
(stack.getMaxDamage() - stack.getDamage()) / (float) stack.getMaxDamage();
private BiFunction<ItemStack, Float, Integer> colorFunc = (stack, level) ->
MathHelper.hsvToRgb(levelFunc.apply(stack) / 3F, 1F, 1F);
private boolean displayAtFull = false;

/**
* @param function The function for getting the current level of a meter.
* @return The builder with the function set.
*/
public Builder levelFunction(Function<ItemStack, Float> function) {
this.levelFunc = function;
return this;
}

/**
* @param function The function for getting the current color of a meter.
* @return The builder with the function set.
*/
public Builder colorFunction(BiFunction<ItemStack, Float, Integer> function) {
this.colorFunc = function;
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(levelFunc, colorFunc, displayAtFull);
}
}
}
25 changes: 0 additions & 25 deletions src/main/java/net/wovenmc/woven/api/item/settings/TemplateAPI.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* 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 java.util.function.BiFunction;
import java.util.function.Function;

import org.jetbrains.annotations.Nullable;

import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
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 BiFunction<ItemStack, Identifier, ItemStack> dynamicRecipeRemainder = null;
private Function<ItemStack, EquipmentSlot> equipmentHandler = null;

/**
* @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;
}

/**
* @param remainder A function for determining the remainder of an item stack when crafting dynamically.
* @return The item settings with the function added.
*/
public WovenItemSettings dynamicRecipeRemainder(BiFunction<ItemStack, Identifier, ItemStack> remainder) {
repulica marked this conversation as resolved.
Show resolved Hide resolved
this.dynamicRecipeRemainder = remainder;
return this;
}

/**
* @param equipmentHandler A function for determining the equipment slot an item stack should go in.
* @return The item settings with the function added.
*/
public WovenItemSettings equipmentHandler(Function<ItemStack, EquipmentSlot> 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;
}

@Override
public WovenItemSettings recipeRemainder(Item recipeRemainder) {
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 BiFunction<ItemStack, Identifier, ItemStack> getDynamicRecipeRemainder() {
return dynamicRecipeRemainder;
}

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

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

import org.apache.logging.log4j.LogManager;
import java.util.function.BiFunction;
import java.util.function.Function;

import net.fabricmc.api.ModInitializer;
import net.wovenmc.woven.api.item.settings.MeterComponent;
import org.jetbrains.annotations.Nullable;

public class TemplateModInitializer implements ModInitializer {
@Override
public void onInitialize() {
LogManager.getLogger("woven_module_template").info("Woven Module Template initialized.");
}
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;

public interface WovenItemSettingsHolder {
@Nullable
MeterComponent woven$getMeterComponent();

@Nullable
BiFunction<ItemStack, Identifier, ItemStack> woven$getDynamicRecipeRemainder();

@Nullable
Function<ItemStack, EquipmentSlot> woven$getEquipmentHandler();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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.mixin.item.settings;

import net.wovenmc.woven.api.item.settings.WovenItemSettings;
import net.wovenmc.woven.impl.item.settings.WovenItemSettingsHolder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.recipe.Recipe;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.registry.Registry;

@Mixin(AbstractFurnaceBlockEntity.class)
public abstract class MixinAbstractFurnaceBlockEntity {
@Shadow
protected DefaultedList<ItemStack> inventory;
private static final Identifier FUEL_ID = new Identifier("furnace_fuel");
private final ThreadLocal<ItemStack> stack = new ThreadLocal<>();

@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getRecipeRemainder()Lnet/minecraft/item/Item;"),
locals = LocalCapture.CAPTURE_FAILEXCEPTION)
private void grabLocalStack(CallbackInfo info, boolean isBurning, boolean isCooking, ItemStack cookingStack, Recipe<?> recipe) {
stack.set(cookingStack);
}

@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getRecipeRemainder()Lnet/minecraft/item/Item;"))
private Item hackCustomFuelRemainder(Item origItem) {
WovenItemSettingsHolder holder = (WovenItemSettingsHolder) origItem;
System.out.println(Registry.ITEM.getId(origItem));
repulica marked this conversation as resolved.
Show resolved Hide resolved

if (holder.woven$getDynamicRecipeRemainder() != null) {
return Items.COAL;
repulica marked this conversation as resolved.
Show resolved Hide resolved
}

return origItem.getRecipeRemainder();
}

@Redirect(method = "tick", at = @At(value = "NEW", target = "net/minecraft/item/ItemStack"))
private ItemStack getNewFuelRemainder(ItemConvertible origItem) {
WovenItemSettingsHolder holder = (WovenItemSettingsHolder) origItem;

if (holder.woven$getDynamicRecipeRemainder() != null) {
return holder.woven$getDynamicRecipeRemainder().apply(stack.get(), FUEL_ID);
}

return new ItemStack(origItem);
}

@Inject(method = "craftRecipe", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;decrement(I)V"),
cancellable = true, locals = LocalCapture.CAPTURE_FAILEXCEPTION)
private void injectSmeltRemainder(Recipe<?> recipe, CallbackInfo info, ItemStack inStack) {
WovenItemSettingsHolder woven = (WovenItemSettingsHolder) inStack.getItem();
if (woven.woven$getDynamicRecipeRemainder() != null) {
repulica marked this conversation as resolved.
Show resolved Hide resolved
ItemStack newStack = woven.woven$getDynamicRecipeRemainder().apply(inStack, recipe.getId());
if (!newStack.isEmpty()) {
this.inventory.set(0, newStack);
info.cancel();
}
}
}
}
Loading