Skip to content

Instantly share code, notes, and snippets.

@YanisBft
Created July 30, 2019 12:38
Show Gist options
  • Save YanisBft/b40cea373274d3c7c7c41b0c07ad82f3 to your computer and use it in GitHub Desktop.
Save YanisBft/b40cea373274d3c7c7c41b0c07ad82f3 to your computer and use it in GitHub Desktop.
Container code
package com.yanis48.minalchemy.recipe;
import com.yanis48.minalchemy.init.MinalchemyBlocks;
import com.yanis48.minalchemy.init.MinalchemyRecipes;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeFinder;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.RecipeType;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
public class AlchemyRecipe implements Recipe<Inventory> {
protected final Identifier id;
protected final String group;
protected final ItemStack output;
protected final DefaultedList<Ingredient> ingredients;
public AlchemyRecipe(Identifier id, String group, ItemStack output, DefaultedList<Ingredient> ingredients) {
this.id = id;
this.group = group;
this.output = output;
this.ingredients = ingredients;
}
@Override
public boolean matches(Inventory inv, World world) {
RecipeFinder finder = new RecipeFinder();
return finder.findRecipe(this, null);
}
@Override
public ItemStack craft(Inventory inv) {
return this.output.copy();
}
@Override
public boolean fits(int x, int y) {
return true;
}
@Override
public ItemStack getOutput() {
return this.output;
}
@Override
public Identifier getId() {
return this.id;
}
@Override
public DefaultedList<Ingredient> getPreviewInputs() {
return this.ingredients;
}
@Environment(EnvType.CLIENT)
public String getGroup() {
return this.group;
}
@Environment(EnvType.CLIENT)
public ItemStack getRecipeKindIcon() {
return new ItemStack(MinalchemyBlocks.ALCHEMY_TABLE);
}
@Override
public RecipeSerializer<?> getSerializer() {
return MinalchemyRecipes.ALCHEMY_SERIALIZER;
}
@Override
public RecipeType<?> getType() {
return MinalchemyRecipes.ALCHEMY;
}
}
package com.yanis48.minalchemy.recipe;
import java.util.Iterator;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.ShapedRecipe;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;
import net.minecraft.util.PacketByteBuf;
@SuppressWarnings("rawtypes")
public class AlchemyRecipeSerializer implements RecipeSerializer<AlchemyRecipe> {
@Override
public AlchemyRecipe read(Identifier id, JsonObject json) {
String group = JsonHelper.getString(json, "group", "");
DefaultedList<Ingredient> ingredients = getIngredients(JsonHelper.getArray(json, "ingredients"));
if (ingredients.isEmpty()) {
throw new JsonParseException("No ingredients for alchemy recipe");
} else if (ingredients.size() < 2) {
throw new JsonParseException("Not enough ingredients for alchemy recipe");
} else if (ingredients.size() > 2) {
throw new JsonParseException("Too many ingredients for alchemy recipe");
} else {
ItemStack result = ShapedRecipe.getItemStack(JsonHelper.getObject(json, "result"));
return new AlchemyRecipe(id, group, result, ingredients);
}
}
@Override
public AlchemyRecipe read(Identifier id, PacketByteBuf buf) {
String group = buf.readString(32767);
int ingredientSize = buf.readVarInt();
DefaultedList<Ingredient> ingredients = DefaultedList.ofSize(ingredientSize, Ingredient.EMPTY);
for (int i = 0; i < ingredients.size(); i++) {
ingredients.set(i, Ingredient.fromPacket(buf));
}
ItemStack result = buf.readItemStack();
return new AlchemyRecipe(id, group, result, ingredients);
}
@Override
public void write(PacketByteBuf buf, AlchemyRecipe recipe) {
buf.writeString(recipe.group);
buf.writeVarInt(recipe.ingredients.size());
Iterator i = recipe.ingredients.iterator();
while (i.hasNext()) {
Ingredient ingredient = (Ingredient) i.next();
ingredient.write(buf);
}
buf.writeItemStack(recipe.output);
}
private static DefaultedList<Ingredient> getIngredients(JsonArray json) {
DefaultedList<Ingredient> ingredients = DefaultedList.of();
for (int i = 0; i < json.size(); i++) {
Ingredient ingredient = Ingredient.fromJson(json.get(i));
if (!ingredient.isEmpty()) {
ingredients.add(ingredient);
}
}
return ingredients;
}
}
package com.yanis48.minalchemy.container;
import java.util.Optional;
import com.yanis48.minalchemy.init.MinalchemyBlocks;
import com.yanis48.minalchemy.init.MinalchemyRecipes;
import com.yanis48.minalchemy.init.MinalchemyTags;
import com.yanis48.minalchemy.recipe.AlchemyRecipe;
import net.minecraft.block.Blocks;
import net.minecraft.client.network.packet.GuiSlotUpdateS2CPacket;
import net.minecraft.container.BlockContext;
import net.minecraft.container.CraftingContainer;
import net.minecraft.container.CraftingResultSlot;
import net.minecraft.container.Slot;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.CraftingResultInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeFinder;
import net.minecraft.recipe.RecipeInputProvider;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.World;
public class AlchemyTableContainer extends CraftingContainer<Inventory> {
private final CraftingInventory alchemyInv;
private final CraftingResultInventory resultInv;
private final BlockContext context;
private final World world;
private final PlayerEntity player;
public AlchemyTableContainer(int syncId, PlayerEntity player) {
this(syncId, player.inventory, BlockContext.EMPTY);
}
public AlchemyTableContainer(int syncId, PlayerInventory playerInv, BlockContext blockContext) {
super(null, syncId);
this.alchemyInv = new CraftingInventory(this, 1, 2) {
@Override
public void markDirty() {
super.markDirty();
AlchemyTableContainer.this.onContentChanged(this);
}
};
this.resultInv = new CraftingResultInventory();
this.context = blockContext;
this.player = playerInv.player;
this.world = player.world;
// Input Slot 1
this.addSlot(new Slot(this.alchemyInv, 0, 49, 23) {
public boolean canInsert(ItemStack stack) {
return stack.getItem().isIn(MinalchemyTags.ELEMENTS);
}
});
// Input Slot 2
this.addSlot(new Slot(this.alchemyInv, 1, 49, 44) {
public boolean canInsert(ItemStack stack) {
return stack.getItem().isIn(MinalchemyTags.ELEMENTS);
}
});
// Output Slot
this.addSlot(new CraftingResultSlot(this.player, this.alchemyInv, this.resultInv, 2, 129, 34));
// Player Inventory
for(int i = 0; i < 3; ++i) {
for(int j = 0; j < 9; ++j) {
this.addSlot(new Slot(playerInv, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
}
}
// Player Hotbar
for(int i = 0; i < 9; ++i) {
this.addSlot(new Slot(playerInv, i, 8 + i * 18, 142));
}
}
@Override
public boolean canUse(PlayerEntity player) {
return canUse(this.context, player, MinalchemyBlocks.ALCHEMY_TABLE);
}
@Override
public void onContentChanged(Inventory inv) {
//this.context.run((world, pos) -> {
updateResult(this.syncId, this.world, this.player, this.alchemyInv, this.resultInv);
//});
}
protected static void updateResult(int syncId, World world, PlayerEntity player, CraftingInventory alchemyInv, CraftingResultInventory resultInv) {
if (!world.isClient) {
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
ItemStack stack = ItemStack.EMPTY;
Optional<AlchemyRecipe> optional = world.getServer().getRecipeManager().getFirstMatch(MinalchemyRecipes.ALCHEMY, alchemyInv, world);
if (optional.isPresent()) {
AlchemyRecipe recipe = optional.get();
stack = recipe.craft(alchemyInv);
world.setBlockState(player.getBlockPos(), Blocks.EMERALD_BLOCK.getDefaultState());
} else {
world.setBlockState(player.getBlockPos(), Blocks.REDSTONE_BLOCK.getDefaultState());
}
/*if (stackInSlot1.getItem() == MinalchemyItems.WATER_ELEMENT && stackInSlot2.getItem() == MinalchemyItems.WATER_ELEMENT) {
this.resultInv.setInvStack(2, MinalchemyItems.PUDDLE_ELEMENT.getStackForRender());
}*/
resultInv.setInvStack(2, stack);
serverPlayer.networkHandler.sendPacket(new GuiSlotUpdateS2CPacket(syncId, 2, stack));
}
}
@Override
public void close(PlayerEntity player) {
super.close(player);
player.inventory.insertStack(this.alchemyInv.getInvStack(0));
player.inventory.insertStack(this.alchemyInv.getInvStack(1));
/*this.context.run((world, pos) -> {
this.dropInventory(player, world, this.alchemyInv);
});*/
}
public ItemStack transferSlot(PlayerEntity player, int slotNum) {
ItemStack stackToTransfer = ItemStack.EMPTY;
Slot slot = this.slotList.get(slotNum);
if (slot != null && slot.hasStack()) {
ItemStack stackInSlot = slot.getStack();
stackToTransfer = stackInSlot.copy();
ItemStack stackInSlot1 = this.alchemyInv.getInvStack(0);
ItemStack stackInSlot2 = this.alchemyInv.getInvStack(1);
if (slotNum == 2) {
if (!this.insertItem(stackInSlot, 3, 39, true)) {
return ItemStack.EMPTY;
}
slot.onStackChanged(stackInSlot, stackToTransfer);
} else if (slotNum != 0 && slotNum != 1) {
if (!stackInSlot1.isEmpty() && !stackInSlot2.isEmpty()) {
if (slotNum >= 3 && slotNum < 30) {
if (!this.insertItem(stackInSlot, 30, 39, false)) {
return ItemStack.EMPTY;
}
} else if (slotNum >= 30 && slotNum < 39 && !this.insertItem(stackInSlot, 3, 30, false)) {
return ItemStack.EMPTY;
}
} else if (!this.insertItem(stackInSlot, 0, 2, false)) {
return ItemStack.EMPTY;
}
} else if (!this.insertItem(stackInSlot, 3, 39, false)) {
return ItemStack.EMPTY;
}
if (stackInSlot.isEmpty()) {
slot.setStack(ItemStack.EMPTY);
} else {
slot.markDirty();
}
if (stackInSlot.getCount() == stackToTransfer.getCount()) {
return ItemStack.EMPTY;
}
slot.onTakeItem(player, stackInSlot);
}
return stackToTransfer;
}
@Override
public void populateRecipeFinder(RecipeFinder finder) {
((RecipeInputProvider)this.alchemyInv).provideRecipeInputs(finder);
}
@Override
public void clearCraftingSlots() {
this.alchemyInv.clear();
this.resultInv.clear();
}
@Override
public boolean matches(Recipe<? super Inventory> recipe) {
return recipe.matches(this.alchemyInv, this.world);
}
@Override
public int getCraftingResultSlotIndex() {
return 2;
}
@Override
public int getCraftingWidth() {
return 1;
}
@Override
public int getCraftingHeight() {
return 1;
}
@Override
public int getCraftingSlotCount() {
return 3;
}
}
package com.yanis48.minalchemy.client;
import com.mojang.blaze3d.platform.GlStateManager;
import com.yanis48.minalchemy.Minalchemy;
import com.yanis48.minalchemy.container.AlchemyTableContainer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Identifier;
@Environment(EnvType.CLIENT)
public class AlchemyTableScreen extends AbstractContainerScreen<AlchemyTableContainer> {
private static final Identifier TEXTURE = new Identifier(Minalchemy.MOD_ID, "textures/gui/alchemy_table.png");
public AlchemyTableScreen(AlchemyTableContainer container, int syncId, PlayerEntity player) {
super(container, player.inventory, new TranslatableText("container.minalchemy.alchemy_table", new Object[0]));
}
@Override
protected void drawForeground(int int_1, int int_2) {
this.font.draw(this.title.asFormattedString(), 8.0F, 6.0F, 4210752);
this.font.draw(this.playerInventory.getDisplayName().asFormattedString(), 8.0F, (float)(this.containerHeight - 96 + 2), 4210752);
}
@Override
public void render(int mouseX, int mouseY, float partialTicks) {
this.renderBackground();
this.drawBackground(partialTicks, mouseX, mouseY);
super.render(mouseX, mouseY, partialTicks);
this.drawMouseoverTooltip(mouseX, mouseY);
}
@Override
protected void drawBackground(float float_1, int int_1, int int_2) {
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
this.minecraft.getTextureManager().bindTexture(TEXTURE);
int int_3 = (this.width - this.containerWidth) / 2;
int int_4 = (this.height - this.containerHeight) / 2;
this.blit(int_3, int_4, 0, 0, this.containerWidth, this.containerHeight);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment