Skip to content

Commit

Permalink
Fix #967 Fix graphical issues with recipe animations
Browse files Browse the repository at this point in the history
  • Loading branch information
mezz committed Aug 3, 2017
1 parent 3452328 commit a828497
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 45 deletions.
34 changes: 15 additions & 19 deletions src/main/java/mezz/jei/gui/TickTimer.java
@@ -1,42 +1,38 @@
package mezz.jei.gui;

import mezz.jei.api.gui.ITickTimer;
import net.minecraft.client.Minecraft;

public class TickTimer implements ITickTimer {
private final int ticksPerCycle;
private final int msPerCycle;
private final int maxValue;
private final boolean countDown;

private long lastUpdateWorldTime = 0;
private int tickCount = 0;
private final long startTime;

public TickTimer(int ticksPerCycle, int maxValue, boolean countDown) {
this.ticksPerCycle = ticksPerCycle;
this.msPerCycle = ticksPerCycle * 50;
this.maxValue = maxValue;
this.countDown = countDown;
this.startTime = System.currentTimeMillis();
}

@Override
public int getValue() {
long worldTime = Minecraft.getMinecraft().world.getTotalWorldTime();
long ticksPassed = worldTime - lastUpdateWorldTime;
lastUpdateWorldTime = worldTime;
tickCount += ticksPassed;
if (tickCount >= ticksPerCycle) {
tickCount = 0;
}
long currentTime = System.currentTimeMillis();
return getValue(startTime, currentTime, maxValue, msPerCycle, countDown);
}

int value = Math.round(tickCount * maxValue / (float) ticksPerCycle);
@Override
public int getMaxValue() {
return maxValue;
}

public static int getValue(long startTime, long currentTime, int maxValue, int msPerCycle, boolean countDown) {
long msPassed = (currentTime - startTime) % msPerCycle;
int value = (int) Math.floorDiv(msPassed * (maxValue + 1), msPerCycle);
if (countDown) {
return maxValue - value;
} else {
return value;
}
}

@Override
public int getMaxValue() {
return maxValue;
}
}
Expand Up @@ -6,10 +6,12 @@
import mezz.jei.api.gui.IDrawableStatic;
import mezz.jei.api.gui.IGuiItemStackGroup;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ITickTimer;
import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.IRecipeCategory;
import mezz.jei.api.recipe.VanillaRecipeCategoryUid;
import mezz.jei.config.Constants;
import mezz.jei.gui.elements.DrawableAnimated;
import mezz.jei.util.Translator;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
Expand All @@ -31,14 +33,15 @@ public class BrewingRecipeCategory implements IRecipeCategory<BrewingRecipeWrapp

