Applied-Energistics-2-tiler.../src/main/java/appeng/integration/modules/CraftGuide.java
LordMZTE f67fb6a129
Some checks failed
continuous-integration/drone/push Build is failing
chore: format code
2022-12-02 17:40:47 +01:00

500 lines
19 KiB
Java

/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 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.
*
* Applied Energistics 2 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 Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
import appeng.api.AEApi;
import appeng.api.IAppEngApi;
import appeng.api.definitions.IBlocks;
import appeng.api.exceptions.MissingIngredientError;
import appeng.api.exceptions.RegistrationError;
import appeng.api.features.IGrinderEntry;
import appeng.api.features.IInscriberRecipe;
import appeng.api.recipes.IIngredient;
import appeng.helpers.Reflected;
import appeng.integration.IIntegrationModule;
import appeng.integration.IntegrationHelper;
import appeng.recipes.game.ShapedRecipe;
import appeng.recipes.game.ShapelessRecipe;
import com.google.common.base.Optional;
import cpw.mods.fml.relauncher.ReflectionHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import uristqwerty.CraftGuide.CraftGuideLog;
import uristqwerty.CraftGuide.DefaultRecipeTemplate;
import uristqwerty.CraftGuide.RecipeGeneratorImplementation;
import uristqwerty.CraftGuide.api.*;
import uristqwerty.gui_craftguide.texture.DynamicTexture;
import uristqwerty.gui_craftguide.texture.TextureClip;
public final class CraftGuide
extends CraftGuideAPIObject implements IIntegrationModule, RecipeProvider {
private static final int SLOT_SIZE = 16;
private static final int TEXTURE_WIDTH = 79;
private static final int TEXTURE_HEIGHT = 58;
private static final int GRINDER_RATIO = 10000;
private static final Slot[] GRINDER_SLOTS = {
new ItemSlot(3, 21, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(41, 21, SLOT_SIZE, SLOT_SIZE, true)
.drawOwnBackground()
.setSlotType(SlotType.OUTPUT_SLOT),
new ChanceSlot(59, 12, SLOT_SIZE, SLOT_SIZE, true)
.setRatio(GRINDER_RATIO)
.setFormatString(" (%1$.2f%% chance)")
.drawOwnBackground()
.setSlotType(SlotType.OUTPUT_SLOT),
new ChanceSlot(59, 30, SLOT_SIZE, SLOT_SIZE, true)
.setRatio(GRINDER_RATIO)
.setFormatString(" (%1$.2f%% chance)")
.drawOwnBackground()
.setSlotType(SlotType.OUTPUT_SLOT),
new ItemSlot(22, 12, SLOT_SIZE, SLOT_SIZE).setSlotType(SlotType.MACHINE_SLOT),
new ItemSlot(22, 30, SLOT_SIZE, SLOT_SIZE).setSlotType(SlotType.MACHINE_SLOT)
};
private static final Slot[] INSCRIBER_SLOTS = {
new ItemSlot(12, 21, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(21, 3, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(21, 39, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(50, 21, SLOT_SIZE, SLOT_SIZE, true)
.drawOwnBackground()
.setSlotType(SlotType.OUTPUT_SLOT),
new ItemSlot(31, 21, SLOT_SIZE, SLOT_SIZE).setSlotType(SlotType.MACHINE_SLOT)
};
private static final Slot[] SHAPELESS_CRAFTING_SLOTS = {
new ItemSlot(3, 3, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(21, 3, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(39, 3, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(3, 21, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(21, 21, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(39, 21, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(3, 39, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(21, 39, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(39, 39, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(59, 21, SLOT_SIZE, SLOT_SIZE, true)
.setSlotType(SlotType.OUTPUT_SLOT),
};
private static final Slot[] CRAFTING_SLOTS_OWN_BG = {
new ItemSlot(3, 3, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(21, 3, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(39, 3, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(3, 21, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(21, 21, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(39, 21, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(3, 39, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(21, 39, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(39, 39, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(59, 21, SLOT_SIZE, SLOT_SIZE, true)
.setSlotType(SlotType.OUTPUT_SLOT)
.drawOwnBackground(),
};
private static final Slot[] SMALL_CRAFTING_SLOTS_OWN_BG = {
new ItemSlot(12, 12, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(30, 12, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(12, 30, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(30, 30, SLOT_SIZE, SLOT_SIZE).drawOwnBackground(),
new ItemSlot(59, 21, SLOT_SIZE, SLOT_SIZE, true)
.setSlotType(SlotType.OUTPUT_SLOT)
.drawOwnBackground(),
};
private static final Slot[] CRTAFTING_SLOTS = {
new ItemSlot(3, 3, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(21, 3, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(39, 3, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(3, 21, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(21, 21, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(39, 21, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(3, 39, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(21, 39, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(39, 39, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(59, 21, SLOT_SIZE, SLOT_SIZE, true)
.setSlotType(SlotType.OUTPUT_SLOT),
};
private static final Slot[] SMALL_CRAFTING_SLOTS = {
new ItemSlot(12, 12, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(30, 12, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(12, 30, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(30, 30, SLOT_SIZE, SLOT_SIZE),
new ItemSlot(59, 21, SLOT_SIZE, SLOT_SIZE, true)
.setSlotType(SlotType.OUTPUT_SLOT),
};
@Reflected
public static CraftGuide instance;
public CraftGuide() {
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.CraftGuideLog.class);
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.DefaultRecipeTemplate.class);
IntegrationHelper.testClassExistence(
this, uristqwerty.CraftGuide.RecipeGeneratorImplementation.class
);
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.api.ChanceSlot.class);
IntegrationHelper.testClassExistence(
this, uristqwerty.CraftGuide.api.CraftGuideAPIObject.class
);
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.api.ItemSlot.class);
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.api.RecipeGenerator.class);
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.api.RecipeProvider.class);
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.api.RecipeTemplate.class);
IntegrationHelper.testClassExistence(this, uristqwerty.CraftGuide.api.Slot.class);
IntegrationHelper
.testClassExistence(this, uristqwerty.CraftGuide.api.SlotType.class);
IntegrationHelper.testClassExistence(
this, uristqwerty.gui_craftguide.texture.DynamicTexture.class
);
IntegrationHelper.testClassExistence(
this, uristqwerty.gui_craftguide.texture.TextureClip.class
);
}
@Override
public void init() throws Throwable {}
@Override
public void postInit() {}
@Override
public void generateRecipes(final RecipeGenerator generator) {
final RecipeTemplate craftingTemplate;
final RecipeTemplate smallTemplate;
if (uristqwerty.CraftGuide.CraftGuide.newerBackgroundStyle) {
craftingTemplate
= generator.createRecipeTemplate(CRAFTING_SLOTS_OWN_BG, null);
smallTemplate
= generator.createRecipeTemplate(SMALL_CRAFTING_SLOTS_OWN_BG, null);
} else {
final TextureClip craftingBG = new TextureClip(
DynamicTexture.instance("recipe_backgrounds"),
1,
1,
TEXTURE_WIDTH,
TEXTURE_HEIGHT
);
final TextureClip craftingSelected = new TextureClip(
DynamicTexture.instance("recipe_backgrounds"),
82,
1,
TEXTURE_WIDTH,
TEXTURE_HEIGHT
);
craftingTemplate = new DefaultRecipeTemplate(
CRTAFTING_SLOTS,
RecipeGeneratorImplementation.workbench,
craftingBG,
craftingSelected
);
final TextureClip smallBG = new TextureClip(
DynamicTexture.instance("recipe_backgrounds"),
1,
61,
TEXTURE_WIDTH,
TEXTURE_HEIGHT
);
final TextureClip smallSelected = new TextureClip(
DynamicTexture.instance("recipe_backgrounds"),
82,
61,
TEXTURE_WIDTH,
TEXTURE_HEIGHT
);
smallTemplate = new DefaultRecipeTemplate(
SMALL_CRAFTING_SLOTS,
RecipeGeneratorImplementation.workbench,
smallBG,
smallSelected
);
}
final TextureClip shapelessBG = new TextureClip(
DynamicTexture.instance("recipe_backgrounds"),
1,
121,
TEXTURE_WIDTH,
TEXTURE_HEIGHT
);
final TextureClip shapelessSelected = new TextureClip(
DynamicTexture.instance("recipe_backgrounds"),
82,
121,
TEXTURE_WIDTH,
TEXTURE_HEIGHT
);
final RecipeTemplate shapelessTemplate = new DefaultRecipeTemplate(
SHAPELESS_CRAFTING_SLOTS,
RecipeGeneratorImplementation.workbench,
shapelessBG,
shapelessSelected
);
this.addCraftingRecipes(
craftingTemplate, smallTemplate, shapelessTemplate, generator
);
final IAppEngApi api = AEApi.instance();
final IBlocks aeBlocks = api.definitions().blocks();
final Optional<ItemStack> grindstone = aeBlocks.grindStone().maybeStack(1);
final Optional<ItemStack> inscriber = aeBlocks.inscriber().maybeStack(1);
if (grindstone.isPresent()) {
this.addGrinderRecipes(api, grindstone.get(), generator);
}
if (inscriber.isPresent()) {
this.addInscriberRecipes(api, inscriber.get(), generator);
}
}
@SuppressWarnings("unchecked")
private List<IRecipe> getUncheckedRecipes() {
return (List<IRecipe>) CraftingManager.getInstance().getRecipeList();
}
private void addCraftingRecipes(
final RecipeTemplate template,
final RecipeTemplate templateSmall,
final RecipeTemplate templateShapeless,
final RecipeGenerator generator
) {
final List<IRecipe> recipes = this.getUncheckedRecipes();
int errCount = 0;
for (final IRecipe recipe : recipes) {
try {
final Object[] items = this.getCraftingRecipe(recipe, true);
if (items == null) {
continue;
}
if (items.length == 5) {
generator.addRecipe(templateSmall, items);
} else if (recipe instanceof ShapelessRecipe) {
generator.addRecipe(templateShapeless, items);
} else {
generator.addRecipe(template, items);
}
} catch (final Exception e) {
if (errCount >= 5) {
CraftGuideLog.log(
"AppEng CraftGuide integration: Stack trace limit reached, further stack traces from this invocation will not be logged to the console. They will still be logged to (.minecraft)/config/CraftGuide/CraftGuide.log",
true
);
} else {
e.printStackTrace();
}
errCount++;
CraftGuideLog.log(e);
}
}
}
private void addGrinderRecipes(
final IAppEngApi api, final ItemStack grindstone, final RecipeGenerator generator
) {
final ItemStack handle
= api.definitions().blocks().crankHandle().maybeStack(1).orNull();
final RecipeTemplate grinderTemplate
= generator.createRecipeTemplate(GRINDER_SLOTS, grindstone);
for (final IGrinderEntry recipe : api.registries().grinder().getRecipes()) {
generator.addRecipe(
grinderTemplate,
new Object[] {
recipe.getInput(),
recipe.getOutput(),
new Object[] { recipe.getOptionalOutput(),
(int) (recipe.getOptionalChance() * GRINDER_RATIO) },
new Object[] { recipe.getSecondOptionalOutput(),
(int) (recipe.getOptionalChance() * GRINDER_RATIO) },
handle,
grindstone }
);
}
}
private void addInscriberRecipes(
final IAppEngApi api, final ItemStack inscriber, final RecipeGenerator generator
) {
final RecipeTemplate inscriberTemplate
= generator.createRecipeTemplate(INSCRIBER_SLOTS, inscriber);
for (final IInscriberRecipe recipe : api.registries().inscriber().getRecipes()) {
generator.addRecipe(
inscriberTemplate,
new Object[] { recipe.getInputs(),
recipe.getTopOptional().orNull(),
recipe.getBottomOptional().orNull(),
recipe.getOutput(),
inscriber }
);
}
}
private Object[] getCraftingShapelessRecipe(
final List<?> items, final ItemStack recipeOutput
) {
final Object[] output = new Object[10];
for (int i = 0; i < items.size(); i++) {
output[i] = items.get(i);
if (output[i] instanceof ItemStack[]) {
output[i] = Arrays.asList((ItemStack[]) output[i]);
}
if (output[i] instanceof IIngredient) {
try {
output[i] = this.toCG(((IIngredient) output[i]).getItemStackSet());
} catch (final RegistrationError ignored) {
} catch (final MissingIngredientError ignored) {}
}
}
output[9] = recipeOutput;
return output;
}
private Object[] getSmallShapedRecipe(
final int width,
final int height,
final Object[] items,
final ItemStack recipeOutput
) {
final Object[] output = new Object[5];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
final int i = y * 2 + x;
output[i] = items[y * width + x];
if (output[i] instanceof ItemStack[]) {
output[i] = Arrays.asList((ItemStack[]) output[i]);
}
if (output[i] instanceof IIngredient) {
try {
output[i]
= this.toCG(((IIngredient) output[i]).getItemStackSet());
} catch (final RegistrationError ignored) {
} catch (final MissingIngredientError ignored) {}
}
}
}
output[4] = recipeOutput;
return output;
}
private Object[] getCraftingShapedRecipe(
final int width,
final int height,
final Object[] items,
final ItemStack recipeOutput
) {
final Object[] output = new Object[10];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
final int i = y * 3 + x;
output[i] = items[y * width + x];
if (output[i] instanceof ItemStack[]) {
output[i] = Arrays.asList((ItemStack[]) output[i]);
}
if (output[i] instanceof IIngredient) {
try {
output[i]
= this.toCG(((IIngredient) output[i]).getItemStackSet());
} catch (final RegistrationError ignored) {
} catch (final MissingIngredientError ignored) {}
}
}
}
output[9] = recipeOutput;
return output;
}
private Object toCG(final ItemStack[] itemStackSet) {
final List<ItemStack> list = Arrays.asList(itemStackSet);
for (int x = 0; x < list.size(); x++) {
list.set(x, list.get(x).copy());
if (list.get(x).stackSize == 0) {
list.get(x).stackSize = 1;
}
}
return list;
}
@Nullable
private Object[] getCraftingRecipe(
final IRecipe recipe, final boolean allowSmallGrid
) {
if (recipe instanceof ShapelessRecipe) {
final List<Object> items = ReflectionHelper.getPrivateValue(
ShapelessRecipe.class, (ShapelessRecipe) recipe, "input"
);
return this.getCraftingShapelessRecipe(items, recipe.getRecipeOutput());
} else if (recipe instanceof ShapedRecipe) {
final int width = ReflectionHelper.getPrivateValue(
ShapedRecipe.class, (ShapedRecipe) recipe, "width"
);
final int height = ReflectionHelper.getPrivateValue(
ShapedRecipe.class, (ShapedRecipe) recipe, "height"
);
final Object[] items = ReflectionHelper.getPrivateValue(
ShapedRecipe.class, (ShapedRecipe) recipe, "input"
);
if (allowSmallGrid && width < 3 && height < 3) {
return this.getSmallShapedRecipe(
width, height, items, recipe.getRecipeOutput()
);
} else {
return this.getCraftingShapedRecipe(
width, height, items, recipe.getRecipeOutput()
);
}
}
return null;
}
}