Skip to content

Commit

Permalink
convert from accesstransformers to accessors and invokers
Browse files Browse the repository at this point in the history
  • Loading branch information
gottsch committed Dec 17, 2024
1 parent 773f117 commit 9f58c5d
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 63 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2024-12-16

### Changed

- Save any unused detla/elapsed time (remainingDeltaTime) to the next tick
in order to process against any inputted cook items, ie provided by hopper.
if none is found then remainingDeltaTime is reset to 0.
- Refactored to use Accessors and Invokers instead of accesstransformer.cfg
- Refactored to use mixin best practices to rename properties. this can cause a
one-time loss of elapsed time on first load of furnace.

### Added

- Saving new data -> remainingDeltaTime

## [1.0.1] - 2024-12-13

### Changed
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,6 @@ publishing {
}
}

loom {
accessWidenerPath = file("src/main/resources/everfurnace.accesswidener")
}
//loom {
// accessWidenerPath = file("src/main/resources/everfurnace.accesswidener")
//}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ yarn_mappings=1.21.4+build.1
loader_version=0.16.9

# Mod Properties
mod_version=1.0.1
mod_version=1.1.0
maven_group=gottsch
archives_base_name=everfurnace

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,31 @@
* Created by Mark Gottschling on 12/05/2024
*/
@Mixin(AbstractFurnaceBlockEntity.class)
public abstract class ModFurnaceBlockEntityMixin extends LockableContainerBlockEntity implements SidedInventory, RecipeUnlocker, RecipeInputProvider { //}, IModFurnaceBlockEntityMixin {
public abstract class EverFurnaceBlockEntity extends LockableContainerBlockEntity implements SidedInventory, RecipeUnlocker, RecipeInputProvider { //}, IModFurnaceBlockEntityMixin {
@Unique
private static final int INPUT_SLOT = 0;
@Unique
private static final int FUEL_SLOT = 1;
@Unique
private static final int OUTPUT_SLOT = 2;
@Unique
private static final String LAST_GAME_TIME_TAG = "everfurnace_lastGameTime";

@Unique
private long lastGameTime;
private long everfurnace$lastGameTime;

protected ModFurnaceBlockEntityMixin(BlockEntityType<?> blockEntityType, BlockPos blockPos, BlockState blockState) {
protected EverFurnaceBlockEntity(BlockEntityType<?> blockEntityType, BlockPos blockPos, BlockState blockState) {
super(blockEntityType, blockPos, blockState);
}

@Inject(method = "writeNbt", at = @At("TAIL"))
private void onSave(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup, CallbackInfo ci) {
nbt.putLong("lastGameTime", this.lastGameTime);
private void onSave(NbtCompound nbt, RegistryWrapper.WrapperLookup registries, CallbackInfo ci) {
nbt.putLong(LAST_GAME_TIME_TAG, getEverfurnace$lastGameTime());
}

@Inject(method = "readNbt", at = @At("TAIL"))
private void onLoad(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup, CallbackInfo ci) {
this.lastGameTime = nbt.getLong("lastGameTime");
private void onLoad(NbtCompound nbt, RegistryWrapper.WrapperLookup registries, CallbackInfo ci) {
setEverfurnace$lastGameTime(nbt.getLong(LAST_GAME_TIME_TAG));
}

/**
Expand All @@ -75,13 +83,14 @@ private void onLoad(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLooku
@Inject(method = "tick", at = @At("HEAD")) // target more specifically somewhere closer to the actual calculations?
private static void onTick(ServerWorld world, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity blockEntity, CallbackInfo ci) {
// cast block entity as a mixin block entity
ModFurnaceBlockEntityMixin blockEntityMixin = (ModFurnaceBlockEntityMixin)(Object) blockEntity;
EverFurnaceBlockEntity blockEntityMixin = (EverFurnaceBlockEntity)(Object) blockEntity;
IEverFurnaceBlockEntity everFurnaceBlockEntity = (IEverFurnaceBlockEntity) ((Object) blockEntity);

// record last world time
long localLastGameTime = blockEntityMixin.getLastGameTime();
blockEntityMixin.setLastGameTime(blockEntity.getWorld().getTime());
long localLastGameTime = blockEntityMixin.getEverfurnace$lastGameTime();
blockEntityMixin.setEverfurnace$lastGameTime(blockEntity.getWorld().getTime());

if (!blockEntity.isBurning()){
if (!everFurnaceBlockEntity.callIsBurning()){
return;
}

Expand All @@ -98,38 +107,40 @@ private static void onTick(ServerWorld world, BlockPos pos, BlockState state, Ab
* validations
* //////////////////////
*/
ItemStack cookStack = blockEntity.inventory.get(AbstractFurnaceBlockEntity.INPUT_SLOT_INDEX);
ItemStack cookStack = everFurnaceBlockEntity.getInventory().get(INPUT_SLOT);
if (cookStack.isEmpty()) return;

// get the output stack
ItemStack outputStack = blockEntity.inventory.get(AbstractFurnaceBlockEntity.OUTPUT_SLOT_INDEX);
ItemStack outputStack = everFurnaceBlockEntity.getInventory().get(OUTPUT_SLOT);
// return if it is already maxed out
if (!outputStack.isEmpty() && outputStack.getCount() == blockEntity.getMaxCountPerStack()) return;

// test if can accept recipe output
SingleStackRecipeInput singleStackRecipeInput = new SingleStackRecipeInput(cookStack);
RecipeEntry<? extends AbstractCookingRecipe> recipeEntry;
recipeEntry = (RecipeEntry)blockEntity.matchGetter.getFirstMatch(singleStackRecipeInput, world).orElse(null);
RecipeEntry recipeEntry;
recipeEntry = (RecipeEntry)everFurnaceBlockEntity.getMatchGetter().getFirstMatch(singleStackRecipeInput, world).orElse(null);

if (!AbstractFurnaceBlockEntity.canAcceptRecipeOutput(blockEntity.getWorld().getRegistryManager(), recipeEntry, singleStackRecipeInput, blockEntity.inventory, blockEntity.getMaxCountPerStack())) return;
if (!IEverFurnaceBlockEntity.callCanAcceptRecipeOutput(blockEntity.getWorld().getRegistryManager(), recipeEntry, singleStackRecipeInput, everFurnaceBlockEntity.getInventory(), blockEntity.getMaxCountPerStack())) return;
/////////////////////////

/*
* begin processing
*/
// calculate totalBurnTimeRemaining
ItemStack fuelStack = blockEntity.inventory.get(AbstractFurnaceBlockEntity.FUEL_SLOT_INDEX);
ItemStack fuelStack = everFurnaceBlockEntity.getInventory().get(FUEL_SLOT);
if (fuelStack.isEmpty()) return;

// have to calculate fuel time as it is no longer calculated during readNbt() as in 1.21.1
if (blockEntity.litTotalTime == 0) {
blockEntity.litTotalTime = blockEntity.getFuelTime(blockEntity.getWorld().getFuelRegistry(), fuelStack);
if (everFurnaceBlockEntity.getLitTotalTime() == 0) {
everFurnaceBlockEntity.setLitTotalTime(everFurnaceBlockEntity.callGetFuelTime(blockEntity.getWorld().getFuelRegistry(), fuelStack));
}

long totalBurnTimeRemaining = (long) (fuelStack.getCount() - 1) * blockEntity.litTotalTime + blockEntity.litTimeRemaining;
long totalBurnTimeRemaining = (long) (fuelStack.getCount() - 1) * everFurnaceBlockEntity.getLitTotalTime()
+ everFurnaceBlockEntity.getLitTimeRemaining();

// calculate totalCookTimeRemaining
long totalCookTimeRemaining = (long) (cookStack.getCount() -1) * blockEntity.cookingTotalTime + (blockEntity.cookingTotalTime - blockEntity.cookingTimeSpent);
long totalCookTimeRemaining = (long) (cookStack.getCount() -1) * everFurnaceBlockEntity.getCookingTotalTime()
+ (everFurnaceBlockEntity.getCookingTotalTime() - everFurnaceBlockEntity.getCookingTimeSpent());

// determine the max amount of time that can be used before one or both input run out.
long maxInputTime = Math.min(totalBurnTimeRemaining, totalCookTimeRemaining);
Expand All @@ -140,97 +151,105 @@ private static void onTick(ServerWorld world, BlockPos pos, BlockState state, Ab
*/
long actualAppliedTime = Math.min(deltaTime, maxInputTime);

if (actualAppliedTime < blockEntity.litTotalTime) {
if (actualAppliedTime < everFurnaceBlockEntity.getLitTotalTime()) {
// reduce burn time
blockEntity.litTimeRemaining =- (int) actualAppliedTime;
if (blockEntity.litTimeRemaining <= 0) {
everFurnaceBlockEntity.setLitTimeRemaining(everFurnaceBlockEntity.getLitTimeRemaining()
- (int) actualAppliedTime);

if (everFurnaceBlockEntity.getLitTimeRemaining() <= 0) {
Item fuelItem = fuelStack.getItem();
// reduce the size of the fuel stack
fuelStack.decrement(1);
if (fuelStack.isEmpty()) {
blockEntity.litTimeRemaining = 0;
blockEntity.inventory.set(1, fuelItem.getRecipeRemainder());
everFurnaceBlockEntity.setLitTimeRemaining(0);
everFurnaceBlockEntity.getInventory().set(1, fuelItem.getRecipeRemainder());
} else {
blockEntity.litTimeRemaining =+ blockEntity.litTotalTime;
everFurnaceBlockEntity.setLitTimeRemaining(everFurnaceBlockEntity.getLitTimeRemaining()
- everFurnaceBlockEntity.getLitTotalTime());
}
}
} else {
int quotient = (int) (Math.floorDivExact(actualAppliedTime, blockEntity.litTotalTime));
long remainder = actualAppliedTime % blockEntity.litTotalTime;
int quotient = (int) (Math.floorDivExact(actualAppliedTime, everFurnaceBlockEntity.getLitTotalTime()
));
long remainder = actualAppliedTime % everFurnaceBlockEntity.getLitTotalTime();
// reduced stack by quotient
Item fuelItem = fuelStack.getItem();
fuelStack.decrement(quotient);
// reduce litTimeRemaining by remainder
blockEntity.litTimeRemaining =- (int)remainder;
if (blockEntity.litTimeRemaining <= 0) {
everFurnaceBlockEntity.setLitTimeRemaining(everFurnaceBlockEntity.getLitTimeRemaining() - (int) remainder);
if (everFurnaceBlockEntity.getLitTimeRemaining() <= 0) {
// reduce the size of the fuel stack
fuelStack.decrement(1);
}
if (fuelStack.isEmpty()) {
blockEntity.litTimeRemaining = 0;
blockEntity.inventory.set(1, fuelItem.getRecipeRemainder());
everFurnaceBlockEntity.setLitTimeRemaining(0);
everFurnaceBlockEntity.getInventory().set(1, fuelItem.getRecipeRemainder());
} else {
blockEntity.litTimeRemaining =+ blockEntity.litTotalTime;
everFurnaceBlockEntity.setLitTimeRemaining(everFurnaceBlockEntity.getLitTimeRemaining() + everFurnaceBlockEntity.getLitTotalTime());
}
}

if (actualAppliedTime < blockEntity.cookingTotalTime) {
if (actualAppliedTime < everFurnaceBlockEntity.getCookingTotalTime()) {
// increment cook time
blockEntity.cookingTimeSpent =+ (int) actualAppliedTime;
if (blockEntity.cookingTimeSpent >= blockEntity.cookingTotalTime) {
if (AbstractFurnaceBlockEntity.craftRecipe(world.getRegistryManager(), recipeEntry, singleStackRecipeInput, blockEntity.inventory, blockEntity.getMaxCountPerStack())) {
everFurnaceBlockEntity.setCookingTimeSpent(everFurnaceBlockEntity.getCookingTimeSpent()
+ (int) actualAppliedTime);
if (everFurnaceBlockEntity.getCookingTimeSpent() >= everFurnaceBlockEntity.getCookingTotalTime()) {
if (IEverFurnaceBlockEntity.callCraftRecipe(world.getRegistryManager(), recipeEntry, singleStackRecipeInput, everFurnaceBlockEntity.getInventory(), blockEntity.getMaxCountPerStack())) {
blockEntity.setLastRecipe(recipeEntry);
}
if (cookStack.isEmpty()) {
blockEntity.cookingTimeSpent = 0;
blockEntity.cookingTotalTime = 0;
everFurnaceBlockEntity.setCookingTimeSpent(0);
everFurnaceBlockEntity.setCookingTotalTime(0);
} else {
blockEntity.cookingTotalTime -= blockEntity.cookingTotalTime;
everFurnaceBlockEntity.setCookingTimeSpent(everFurnaceBlockEntity.getCookingTimeSpent()
- everFurnaceBlockEntity.getCookingTotalTime());
}
}
}
// actual applied time is greated that cook time total,
// there, need to apply a factor of
else {
int quotient = (int) (Math.floorDivExact(actualAppliedTime, blockEntity.cookingTotalTime));
long remainder = actualAppliedTime % blockEntity.cookingTotalTime;
int quotient = (int) (Math.floorDivExact(actualAppliedTime, everFurnaceBlockEntity.getCookingTotalTime()));
long remainder = actualAppliedTime % everFurnaceBlockEntity.getCookingTotalTime();
// reduced stack by quotient
boolean isSuccessful = false;
for (int iterations = 0; iterations < quotient; iterations++) {
isSuccessful |= AbstractFurnaceBlockEntity.craftRecipe(world.getRegistryManager(), recipeEntry, singleStackRecipeInput, blockEntity.inventory, blockEntity.getMaxCountPerStack());
isSuccessful |= IEverFurnaceBlockEntity.callCraftRecipe(world.getRegistryManager(), recipeEntry, singleStackRecipeInput, everFurnaceBlockEntity.getInventory(), blockEntity.getMaxCountPerStack());
}
// update last recipe
if (isSuccessful) blockEntity.setLastRecipe(recipeEntry);

// increment cook time
blockEntity.cookingTimeSpent =+ (int) remainder;
if (blockEntity.cookingTimeSpent >= blockEntity.cookingTotalTime) {
if (AbstractFurnaceBlockEntity.craftRecipe(world.getRegistryManager(), recipeEntry, singleStackRecipeInput, blockEntity.inventory, blockEntity.getMaxCountPerStack())) {
everFurnaceBlockEntity.setCookingTimeSpent(everFurnaceBlockEntity.getCookingTimeSpent()
+ (int) remainder);
if (everFurnaceBlockEntity.getCookingTimeSpent() >= everFurnaceBlockEntity.getCookingTotalTime()) {
if (IEverFurnaceBlockEntity.callCraftRecipe(world.getRegistryManager(), recipeEntry, singleStackRecipeInput, everFurnaceBlockEntity.getInventory(), blockEntity.getMaxCountPerStack())) {
blockEntity.setLastRecipe(recipeEntry);
}
if (cookStack.isEmpty()) {
blockEntity.cookingTimeSpent = 0;
blockEntity.cookingTotalTime = 0;
everFurnaceBlockEntity.setCookingTimeSpent(0);
everFurnaceBlockEntity.setCookingTotalTime(0);
} else {
blockEntity.cookingTotalTime -= blockEntity.cookingTotalTime;
everFurnaceBlockEntity.setCookingTimeSpent(everFurnaceBlockEntity.getCookingTimeSpent()
- everFurnaceBlockEntity.getCookingTotalTime());
}
}
}

if(!blockEntity.isBurning()) {
state = state.with(AbstractFurnaceBlock.LIT, Boolean.valueOf(blockEntity.isBurning()));
if(!everFurnaceBlockEntity.callIsBurning()) {
state = state.with(AbstractFurnaceBlock.LIT, Boolean.valueOf(everFurnaceBlockEntity.callIsBurning()));
world.setBlockState(pos, state, Block.NOTIFY_ALL);
AbstractFurnaceBlockEntity.markDirty(world, pos, state);
}
}

@Unique
public long getLastGameTime() {
return this.lastGameTime;
public long getEverfurnace$lastGameTime() {
return this.everfurnace$lastGameTime;
}

@Unique
public void setLastGameTime(long gameTime) {
this.lastGameTime = gameTime;
public void setEverfurnace$lastGameTime(long gameTime) {
this.everfurnace$lastGameTime = gameTime;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* This file is part of EverFurnace.
* Copyright (c) 2024 Mark Gottschling (gottsch)
*
* EverFurnace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EverFurnace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with EverFurnace. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package mod.gottsch.fabric.everfurnace.core.mixin;

import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.item.FuelRegistry;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.AbstractCookingRecipe;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.ServerRecipeManager;
import net.minecraft.recipe.input.SingleStackRecipeInput;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.collection.DefaultedList;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;

/**
* Created by Mark Gottschling on 12/13/2024
*/
@Mixin(AbstractFurnaceBlockEntity.class)
public interface IEverFurnaceBlockEntity {

@Accessor
int getLitTimeRemaining();
@Accessor("litTimeRemaining")
public void setLitTimeRemaining(int litTimeRemaining);

@Accessor
int getLitTotalTime();
@Accessor("litTotalTime")
public void setLitTotalTime(int litTotalTime);

@Accessor
int getCookingTimeSpent();
@Accessor("cookingTimeSpent")
public void setCookingTimeSpent(int cookingTimeSpent);

@Accessor
int getCookingTotalTime();
@Accessor
public void setCookingTotalTime(int cookingTotalTime);

@Accessor
DefaultedList<ItemStack> getInventory();

@Accessor
ServerRecipeManager.MatchGetter<SingleStackRecipeInput, ? extends AbstractCookingRecipe> getMatchGetter();


@Invoker
public boolean callIsBurning();

// @Invoker
// public boolean callCanBurn(RegistryAccess pRecipe, @Nullable RecipeHolder<?> pInventory, NonNullList<ItemStack> pMaxStackSize, int p_155008_);

// @Invoker
// public boolean callBurn(RegistryAccess pRecipe, @Nullable RecipeHolder<?> pInventory, NonNullList<ItemStack> pMaxStackSize, int p_267157_);

@Invoker
public int callGetFuelTime(FuelRegistry fuelRegistry, ItemStack stack);

@Invoker
public static boolean callCraftRecipe(DynamicRegistryManager dynamicRegistryManager, @Nullable RecipeEntry<? extends AbstractCookingRecipe> recipe, SingleStackRecipeInput input, DefaultedList<ItemStack> inventory, int maxCount) {
throw new AssertionError();
}

@Invoker
public static boolean callCanAcceptRecipeOutput(DynamicRegistryManager dynamicRegistryManager, @Nullable RecipeEntry<? extends AbstractCookingRecipe> recipe, SingleStackRecipeInput input, DefaultedList<ItemStack> inventory, int maxCount) {
throw new AssertionError();
}
}
Loading

0 comments on commit 9f58c5d

Please sign in to comment.