public BrewingRecipeCategory(IGuiHelper guiHelper) {
ResourceLocation location = Constants.RECIPE_GUI_VANILLA;
background = guiHelper.createDrawable(location, 0, 0, 64, 60, 0, 0, 0, 40);
background = guiHelper.createDrawable(location, 0, 0, 64, 60, 1, 0, 0, 40);
localizedName = Translator.translateToLocal("gui.jei.category.brewing");

IDrawableStatic brewArrowDrawable = guiHelper.createDrawable(location, 64, 0, 9, 28);
arrow = guiHelper.createAnimatedDrawable(brewArrowDrawable, 400, IDrawableAnimated.StartDirection.TOP, false);

IDrawableStatic brewBubblesDrawable = guiHelper.createDrawable(location, 73, 1, 12, 28);
bubbles = guiHelper.createAnimatedDrawable(brewBubblesDrawable, 20, IDrawableAnimated.StartDirection.BOTTOM, false);
IDrawableStatic brewBubblesDrawable = guiHelper.createDrawable(location, 73, 0, 12, 29);
ITickTimer bubblesTickTimer = new BrewingBubblesTickTimer(guiHelper);
bubbles = new DrawableAnimated(brewBubblesDrawable, bubblesTickTimer, IDrawableAnimated.StartDirection.BOTTOM);

blazeHeat = guiHelper.createDrawable(location, 64, 29, 18, 4);

Expand Down Expand Up @@ -67,23 +70,46 @@ public IDrawable getBackground() {

@Override
public void drawExtras(Minecraft minecraft) {
blazeHeat.draw(minecraft, 5, 29);
blazeHeat.draw(minecraft, 5, 30);
bubbles.draw(minecraft, 8, 0);
arrow.draw(minecraft, 42, 1);
arrow.draw(minecraft, 42, 2);
}

@Override
public void setRecipe(IRecipeLayout recipeLayout, BrewingRecipeWrapper recipeWrapper, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();

itemStacks.init(brewPotionSlot1, true, 0, 35);
itemStacks.init(brewPotionSlot2, true, 23, 42);
itemStacks.init(brewPotionSlot3, true, 46, 35);
itemStacks.init(brewIngredientSlot, true, 23, 1);
itemStacks.init(outputSlot, false, 80, 1);
itemStacks.init(brewPotionSlot1, true, 0, 36);
itemStacks.init(brewPotionSlot2, true, 23, 43);
itemStacks.init(brewPotionSlot3, true, 46, 36);
itemStacks.init(brewIngredientSlot, true, 23, 2);
itemStacks.init(outputSlot, false, 80, 2);

itemStacks.setBackground(outputSlot, slotDrawable);

itemStacks.set(ingredients);
}

private static class BrewingBubblesTickTimer implements ITickTimer {
/**
* Similar to {@link net.minecraft.client.gui.inventory.GuiBrewingStand#BUBBLELENGTHS}
*/
private static final int[] BUBBLE_LENGTHS = new int[]{29, 23, 18, 13, 9, 5, 0};
private final ITickTimer internalTimer;

public BrewingBubblesTickTimer(IGuiHelper guiHelper) {
this.internalTimer = guiHelper.createTickTimer(14, BUBBLE_LENGTHS.length - 1, false);
}

@Override
public int getValue() {
int timerValue = this.internalTimer.getValue();
return BUBBLE_LENGTHS[timerValue];
}

@Override
public int getMaxValue() {
return BUBBLE_LENGTHS[0];
}
}
}
19 changes: 9 additions & 10 deletions src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipe.java
@@ -1,12 +1,5 @@
package mezz.jei.plugins.vanilla.furnace;

import java.awt.Color;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import mezz.jei.api.IGuiHelper;
import mezz.jei.api.gui.IDrawableAnimated;
import mezz.jei.api.gui.IDrawableStatic;
Expand All @@ -16,7 +9,13 @@
import mezz.jei.util.Translator;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;

import java.awt.Color;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class FuelRecipe implements IRecipeWrapper {
private final List<List<ItemStack>> inputs;
Expand All @@ -39,7 +38,7 @@ public FuelRecipe(IGuiHelper guiHelper, Collection<ItemStack> input, int burnTim

this.burnTimeString = Translator.translateToLocalFormatted("gui.jei.category.fuel.burnTime", burnTime);

IDrawableStatic flameDrawable = guiHelper.createDrawable(Constants.RECIPE_GUI_VANILLA, 176, 114, 14, 14);
IDrawableStatic flameDrawable = guiHelper.createDrawable(Constants.RECIPE_GUI_VANILLA, 82, 114, 14, 14);
this.flame = guiHelper.createAnimatedDrawable(flameDrawable, burnTime, IDrawableAnimated.StartDirection.TOP, true);
}

Expand All @@ -50,7 +49,7 @@ public void getIngredients(IIngredients ingredients) {

@Override
public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) {
flame.draw(minecraft, 2, 0);
flame.draw(minecraft, 1, 0);
minecraft.fontRenderer.drawString(smeltCountString, 24, 8, Color.gray.getRGB());
minecraft.fontRenderer.drawString(burnTimeString, 24, 18, Color.gray.getRGB());
}
Expand Down
@@ -1,7 +1,5 @@
package mezz.jei.plugins.vanilla.furnace;

import javax.annotation.Nullable;

import mezz.jei.api.IGuiHelper;
import mezz.jei.api.gui.IDrawable;
import mezz.jei.api.gui.IDrawableStatic;
Expand All @@ -12,14 +10,16 @@
import mezz.jei.config.Constants;
import mezz.jei.util.Translator;

import javax.annotation.Nullable;

public class FurnaceFuelCategory extends FurnaceRecipeCategory<FuelRecipe> {
private final IDrawableStatic background;
private final IDrawableStatic flameTransparentBackground;
private final String localizedName;

public FurnaceFuelCategory(IGuiHelper guiHelper) {
super(guiHelper);
background = guiHelper.createDrawable(Constants.RECIPE_GUI_VANILLA, 0, 135, 18, 33, 0, 0, 0, 80);
background = guiHelper.createDrawable(Constants.RECIPE_GUI_VANILLA, 0, 134, 18, 34, 0, 0, 0, 80);

flameTransparentBackground = guiHelper.createDrawable(Constants.RECIPE_BACKGROUND, 215, 0, 14, 14);
localizedName = Translator.translateToLocal("gui.jei.category.fuel");
Expand Down Expand Up @@ -55,7 +55,7 @@ public IDrawable getIcon() {
public void setRecipe(IRecipeLayout recipeLayout, FuelRecipe recipeWrapper, IIngredients ingredients) {
IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks();

guiItemStacks.init(fuelSlot, true, 0, 15);
guiItemStacks.init(fuelSlot, true, 0, 16);
guiItemStacks.set(ingredients);
}
}
Expand Up @@ -20,7 +20,7 @@ public FurnaceRecipeCategory(IGuiHelper guiHelper) {
staticFlame = guiHelper.createDrawable(Constants.RECIPE_GUI_VANILLA, 82, 114, 14, 14);
animatedFlame = guiHelper.createAnimatedDrawable(staticFlame, 300, IDrawableAnimated.StartDirection.TOP, true);

IDrawableStatic arrowDrawable = guiHelper.createDrawable(Constants.RECIPE_GUI_VANILLA, 176, 128, 24, 17);
IDrawableStatic arrowDrawable = guiHelper.createDrawable(Constants.RECIPE_GUI_VANILLA, 82, 128, 24, 17);
this.arrow = guiHelper.createAnimatedDrawable(arrowDrawable, 200, IDrawableAnimated.StartDirection.LEFT, false);
}
}
Expand Up @@ -27,7 +27,7 @@ public IDrawable getBackground() {

@Override
public void drawExtras(Minecraft minecraft) {
animatedFlame.draw(minecraft, 2, 20);
animatedFlame.draw(minecraft, 1, 20);
arrow.draw(minecraft, 24, 18);
}

Expand Down
54 changes: 54 additions & 0 deletions src/test/java/mezz/jei/test/TickTimerTest.java
@@ -0,0 +1,54 @@
package mezz.jei.test;

import mezz.jei.gui.TickTimer;
import org.junit.Assert;
import org.junit.Test;

public class TickTimerTest {
@Test
public void testBasicTickTimerMath() {
int maxValue = 1000;
int msPerCycle = 20;
for (int i = 0; i < 1000; i++) {
int expectedValue = (i % msPerCycle) * 50;
int value = TickTimer.getValue(0, i, maxValue, msPerCycle, false);
Assert.assertEquals(expectedValue, value);

int expectedDownValue = maxValue - expectedValue;
int downValue = TickTimer.getValue(0, i, maxValue, msPerCycle, true);
Assert.assertEquals(expectedDownValue, downValue);
}
}

@Test
public void testMoreTicksThanValuesMath() {
int maxValue = 4;
int msPerCycle = 20;
int[] expectedValues = new int[] {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};
for (int i = 0; i < 1000; i++) {
int expectedValue = expectedValues[i % msPerCycle];
int value = TickTimer.getValue(0, i, maxValue, msPerCycle, false);
Assert.assertEquals(expectedValue, value);

int expectedDownValue = maxValue - expectedValue;
int downValue = TickTimer.getValue(0, i, maxValue, msPerCycle, true);
Assert.assertEquals(expectedDownValue, downValue);
}
}

@Test
public void testIndivisibleTicking() {
int maxValue = 3;
int msPerCycle = 10;
int[] expectedValues = new int[] {0, 0, 0, 1, 1, 2, 2, 2, 3, 3};
for (int i = 0; i < 1000; i++) {
int expectedValue = expectedValues[i % msPerCycle];
int value = TickTimer.getValue(0, i, maxValue, msPerCycle, false);
Assert.assertEquals(expectedValue, value);

int expectedDownValue = maxValue - expectedValue;
int downValue = TickTimer.getValue(0, i, maxValue, msPerCycle, true);
Assert.assertEquals(expectedDownValue, downValue);
}
}
}

0 comments on commit a828497

Please sign in to comment.