🎉 Trading starts!
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
package com.oierbravo.trading_station;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.oierbravo.trading_station.foundation.util.ModLang;
|
||||
import com.oierbravo.trading_station.registrate.*;
|
||||
import com.tterrag.registrate.Registrate;
|
||||
import net.minecraftforge.common.util.Lazy;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
// The value here should match an entry in the META-INF/mods.toml file
|
||||
@Mod("trading_station")
|
||||
public class TradingStation
|
||||
{
|
||||
// Directly reference a slf4j logger
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static final String MODID = "trading_station";
|
||||
public static final String DISPLAY_NAME = "Trading Station";
|
||||
|
||||
public static IEventBus modEventBus;
|
||||
|
||||
private static final Lazy<Registrate> REGISTRATE = Lazy.of(() -> Registrate.create(MODID));
|
||||
|
||||
public static final boolean withCreate = ModList.get().isLoaded("create");
|
||||
|
||||
|
||||
public static final Gson GSON = new GsonBuilder().setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.create();
|
||||
public TradingStation()
|
||||
{
|
||||
modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
// Register ourselves for server and other game events we are interested in
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
ModCreativeTab modTab = new ModCreativeTab();
|
||||
|
||||
ModBlocks.register();
|
||||
ModBlockEntities.register();
|
||||
ModRecipes.register(modEventBus);
|
||||
ModMessages.register();
|
||||
ModMenus.register();
|
||||
Config.register();
|
||||
|
||||
registrate().addRawLang("itemGroup.trading_station:main", "Trading Station");
|
||||
registrate().addRawLang(ModLang.key("block.display"), "Trading Station");
|
||||
registrate().addRawLang(ModLang.key("recipe"), "Trading recipe");
|
||||
registrate().addRawLang(ModLang.key("tooltip.progress"), "Progress: %d%%");
|
||||
registrate().addRawLang(ModLang.key("select_target.title"), "Select an output target");
|
||||
registrate().addRawLang(ModLang.key("select_target.button"), "Select target");
|
||||
registrate().addRawLang(ModLang.key("select_target.clear"), "Clear");
|
||||
registrate().addRawLang("config.jade.plugin_trading_station.trading_station_data", "Trading Station data");
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static Registrate registrate() {
|
||||
return REGISTRATE.get();
|
||||
}
|
||||
|
||||
|
||||
public static ResourceLocation asResource(String path) {
|
||||
return new ResourceLocation(MODID, path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.oierbravo.trading_station.compat.crafttweaker;
|
||||
|
||||
import com.blamejared.crafttweaker.api.recipe.component.IDecomposedRecipe;
|
||||
import com.blamejared.crafttweaker.api.recipe.handler.IRecipeHandler;
|
||||
import com.blamejared.crafttweaker.api.recipe.manager.base.IRecipeManager;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingRecipe;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@IRecipeHandler.For(TradingRecipe.class)
|
||||
public class TradingRecipeHandler implements IRecipeHandler<TradingRecipe>{
|
||||
|
||||
@Override
|
||||
public String dumpToCommandString(IRecipeManager<? super TradingRecipe> manager, TradingRecipe recipe) {
|
||||
return manager.getCommandString() + recipe.toString() + recipe.getOutput() + "[" + recipe.getIngredient() + "]";
|
||||
}
|
||||
@Override
|
||||
public <U extends Recipe<?>> boolean doesConflict(IRecipeManager<? super TradingRecipe> manager, TradingRecipe firstRecipe, U secondRecipe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<IDecomposedRecipe> decompose(IRecipeManager<? super TradingRecipe> manager, TradingRecipe recipe) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TradingRecipe> recompose(IRecipeManager<? super TradingRecipe> manager, ResourceLocation name, IDecomposedRecipe recipe) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.oierbravo.trading_station.compat.crafttweaker;
|
||||
|
||||
|
||||
import com.blamejared.crafttweaker.api.CraftTweakerAPI;
|
||||
import com.blamejared.crafttweaker.api.action.recipe.ActionAddRecipe;
|
||||
import com.blamejared.crafttweaker.api.annotation.ZenRegister;
|
||||
import com.blamejared.crafttweaker.api.fluid.IFluidStack;
|
||||
import com.blamejared.crafttweaker.api.ingredient.IIngredient;
|
||||
import com.blamejared.crafttweaker.api.recipe.manager.base.IRecipeManager;
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingRecipe;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import org.openzen.zencode.java.ZenCodeType;
|
||||
|
||||
@ZenRegister
|
||||
@ZenCodeType.Name("mods.trading_station.TradingManager")
|
||||
//@Document("mods/trading_station/melting")
|
||||
public class TradingRecipeManager implements IRecipeManager<TradingRecipe> {
|
||||
/**
|
||||
* Adds a Trading recipe.
|
||||
*
|
||||
* @param name The name of the recipe
|
||||
* @param output The output fluidStack of the recipe.
|
||||
* @param input The input of the recipe.
|
||||
* @param processingTime The duration of the recipe (default 100 ticks)
|
||||
* @param heatLevel Minimum heat level
|
||||
*
|
||||
* @docParam name "meltDown"
|
||||
* @docParam output <fluid:minecraft:lava> * 100
|
||||
* @docParam input <item:minecraft:dirt>
|
||||
* @docParam duration 200
|
||||
* @docParam heatLevel 2
|
||||
*/
|
||||
@ZenCodeType.Method
|
||||
public void addRecipe(String name, IFluidStack output, IIngredient input, int processingTime, int heatLevel ){
|
||||
name = fixRecipeName(name);
|
||||
ResourceLocation resourceLocation = new ResourceLocation(TradingStation.MODID, name);
|
||||
CraftTweakerAPI.apply(new ActionAddRecipe<>( this, new TradingRecipe(resourceLocation, output.getInternal(), input.asVanillaIngredient(), processingTime, heatLevel)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<TradingRecipe> getRecipeType() {
|
||||
return TradingRecipe.Type.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.oierbravo.trading_station.compat.jade;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import snownee.jade.api.BlockAccessor;
|
||||
import snownee.jade.api.IBlockComponentProvider;
|
||||
import snownee.jade.api.IServerDataProvider;
|
||||
import snownee.jade.api.ITooltip;
|
||||
import snownee.jade.api.config.IPluginConfig;
|
||||
import snownee.jade.api.ui.IElementHelper;
|
||||
import snownee.jade.api.ui.IProgressStyle;
|
||||
|
||||
public class ProgressComponentProvider implements IBlockComponentProvider, IServerDataProvider<BlockEntity> {
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ITooltip tooltip, BlockAccessor accessor, IPluginConfig config) {
|
||||
//CompoundTag serverData = accessor.getServerData();
|
||||
if (accessor.getServerData().contains("trading_station.progress")) {
|
||||
int progress = accessor.getServerData().getInt("trading_station.progress");
|
||||
IElementHelper elementHelper = tooltip.getElementHelper();
|
||||
IProgressStyle progressStyle = elementHelper.progressStyle();
|
||||
if(progress > 0)
|
||||
tooltip.add(elementHelper.progress((float)progress / 100, Component.translatable("trading_station.tooltip.progress", progress), progressStyle,elementHelper.borderStyle()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendServerData(CompoundTag compoundTag, ServerPlayer serverPlayer, Level level, BlockEntity blockEntity, boolean b) {
|
||||
if(blockEntity instanceof TradingStationBlockEntity){
|
||||
TradingStationBlockEntity trading_station = (TradingStationBlockEntity) blockEntity;
|
||||
compoundTag.putInt("trading_station.progress",trading_station.getProgressPercent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getUid() {
|
||||
return TradingStationPlugin.TRADING_STATION_DATA;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.oierbravo.trading_station.compat.jade;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlock;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import snownee.jade.api.*;
|
||||
|
||||
@WailaPlugin
|
||||
public class TradingStationPlugin implements IWailaPlugin {
|
||||
public static final ResourceLocation TRADING_STATION_DATA = TradingStation.asResource("trading_station_data");
|
||||
|
||||
@Override
|
||||
public void register(IWailaCommonRegistration registration) {
|
||||
registration.registerBlockDataProvider(new ProgressComponentProvider(), TradingStationBlockEntity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerClient(IWailaClientRegistration registration) {
|
||||
registration.registerBlockComponent(new ProgressComponentProvider(), TradingStationBlock.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.oierbravo.trading_station.compat.jei;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingRecipe;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationScreen;
|
||||
import com.oierbravo.trading_station.registrate.ModBlocks;
|
||||
import mezz.jei.api.IModPlugin;
|
||||
import mezz.jei.api.JeiPlugin;
|
||||
import mezz.jei.api.recipe.RecipeType;
|
||||
import mezz.jei.api.registration.IGuiHandlerRegistration;
|
||||
import mezz.jei.api.registration.IRecipeCatalystRegistration;
|
||||
import mezz.jei.api.registration.IRecipeCategoryRegistration;
|
||||
import mezz.jei.api.registration.IRecipeRegistration;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@JeiPlugin
|
||||
public class JEIPlugin implements IModPlugin {
|
||||
|
||||
@Override
|
||||
public ResourceLocation getPluginUid() {
|
||||
return new ResourceLocation(TradingStation.MODID, "jei_plugin");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCategories(IRecipeCategoryRegistration registration) {
|
||||
registration.addRecipeCategories(new
|
||||
TradingRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
|
||||
registration.addRecipeCatalyst(new ItemStack(ModBlocks.TRADING_STATION.get()),new RecipeType<>(TradingRecipeCategory.UID, TradingRecipe.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRecipes(IRecipeRegistration registration) {
|
||||
RecipeManager rm = Objects.requireNonNull(Minecraft.getInstance().level).getRecipeManager();
|
||||
|
||||
List<TradingRecipe> tradingRecipes = rm.getAllRecipesFor(TradingRecipe.Type.INSTANCE);
|
||||
registration.addRecipes(new RecipeType<>(TradingRecipeCategory.UID, TradingRecipe.class), tradingRecipes);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.oierbravo.trading_station.compat.jei;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingRecipe;
|
||||
import com.oierbravo.trading_station.foundation.util.ModLang;
|
||||
import com.oierbravo.trading_station.registrate.ModBlocks;
|
||||
import mezz.jei.api.constants.VanillaTypes;
|
||||
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
|
||||
import mezz.jei.api.gui.drawable.IDrawable;
|
||||
import mezz.jei.api.gui.drawable.IDrawableAnimated;
|
||||
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
|
||||
import mezz.jei.api.helpers.IGuiHelper;
|
||||
import mezz.jei.api.recipe.IFocusGroup;
|
||||
import mezz.jei.api.recipe.RecipeIngredientRole;
|
||||
import mezz.jei.api.recipe.RecipeType;
|
||||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||
import mezz.jei.common.Constants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TradingRecipeCategory implements IRecipeCategory<TradingRecipe> {
|
||||
public final static ResourceLocation UID = new ResourceLocation(TradingStation.MODID, "trading");
|
||||
private final LoadingCache<Integer, IDrawableAnimated> cachedArrows;
|
||||
|
||||
private final IDrawable background;
|
||||
private final IDrawable icon;
|
||||
|
||||
public TradingRecipeCategory(IGuiHelper helper) {
|
||||
this.cachedArrows = CacheBuilder.newBuilder()
|
||||
.maximumSize(25)
|
||||
.build(new CacheLoader<>() {
|
||||
@Override
|
||||
public IDrawableAnimated load(Integer cookTime) {
|
||||
return helper.drawableBuilder(Constants.RECIPE_GUI_VANILLA, 82, 128, 24, 17)
|
||||
.buildAnimated(cookTime, IDrawableAnimated.StartDirection.LEFT, false);
|
||||
}
|
||||
});
|
||||
this.background = new IDrawable() {
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 176;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 45;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(PoseStack poseStack, int xOffset, int yOffset) {
|
||||
|
||||
}
|
||||
};
|
||||
this.icon = helper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(ModBlocks.TRADING_STATION.get()));
|
||||
|
||||
}
|
||||
|
||||
protected IDrawableAnimated getArrow() {
|
||||
return this.cachedArrows.getUnchecked(50);
|
||||
}
|
||||
@Override
|
||||
public RecipeType<TradingRecipe> getRecipeType() {
|
||||
return RecipeType.create("trading_station","trading", TradingRecipe.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTitle() {
|
||||
return ModLang.translate("trading.recipe");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDrawable getBackground() {
|
||||
return this.background;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDrawable getIcon() {
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(@Nonnull IRecipeLayoutBuilder builder, @Nonnull TradingRecipe recipe, @Nonnull IFocusGroup focusGroup) {
|
||||
NonNullList<Ingredient> ingredients = recipe.getIngredients();
|
||||
for(int index = 0; index < ingredients.size(); index++) {
|
||||
Ingredient ing = ingredients.get(index);
|
||||
builder.addSlot(RecipeIngredientRole.INPUT, 41 + index * 18, 11)
|
||||
.addIngredients(ingredients.get(index));
|
||||
//.addItemStacks(Arrays.asList(ingredients.get(0).getItems()));
|
||||
|
||||
}
|
||||
|
||||
builder.addSlot(RecipeIngredientRole.OUTPUT, 113, 11)
|
||||
.addItemStack(recipe.getResultItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(TradingRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack stack, double mouseX, double mouseY) {
|
||||
IRecipeCategory.super.draw(recipe, recipeSlotsView, stack, mouseX, mouseY);
|
||||
IDrawableAnimated arrow = getArrow();
|
||||
arrow.draw(stack, 75, 14);
|
||||
drawProcessingTime(recipe, stack, 81,4);
|
||||
|
||||
|
||||
}
|
||||
protected void drawProcessingTime(TradingRecipe recipe, PoseStack poseStack, int x, int y) {
|
||||
int processingTime = recipe.getProcessingTime();
|
||||
if (processingTime > 0) {
|
||||
int cookTimeSeconds = processingTime / 20;
|
||||
MutableComponent timeString = Component.translatable("gui.jei.category.smelting.time.seconds", cookTimeSeconds);
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
Font fontRenderer = minecraft.font;
|
||||
fontRenderer.draw(poseStack, timeString, x, y, 0xFF808080);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.oierbravo.trading_station.compat.kubejs;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingRecipe;
|
||||
import dev.latvian.mods.kubejs.recipe.schema.RegisterRecipeSchemasEvent;
|
||||
|
||||
public class KubeJSPlugin extends dev.latvian.mods.kubejs.KubeJSPlugin {
|
||||
@Override
|
||||
public void registerRecipeSchemas(RegisterRecipeSchemasEvent event) {
|
||||
event.register(TradingRecipe.Serializer.ID, TradingRecipeSchema.SCHEMA);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.oierbravo.trading_station.compat.kubejs;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.latvian.mods.kubejs.item.InputItem;
|
||||
import dev.latvian.mods.kubejs.item.OutputItem;
|
||||
import dev.latvian.mods.kubejs.recipe.RecipeJS;
|
||||
import dev.latvian.mods.kubejs.recipe.RecipeKey;
|
||||
import dev.latvian.mods.kubejs.recipe.component.ItemComponents;
|
||||
import dev.latvian.mods.kubejs.recipe.component.NumberComponent;
|
||||
import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema;
|
||||
|
||||
public interface TradingRecipeSchema {
|
||||
RecipeKey<InputItem[]> INGREDIENTS = ItemComponents.INPUT_ARRAY.key("ingredients");
|
||||
RecipeKey<OutputItem> RESULT = ItemComponents.OUTPUT.key("result");
|
||||
RecipeKey<Integer> PROCESSING_TIME = NumberComponent.INT.key("processingTime").optional(1);
|
||||
public class TradingRecipeJS extends RecipeJS{
|
||||
@Override
|
||||
public JsonElement writeInputItem(InputItem value) {
|
||||
JsonObject json = super.writeInputItem(value).getAsJsonObject();
|
||||
if(value.count > 1){
|
||||
json.addProperty("count", value.count);
|
||||
}
|
||||
return (JsonElement) json;
|
||||
}
|
||||
}
|
||||
RecipeSchema SCHEMA = new RecipeSchema(TradingRecipeJS.class, TradingRecipeJS::new, RESULT, INGREDIENTS, PROCESSING_TIME);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.oierbravo.trading_station.foundation.util.ModLang;
|
||||
import com.oierbravo.trading_station.network.packets.ItemStackSyncS2CPacket;
|
||||
import com.oierbravo.trading_station.registrate.ModMessages;
|
||||
import com.oierbravo.trading_station.registrate.ModRecipes;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class AbstractTradingStationBlockEntity extends BlockEntity {
|
||||
private CompoundTag updateTag;
|
||||
public final ItemStackHandler inputItems = createInputItemHandler();
|
||||
public final ItemStackHandler outputItems = createOutputItemHandler();
|
||||
|
||||
public final ItemStackHandler targetItemHandler = createTargetItemHandler();
|
||||
private final LazyOptional<IItemHandler> inputItemHandler = LazyOptional.of(() -> inputItems);
|
||||
private final LazyOptional<IItemHandler> outputItemHandler = LazyOptional.of(() -> outputItems);
|
||||
|
||||
public int progress = 0;
|
||||
public int maxProgress = 1;
|
||||
private BlockState lastBlockState;
|
||||
|
||||
protected final ContainerData containerData;
|
||||
private Item preferedItem;
|
||||
|
||||
public AbstractTradingStationBlockEntity(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) {
|
||||
super(pType, pWorldPosition, pBlockState);
|
||||
updateTag = getPersistentData();
|
||||
lastBlockState = this.getBlockState();
|
||||
preferedItem = ItemStack.EMPTY.getItem();
|
||||
containerData = AbstractTradingStationBlockEntity.createContainerData(this);
|
||||
}
|
||||
public static ContainerData createContainerData(AbstractTradingStationBlockEntity pBlockEntity){
|
||||
return new ContainerData(){
|
||||
@Override
|
||||
public int get(int pIndex){
|
||||
return switch (pIndex) {
|
||||
case 0 -> pBlockEntity.progress;
|
||||
case 1 -> pBlockEntity.maxProgress;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void set(int pIndex, int pValue) {
|
||||
switch (pIndex) {
|
||||
case 0 -> pBlockEntity.progress = pValue;
|
||||
case 1 -> pBlockEntity.maxProgress = pValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
@NotNull
|
||||
@Nonnull
|
||||
private ItemStackHandler createTargetItemHandler() {
|
||||
return new ItemStackHandler(1) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
ModMessages.sendToClients(new ItemStackSyncS2CPacket(slot,this.getStackInSlot(0), worldPosition, ItemStackSyncS2CPacket.SlotType.TARGET));
|
||||
}
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
// clientSync();
|
||||
}
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return true;
|
||||
//return canProcess(stack) && super.isItemValid(slot, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ItemStackHandler createInputItemHandler() {
|
||||
return new ItemStackHandler(2) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
ModMessages.sendToClients(new ItemStackSyncS2CPacket(slot,this.getStackInSlot(0), worldPosition, ItemStackSyncS2CPacket.SlotType.INPUT));
|
||||
}
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
// clientSync();
|
||||
}
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return true;
|
||||
//return canProcess(stack) && super.isItemValid(slot, stack);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
private ItemStackHandler createOutputItemHandler() {
|
||||
return new ItemStackHandler(1) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
ModMessages.sendToClients(new ItemStackSyncS2CPacket(slot, this.getStackInSlot(slot), worldPosition, ItemStackSyncS2CPacket.SlotType.OUTPUT));
|
||||
}
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
// clientSync();
|
||||
}
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return canProcess(stack) && super.isItemValid(slot, stack);
|
||||
//return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||
if (cap == ForgeCapabilities.ITEM_HANDLER) {
|
||||
return inputItemHandler.cast();
|
||||
}
|
||||
return super.getCapability(cap, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoved() {
|
||||
super.setRemoved();
|
||||
inputItemHandler.invalidate();
|
||||
outputItemHandler.invalidate();
|
||||
}
|
||||
public LazyOptional<IItemHandler> getInputItemHandler(){
|
||||
return inputItemHandler;
|
||||
}
|
||||
public LazyOptional<IItemHandler> getOutputItemHandler(){
|
||||
return outputItemHandler;
|
||||
}
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCaps() {
|
||||
super.invalidateCaps();
|
||||
inputItemHandler.invalidate();
|
||||
outputItemHandler.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(@NotNull CompoundTag tag) {
|
||||
super.saveAdditional(tag);
|
||||
tag.put("input", inputItems.serializeNBT());
|
||||
tag.put("output", outputItems.serializeNBT());
|
||||
tag.put("target", targetItemHandler.serializeNBT());
|
||||
tag.putInt("trading_station.progress", progress);
|
||||
tag.putInt("trading_station.maxProgress", maxProgress);
|
||||
String preferedItemString = ForgeRegistries.ITEMS.getKey(preferedItem).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(CompoundTag tag) {
|
||||
super.load(tag);
|
||||
inputItems.deserializeNBT(tag.getCompound("input"));
|
||||
outputItems.deserializeNBT(tag.getCompound("output"));
|
||||
targetItemHandler.deserializeNBT(tag.getCompound("target"));
|
||||
progress = tag.getInt("trading_station.progress");
|
||||
maxProgress = tag.getInt("trading_station.maxProgress");
|
||||
String preferedItemString = tag.getString("trading_station.preferedItem");
|
||||
preferedItem = ForgeRegistries.ITEMS.getValue( ResourceLocation.tryParse(preferedItemString));
|
||||
}
|
||||
|
||||
public void drops() {
|
||||
SimpleContainer inventory = new SimpleContainer(inputItems.getSlots() + 1);
|
||||
for (int i = 0; i < inputItems.getSlots(); i++) {
|
||||
inventory.setItem(i, inputItems.getStackInSlot(i));
|
||||
}
|
||||
inventory.setItem(inputItems.getSlots(), inputItems.getStackInSlot(0));
|
||||
|
||||
Containers.dropContents(this.level, this.worldPosition, inventory);
|
||||
}
|
||||
|
||||
|
||||
public void resetProgress() {
|
||||
this.progress = 0;
|
||||
this.maxProgress = 1;
|
||||
}
|
||||
|
||||
protected static Optional<TradingRecipe> getRecipe(AbstractTradingStationBlockEntity pBlockEntity){
|
||||
Level level = pBlockEntity.getLevel();
|
||||
SimpleContainer inputInventory = getInputInventory(pBlockEntity);
|
||||
if(!pBlockEntity.targetItemHandler.getStackInSlot(0).isEmpty())
|
||||
return ModRecipes.findByOutput(level,pBlockEntity.targetItemHandler.getStackInSlot(0));
|
||||
return ModRecipes.find(inputInventory,level);
|
||||
// return level.getRecipeManager().getRecipeFor(TradingRecipe.Type.INSTANCE, inputInventory, level);
|
||||
}
|
||||
protected int getProcessingTime(AbstractTradingStationBlockEntity pBlockEntity) {
|
||||
return getRecipe(pBlockEntity).map(TradingRecipe::getProcessingTime).orElse(1);
|
||||
}
|
||||
|
||||
public static void tick(Level pLevel, BlockPos pPos, BlockState pState, AbstractTradingStationBlockEntity pBlockEntity) {
|
||||
|
||||
if(pLevel.isClientSide()) {
|
||||
return;
|
||||
}
|
||||
if(!isPowered(pBlockEntity))
|
||||
return;
|
||||
|
||||
if (canCraftItem(pBlockEntity)) {
|
||||
pBlockEntity.progress += 1;
|
||||
BlockEntity.setChanged(pLevel, pPos, pState);
|
||||
pBlockEntity.maxProgress = pBlockEntity.getProcessingTime(pBlockEntity);
|
||||
if (pBlockEntity.progress > pBlockEntity.maxProgress) {
|
||||
AbstractTradingStationBlockEntity.craftItem(pBlockEntity);
|
||||
}
|
||||
BlockEntity.setChanged(pLevel, pPos, pState);
|
||||
|
||||
} else {
|
||||
pBlockEntity.resetProgress();
|
||||
BlockEntity.setChanged(pLevel, pPos, pState);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
protected static void updateProgress(AbstractTradingStationBlockEntity pBlockEntity){
|
||||
pBlockEntity.progress += 1;
|
||||
|
||||
}
|
||||
private static boolean isPowered(AbstractTradingStationBlockEntity pBlockEntity){
|
||||
return pBlockEntity.getLevel().getBlockState(pBlockEntity.getBlockPos())
|
||||
.getValue(BlockStateProperties.POWERED);
|
||||
}
|
||||
private static SimpleContainer getInputInventory(AbstractTradingStationBlockEntity pBlockEntity){
|
||||
int containerSize = 0;
|
||||
for(int index = 0; index < pBlockEntity.inputItems.getSlots(); index++) {
|
||||
if (!pBlockEntity.inputItems.getStackInSlot(index).isEmpty())
|
||||
containerSize++;
|
||||
}
|
||||
|
||||
SimpleContainer inputInventory = new SimpleContainer(containerSize);
|
||||
pBlockEntity.inputItemHandler.ifPresent(iItemHandler -> {
|
||||
for(int slot = 0; slot < iItemHandler.getSlots(); slot++) {
|
||||
if(!iItemHandler.getStackInSlot(slot).isEmpty()){
|
||||
inputInventory.addItem(iItemHandler.getStackInSlot(slot));
|
||||
}
|
||||
}
|
||||
});
|
||||
return inputInventory;
|
||||
}
|
||||
private static void craftItem(AbstractTradingStationBlockEntity pBlockEntity) {
|
||||
Level level = pBlockEntity.getLevel();
|
||||
SimpleContainer inputInventory = getInputInventory(pBlockEntity);
|
||||
|
||||
Optional<TradingRecipe> recipe = getRecipe(pBlockEntity);
|
||||
|
||||
if(recipe.isPresent()){
|
||||
for (int i = 0; i < recipe.get().getIngredients().size(); i++) {
|
||||
Ingredient ingredient = recipe.get().getIngredients().get(i);
|
||||
|
||||
for (int slot = 0; slot < pBlockEntity.inputItems.getSlots(); slot++) {
|
||||
ItemStack itemStack = pBlockEntity.inputItems.getStackInSlot(slot);
|
||||
if(ingredient.test(itemStack)){
|
||||
pBlockEntity.inputItems.extractItem(slot,ingredient.getItems()[0].getCount(),false);
|
||||
inputInventory.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
pBlockEntity.outputItems.insertItem(0, recipe.get().getResultItem(), false);
|
||||
}
|
||||
|
||||
pBlockEntity.resetProgress();
|
||||
pBlockEntity.setChanged();
|
||||
}
|
||||
|
||||
|
||||
static boolean canCraftItem(AbstractTradingStationBlockEntity pBlockEntity) {
|
||||
Level level = pBlockEntity.getLevel();
|
||||
if(level == null)
|
||||
return false;
|
||||
|
||||
SimpleContainer inputInventory = getInputInventory(pBlockEntity);
|
||||
|
||||
Optional<TradingRecipe> match = getRecipe(pBlockEntity);
|
||||
|
||||
if(match.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
//return false;
|
||||
return match.isPresent()
|
||||
&& AbstractTradingStationBlockEntity.hasEnoughInputItems(inputInventory,match.get().getIngredients())
|
||||
&& AbstractTradingStationBlockEntity.hasEnoughOutputSpace(pBlockEntity.outputItems,match.get().getResultItem());
|
||||
}
|
||||
|
||||
private boolean canProcess(ItemStack stack) {
|
||||
|
||||
return getRecipe(this).isPresent();
|
||||
}
|
||||
protected static boolean hasEnoughInputItems(SimpleContainer inventory, NonNullList<Ingredient> ingredients){
|
||||
int enough = 0;
|
||||
for(int ingredientIndex = 0; ingredientIndex < ingredients.size();ingredientIndex ++){
|
||||
Ingredient ingredient = ingredients.get(ingredientIndex);
|
||||
for(int slot = 0; slot < inventory.getContainerSize(); slot++){
|
||||
if(ingredient.test(inventory.getItem(slot))){
|
||||
if(inventory.getItem(slot).getCount() >= ingredient.getItems()[0].getCount() )
|
||||
enough++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ingredients.size() == enough;
|
||||
}
|
||||
|
||||
protected static boolean hasEnoughOutputSpace(ItemStackHandler stackHandler,ItemStack resultItemStack){
|
||||
return stackHandler.getStackInSlot(0).isEmpty() || stackHandler.getStackInSlot(0).is(resultItemStack.getItem()) && stackHandler.getStackInSlot(0).getMaxStackSize() - stackHandler.getStackInSlot(0).getCount() >= resultItemStack.getCount() ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpdateTag() {
|
||||
this.saveAdditional(updateTag);
|
||||
return updateTag;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpdateTag(CompoundTag tag) {
|
||||
this.load(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) {
|
||||
this.load(pkt.getTag());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getProgressPercent() {
|
||||
return this.progress * 100 / this.maxProgress;
|
||||
}
|
||||
|
||||
|
||||
public void setItemStack(int slot, ItemStack itemStack,ItemStackSyncS2CPacket.SlotType slotType) {
|
||||
if(slotType == ItemStackSyncS2CPacket.SlotType.INPUT)
|
||||
inputItems.setStackInSlot(slot,itemStack);
|
||||
else if (slotType == ItemStackSyncS2CPacket.SlotType.OUTPUT)
|
||||
outputItems.setStackInSlot(slot,itemStack);
|
||||
else if (slotType == ItemStackSyncS2CPacket.SlotType.TARGET)
|
||||
targetItemHandler.setStackInSlot(slot,itemStack);
|
||||
|
||||
}
|
||||
|
||||
public void setPreferedItem(ItemStack itemStack) {
|
||||
this.targetItemHandler.setStackInSlot(0,itemStack);
|
||||
}
|
||||
|
||||
|
||||
public ItemStack getPreferedItemStack() {
|
||||
return targetItemHandler.getStackInSlot(0);
|
||||
}
|
||||
public ItemStackHandler getTargetItemHandler(){
|
||||
return targetItemHandler;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.platform.Lighting;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
/**
|
||||
* This class can be used to render a 2D ItemStack to the screen with optional transparency. The item being rendered
|
||||
* doesn't need to represent a real ItemStack held in an inventory or container.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class FakeItemRenderer {
|
||||
|
||||
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||
private static final ItemRenderer ITEM_RENDERER = MINECRAFT.getItemRenderer();
|
||||
private static final TextureManager TEXTURE_MANAGER = MINECRAFT.getTextureManager();
|
||||
|
||||
|
||||
public static void renderFakeItem(ItemStack pItemStack, int pX, int pY) {
|
||||
renderFakeItem(pItemStack, pX, pY, 1.0F);
|
||||
}
|
||||
|
||||
public static void renderFakeItem(ItemStack pItemStack, int pX, int pY, float pAlpha) {
|
||||
|
||||
if (!pItemStack.isEmpty()) {
|
||||
BakedModel model = getBakedModel(pItemStack);
|
||||
|
||||
TEXTURE_MANAGER.getTexture(InventoryMenu.BLOCK_ATLAS).setFilter(true, false);
|
||||
RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
RenderSystem.enableBlend();
|
||||
|
||||
PoseStack modelViewStack = RenderSystem.getModelViewStack();
|
||||
modelViewStack.pushPose();
|
||||
modelViewStack.translate(pX + 8.0D, pY + 8.0D, 0F);
|
||||
modelViewStack.scale(16.0F, -16.0F, 16.0F);
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
|
||||
if (!model.usesBlockLight()) {
|
||||
Lighting.setupForFlatItems();
|
||||
}
|
||||
|
||||
MultiBufferSource.BufferSource bufferSource = MINECRAFT.renderBuffers().bufferSource();
|
||||
ITEM_RENDERER.render(pItemStack,
|
||||
ItemTransforms.TransformType.GUI,
|
||||
false,
|
||||
new PoseStack(),
|
||||
getWrappedBuffer(bufferSource, pAlpha),
|
||||
LightTexture.FULL_BRIGHT,
|
||||
OverlayTexture.NO_OVERLAY,
|
||||
model);
|
||||
bufferSource.endBatch();
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
if (!model.usesBlockLight()) {
|
||||
Lighting.setupFor3DItems();
|
||||
}
|
||||
|
||||
modelViewStack.popPose();
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
private static MultiBufferSource getWrappedBuffer(MultiBufferSource pBufferSource, float pAlpha) {
|
||||
return pRenderType -> new WrappedVertexConsumer(pBufferSource.getBuffer(RenderType.entityTranslucent(InventoryMenu.BLOCK_ATLAS)), 1F, 1F, 1F, pAlpha);
|
||||
}
|
||||
|
||||
private static BakedModel getBakedModel(ItemStack pItemStack) {
|
||||
return ITEM_RENDERER.getModel(pItemStack, null, MINECRAFT.player, 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class WrappedVertexConsumer implements VertexConsumer {
|
||||
|
||||
protected final VertexConsumer consumer;
|
||||
protected final float red;
|
||||
protected final float green;
|
||||
protected final float blue;
|
||||
protected final float alpha;
|
||||
|
||||
public WrappedVertexConsumer(VertexConsumer pConsumer, float pRed, float pGreen, float pBlue, float pAlpha) {
|
||||
this.consumer = pConsumer;
|
||||
this.red = pRed;
|
||||
this.green = pGreen;
|
||||
this.blue = pBlue;
|
||||
this.alpha = pAlpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer vertex(double pX, double pY, double pZ) {
|
||||
return consumer.vertex(pX, pY, pZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer color(int pRed, int pGreen, int pBlue, int pAlpha) {
|
||||
return consumer.color((int)(pRed * red), (int)(pGreen * green), (int)(pBlue * blue), (int)(pAlpha * alpha));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer uv(float pU, float pV) {
|
||||
return consumer.uv(pU, pV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer overlayCoords(int pU, int pV) {
|
||||
return consumer.overlayCoords(pU, pV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer uv2(int pU, int pV) {
|
||||
return consumer.uv2(pU, pV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer normal(float pX, float pY, float pZ) {
|
||||
return consumer.normal(pX, pY, pZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVertex() {
|
||||
consumer.endVertex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defaultColor(int pDefaultR, int pDefaultG, int pDefaultB, int pDefaultA) {
|
||||
consumer.defaultColor(pDefaultR, pDefaultG, pDefaultB, pDefaultA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetDefaultColor() {
|
||||
consumer.unsetDefaultColor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingRecipeBuilder.TradingRecipeParams;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.*;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class TradingRecipe implements Recipe<SimpleContainer> {
|
||||
private final ResourceLocation id;
|
||||
private final NonNullList<Ingredient> itemIngredients;
|
||||
private final ItemStack result;
|
||||
|
||||
private final int processingTime;
|
||||
|
||||
public TradingRecipe(TradingRecipeParams params) {
|
||||
this.id = params.id;
|
||||
this.result = params.result;
|
||||
this.itemIngredients = params.itemIngredients;
|
||||
this.processingTime = params.processingTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(SimpleContainer pContainer, Level pLevel) {
|
||||
if(pLevel.isClientSide)
|
||||
return false;
|
||||
if(pContainer.getContainerSize() != itemIngredients.size())
|
||||
return false;
|
||||
|
||||
int matchedIngredients = 0;
|
||||
for (int i = 0; i < itemIngredients.size(); i++) {
|
||||
Ingredient ingredient = itemIngredients.get(i);
|
||||
|
||||
for (int slot = 0; slot < pContainer.getContainerSize(); slot++) {
|
||||
ItemStack itemStack = pContainer.getItem(slot);
|
||||
if(ingredient.test(pContainer.getItem(slot))){
|
||||
matchedIngredients++;
|
||||
}
|
||||
}
|
||||
|
||||
return matchedIngredients == itemIngredients.size();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
public boolean matches(SimpleContainer pContainer, Level pLevel, ItemStack preferedOutput){
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean matchesOutput(ItemStack targetItemStack){
|
||||
return result.sameItem(targetItemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NonNullList<Ingredient> getIngredients() {
|
||||
return itemIngredients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack assemble(SimpleContainer pContainer) {
|
||||
|
||||
return result.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCraftInDimensions(int pWidth, int pHeight) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ItemStack getResultItem() {
|
||||
return result.copy();
|
||||
}
|
||||
public ItemStack getResult(){
|
||||
return result.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return Serializer.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return Type.INSTANCE;
|
||||
}
|
||||
public static class Type implements RecipeType<TradingRecipe> {
|
||||
private Type() { }
|
||||
public static final Type INSTANCE = new Type();
|
||||
public static final String ID = "trading";
|
||||
}
|
||||
public static class Serializer implements RecipeSerializer<TradingRecipe> {
|
||||
public static final Serializer INSTANCE = new Serializer();
|
||||
public static final ResourceLocation ID =
|
||||
new ResourceLocation(TradingStation.MODID,"trading");
|
||||
|
||||
@Override
|
||||
public TradingRecipe fromJson(ResourceLocation id, JsonObject json) {
|
||||
TradingRecipeBuilder builder = new TradingRecipeBuilder(id);
|
||||
NonNullList<Ingredient> itemIngredients = NonNullList.create();
|
||||
int processingTime = 1;
|
||||
|
||||
for (JsonElement je : GsonHelper.getAsJsonArray(json, "ingredients")) {
|
||||
JsonObject jsonObject = je.getAsJsonObject();
|
||||
Ingredient ingredient = Ingredient.fromJson(jsonObject);
|
||||
if(jsonObject.has("count")){
|
||||
ItemStack itemStack = ingredient.getItems()[0];
|
||||
itemStack.setCount(jsonObject.get("count").getAsInt());
|
||||
}
|
||||
|
||||
itemIngredients.add(ingredient);
|
||||
}
|
||||
|
||||
ItemStack result = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
|
||||
|
||||
if(GsonHelper.isValidNode(json,"processingTime")){
|
||||
processingTime = GsonHelper.getAsInt(json,"processingTime");
|
||||
}
|
||||
|
||||
builder.withItemIngredients(itemIngredients)
|
||||
.withSingleItemOutput(result)
|
||||
.processingTime(processingTime);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradingRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||
TradingRecipeBuilder builder = new TradingRecipeBuilder(id);
|
||||
NonNullList<Ingredient> itemIngredients = NonNullList.create();
|
||||
int processingTime = 1;
|
||||
|
||||
int size = buffer.readVarInt();
|
||||
for (int i = 0; i < size; i++)
|
||||
itemIngredients.add(Ingredient.fromNetwork(buffer));
|
||||
|
||||
ItemStack result = buffer.readItem();
|
||||
processingTime = buffer.readInt();
|
||||
|
||||
|
||||
builder.withItemIngredients(itemIngredients)
|
||||
.withSingleItemOutput(result)
|
||||
.processingTime(processingTime);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNetwork(FriendlyByteBuf buffer, TradingRecipe recipe) {
|
||||
NonNullList<Ingredient> itemIngredients = recipe.itemIngredients;
|
||||
int processingTime = recipe.getProcessingTime();
|
||||
|
||||
|
||||
buffer.writeVarInt(itemIngredients.size());
|
||||
itemIngredients.forEach(i -> i.toNetwork(buffer));
|
||||
buffer.writeItem(recipe.getResultItem());
|
||||
buffer.writeInt(processingTime);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public int getProcessingTime() {
|
||||
return processingTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraftforge.common.crafting.conditions.ICondition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TradingRecipeBuilder {
|
||||
protected TradingRecipeParams params;
|
||||
protected List<ICondition> recipeConditions;
|
||||
public TradingRecipeBuilder(ResourceLocation recipeId) {
|
||||
params = new TradingRecipeParams(recipeId);
|
||||
recipeConditions = new ArrayList<>();
|
||||
|
||||
|
||||
}
|
||||
public TradingRecipeBuilder withItemIngredients(Ingredient... itemIngredients) {
|
||||
return withItemIngredients(NonNullList.of(Ingredient.EMPTY, itemIngredients));
|
||||
}
|
||||
|
||||
public TradingRecipeBuilder withItemIngredients(NonNullList<Ingredient> itemIngredients) {
|
||||
params.itemIngredients = itemIngredients;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TradingRecipeBuilder withSingleItemOutput(ItemStack output) {
|
||||
params.result = output;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TradingRecipeBuilder processingTime(int time) {
|
||||
params.processingTime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public TradingRecipe build(){
|
||||
return new TradingRecipe(params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static class TradingRecipeParams {
|
||||
|
||||
protected ResourceLocation id;
|
||||
protected NonNullList<Ingredient> itemIngredients;
|
||||
protected ItemStack result;
|
||||
protected int fuelConsumed;
|
||||
protected int processingTime;
|
||||
|
||||
protected TradingRecipeParams(ResourceLocation id) {
|
||||
this.id = id;
|
||||
itemIngredients = NonNullList.create();
|
||||
result = ItemStack.EMPTY;
|
||||
fuelConsumed = 0;
|
||||
processingTime = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.oierbravo.trading_station.registrate.ModBlockEntities;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING;
|
||||
|
||||
|
||||
public class TradingStationBlock extends BaseEntityBlock {
|
||||
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||||
|
||||
private static final VoxelShape RENDER_SHAPE = Shapes.box(0, 0, 0, 1, 1, 1);
|
||||
//public static final BooleanProperty BOTTOM = BlockStateProperties.BOTTOM;
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
return RENDER_SHAPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
return RENDER_SHAPE;
|
||||
}
|
||||
|
||||
public TradingStationBlock(Properties pProperties) {
|
||||
super(pProperties);
|
||||
registerDefaultState(getStateDefinition().any().setValue(HORIZONTAL_FACING, Direction.NORTH).setValue(POWERED,false));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context)
|
||||
{
|
||||
if (!context.getLevel().getBlockState(context.getClickedPos().above()).canBeReplaced(context))
|
||||
return null;
|
||||
return super.getStateForPlacement(context)
|
||||
.setValue(HORIZONTAL_FACING, context.getHorizontalDirection().getOpposite())
|
||||
.setValue(POWERED, context.getLevel().hasNeighborSignal(context.getClickedPos()));
|
||||
}
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(HORIZONTAL_FACING).add(POWERED);
|
||||
}
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState pState) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
|
||||
return ModBlockEntities.TRADING_STATION.create(pPos, pState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource r) {
|
||||
boolean previouslyPowered = state.getValue(POWERED);
|
||||
if (previouslyPowered != worldIn.hasNeighborSignal(pos))
|
||||
worldIn.setBlock(pos, state.cycle(POWERED), 2);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState, BlockEntityType<T> pBlockEntityType) {
|
||||
return createTickerHelper(pBlockEntityType, ModBlockEntities.TRADING_STATION.get(),
|
||||
TradingStationBlockEntity::tick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
||||
boolean isMoving) {
|
||||
super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving);
|
||||
if (worldIn.isClientSide)
|
||||
return;
|
||||
if (!worldIn.getBlockTicks()
|
||||
.willTickThisTick(pos, this))
|
||||
worldIn.scheduleTick(pos, this, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
|
||||
if (pState.getBlock() != pNewState.getBlock()) {
|
||||
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
|
||||
if (blockEntity instanceof TradingStationBlockEntity) {
|
||||
((TradingStationBlockEntity) blockEntity).drops();
|
||||
}
|
||||
}
|
||||
super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand handIn, BlockHitResult hit) {
|
||||
|
||||
if (!pLevel.isClientSide()) {
|
||||
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
|
||||
if(blockEntity instanceof TradingStationBlockEntity) {
|
||||
NetworkHooks.openScreen(((ServerPlayer)pPlayer), (TradingStationBlockEntity)blockEntity, pPos);
|
||||
} else {
|
||||
throw new IllegalStateException("Our Container provider is missing!");
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(pLevel.isClientSide());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.oierbravo.trading_station.foundation.util.ModLang;
|
||||
import com.oierbravo.trading_station.network.packets.ItemStackSyncS2CPacket;
|
||||
import com.oierbravo.trading_station.registrate.ModMessages;
|
||||
import com.oierbravo.trading_station.registrate.ModRecipes;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.ShapelessRecipe;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class TradingStationBlockEntity extends BlockEntity implements MenuProvider {
|
||||
|
||||
|
||||
//private final int FLUID_CAPACITY = TradingStationConfig.trading_station_CAPACITY.get();
|
||||
//private static final int FLIUD_PER_TICK = TradingStationConfig.trading_statio_FLUID_PER_TICK.get();
|
||||
private CompoundTag updateTag;
|
||||
public final ItemStackHandler inputItems = createInputItemHandler();
|
||||
public final ItemStackHandler outputItems = createOutputItemHandler();
|
||||
|
||||
public final ItemStackHandler targetItemHandler = createTargetItemHandler();
|
||||
private final LazyOptional<IItemHandler> inputItemHandler = LazyOptional.of(() -> inputItems);
|
||||
private final LazyOptional<IItemHandler> outputItemHandler = LazyOptional.of(() -> outputItems);
|
||||
|
||||
public int progress = 0;
|
||||
public int maxProgress = 1;
|
||||
private BlockState lastBlockState;
|
||||
|
||||
protected final ContainerData containerData;
|
||||
private Item preferedItem;
|
||||
|
||||
public TradingStationBlockEntity(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) {
|
||||
super(pType, pWorldPosition, pBlockState);
|
||||
updateTag = getPersistentData();
|
||||
lastBlockState = this.getBlockState();
|
||||
preferedItem = ItemStack.EMPTY.getItem();
|
||||
containerData = TradingStationBlockEntity.createContainerData(this);
|
||||
}
|
||||
public static ContainerData createContainerData(TradingStationBlockEntity pBlockEntity){
|
||||
return new ContainerData(){
|
||||
@Override
|
||||
public int get(int pIndex){
|
||||
return switch (pIndex) {
|
||||
case 0 -> pBlockEntity.progress;
|
||||
case 1 -> pBlockEntity.maxProgress;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void set(int pIndex, int pValue) {
|
||||
switch (pIndex) {
|
||||
case 0 -> pBlockEntity.progress = pValue;
|
||||
case 1 -> pBlockEntity.maxProgress = pValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
@NotNull
|
||||
@Nonnull
|
||||
private ItemStackHandler createTargetItemHandler() {
|
||||
return new ItemStackHandler(1) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
ModMessages.sendToClients(new ItemStackSyncS2CPacket(slot,this.getStackInSlot(0), worldPosition, ItemStackSyncS2CPacket.SlotType.TARGET));
|
||||
}
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
// clientSync();
|
||||
}
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return true;
|
||||
//return canProcess(stack) && super.isItemValid(slot, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ItemStackHandler createInputItemHandler() {
|
||||
return new ItemStackHandler(2) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
ModMessages.sendToClients(new ItemStackSyncS2CPacket(slot,this.getStackInSlot(0), worldPosition, ItemStackSyncS2CPacket.SlotType.INPUT));
|
||||
}
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
// clientSync();
|
||||
}
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return true;
|
||||
//return canProcess(stack) && super.isItemValid(slot, stack);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
private ItemStackHandler createOutputItemHandler() {
|
||||
return new ItemStackHandler(1) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
ModMessages.sendToClients(new ItemStackSyncS2CPacket(slot, this.getStackInSlot(slot), worldPosition, ItemStackSyncS2CPacket.SlotType.OUTPUT));
|
||||
}
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
// clientSync();
|
||||
}
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return canProcess(stack) && super.isItemValid(slot, stack);
|
||||
//return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||
if (cap == ForgeCapabilities.ITEM_HANDLER) {
|
||||
return inputItemHandler.cast();
|
||||
}
|
||||
return super.getCapability(cap, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoved() {
|
||||
super.setRemoved();
|
||||
inputItemHandler.invalidate();
|
||||
outputItemHandler.invalidate();
|
||||
}
|
||||
public LazyOptional<IItemHandler> getInputItemHandler(){
|
||||
return inputItemHandler;
|
||||
}
|
||||
public LazyOptional<IItemHandler> getOutputItemHandler(){
|
||||
return outputItemHandler;
|
||||
}
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCaps() {
|
||||
super.invalidateCaps();
|
||||
inputItemHandler.invalidate();
|
||||
outputItemHandler.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(@NotNull CompoundTag tag) {
|
||||
super.saveAdditional(tag);
|
||||
tag.put("input", inputItems.serializeNBT());
|
||||
tag.put("output", outputItems.serializeNBT());
|
||||
tag.put("target", targetItemHandler.serializeNBT());
|
||||
tag.putInt("trading_station.progress", progress);
|
||||
tag.putInt("trading_station.maxProgress", maxProgress);
|
||||
String preferedItemString = ForgeRegistries.ITEMS.getKey(preferedItem).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(CompoundTag tag) {
|
||||
super.load(tag);
|
||||
inputItems.deserializeNBT(tag.getCompound("input"));
|
||||
outputItems.deserializeNBT(tag.getCompound("output"));
|
||||
targetItemHandler.deserializeNBT(tag.getCompound("target"));
|
||||
progress = tag.getInt("trading_station.progress");
|
||||
maxProgress = tag.getInt("trading_station.maxProgress");
|
||||
String preferedItemString = tag.getString("trading_station.preferedItem");
|
||||
preferedItem = ForgeRegistries.ITEMS.getValue( ResourceLocation.tryParse(preferedItemString));
|
||||
}
|
||||
|
||||
public void drops() {
|
||||
SimpleContainer inventory = new SimpleContainer(inputItems.getSlots() + 1);
|
||||
for (int i = 0; i < inputItems.getSlots(); i++) {
|
||||
inventory.setItem(i, inputItems.getStackInSlot(i));
|
||||
}
|
||||
inventory.setItem(inputItems.getSlots(), inputItems.getStackInSlot(0));
|
||||
|
||||
Containers.dropContents(this.level, this.worldPosition, inventory);
|
||||
}
|
||||
|
||||
|
||||
public void resetProgress() {
|
||||
this.progress = 0;
|
||||
this.maxProgress = 1;
|
||||
}
|
||||
|
||||
protected static Optional<TradingRecipe> getRecipe(TradingStationBlockEntity pBlockEntity){
|
||||
Level level = pBlockEntity.getLevel();
|
||||
SimpleContainer inputInventory = getInputInventory(pBlockEntity);
|
||||
if(!pBlockEntity.targetItemHandler.getStackInSlot(0).isEmpty())
|
||||
return ModRecipes.findByOutput(level,pBlockEntity.targetItemHandler.getStackInSlot(0));
|
||||
return ModRecipes.find(inputInventory,level);
|
||||
// return level.getRecipeManager().getRecipeFor(TradingRecipe.Type.INSTANCE, inputInventory, level);
|
||||
}
|
||||
protected int getProcessingTime(TradingStationBlockEntity pBlockEntity) {
|
||||
return getRecipe(pBlockEntity).map(TradingRecipe::getProcessingTime).orElse(1);
|
||||
}
|
||||
|
||||
public static void tick(Level pLevel, BlockPos pPos, BlockState pState, TradingStationBlockEntity pBlockEntity) {
|
||||
|
||||
if(pLevel.isClientSide()) {
|
||||
return;
|
||||
}
|
||||
if(!isPowered(pBlockEntity))
|
||||
return;
|
||||
|
||||
if (canCraftItem(pBlockEntity)) {
|
||||
pBlockEntity.progress += 1;
|
||||
BlockEntity.setChanged(pLevel, pPos, pState);
|
||||
pBlockEntity.maxProgress = pBlockEntity.getProcessingTime(pBlockEntity);
|
||||
if (pBlockEntity.progress > pBlockEntity.maxProgress) {
|
||||
TradingStationBlockEntity.craftItem(pBlockEntity);
|
||||
}
|
||||
BlockEntity.setChanged(pLevel, pPos, pState);
|
||||
|
||||
} else {
|
||||
pBlockEntity.resetProgress();
|
||||
BlockEntity.setChanged(pLevel, pPos, pState);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
protected static void updateProgress(TradingStationBlockEntity pBlockEntity){
|
||||
pBlockEntity.progress += 1;
|
||||
|
||||
}
|
||||
private static boolean isPowered(TradingStationBlockEntity pBlockEntity){
|
||||
return pBlockEntity.getLevel().getBlockState(pBlockEntity.getBlockPos())
|
||||
.getValue(BlockStateProperties.POWERED);
|
||||
}
|
||||
private static SimpleContainer getInputInventory(TradingStationBlockEntity pBlockEntity){
|
||||
int containerSize = 0;
|
||||
for(int index = 0; index < pBlockEntity.inputItems.getSlots(); index++) {
|
||||
if (!pBlockEntity.inputItems.getStackInSlot(index).isEmpty())
|
||||
containerSize++;
|
||||
}
|
||||
|
||||
SimpleContainer inputInventory = new SimpleContainer(containerSize);
|
||||
pBlockEntity.inputItemHandler.ifPresent(iItemHandler -> {
|
||||
for(int slot = 0; slot < iItemHandler.getSlots(); slot++) {
|
||||
if(!iItemHandler.getStackInSlot(slot).isEmpty()){
|
||||
inputInventory.addItem(iItemHandler.getStackInSlot(slot));
|
||||
}
|
||||
}
|
||||
});
|
||||
return inputInventory;
|
||||
}
|
||||
private static void craftItem(TradingStationBlockEntity pBlockEntity) {
|
||||
Level level = pBlockEntity.getLevel();
|
||||
SimpleContainer inputInventory = getInputInventory(pBlockEntity);
|
||||
|
||||
Optional<TradingRecipe> recipe = getRecipe(pBlockEntity);
|
||||
|
||||
if(recipe.isPresent()){
|
||||
for (int i = 0; i < recipe.get().getIngredients().size(); i++) {
|
||||
Ingredient ingredient = recipe.get().getIngredients().get(i);
|
||||
|
||||
for (int slot = 0; slot < pBlockEntity.inputItems.getSlots(); slot++) {
|
||||
ItemStack itemStack = pBlockEntity.inputItems.getStackInSlot(slot);
|
||||
if(ingredient.test(itemStack)){
|
||||
pBlockEntity.inputItems.extractItem(slot,ingredient.getItems()[0].getCount(),false);
|
||||
inputInventory.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
pBlockEntity.outputItems.insertItem(0, recipe.get().getResultItem(), false);
|
||||
}
|
||||
|
||||
pBlockEntity.resetProgress();
|
||||
pBlockEntity.setChanged();
|
||||
}
|
||||
|
||||
|
||||
static boolean canCraftItem(TradingStationBlockEntity pBlockEntity) {
|
||||
Level level = pBlockEntity.getLevel();
|
||||
if(level == null)
|
||||
return false;
|
||||
|
||||
SimpleContainer inputInventory = getInputInventory(pBlockEntity);
|
||||
|
||||
Optional<TradingRecipe> match = getRecipe(pBlockEntity);
|
||||
|
||||
if(match.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
//return false;
|
||||
return match.isPresent()
|
||||
&& TradingStationBlockEntity.hasEnoughInputItems(inputInventory,match.get().getIngredients())
|
||||
&& TradingStationBlockEntity.hasEnoughOutputSpace(pBlockEntity.outputItems,match.get().getResultItem());
|
||||
}
|
||||
|
||||
private boolean canProcess(ItemStack stack) {
|
||||
|
||||
return getRecipe(this).isPresent();
|
||||
}
|
||||
protected static boolean hasEnoughInputItems(SimpleContainer inventory, NonNullList<Ingredient> ingredients){
|
||||
int enough = 0;
|
||||
for(int ingredientIndex = 0; ingredientIndex < ingredients.size();ingredientIndex ++){
|
||||
Ingredient ingredient = ingredients.get(ingredientIndex);
|
||||
for(int slot = 0; slot < inventory.getContainerSize(); slot++){
|
||||
if(ingredient.test(inventory.getItem(slot))){
|
||||
if(inventory.getItem(slot).getCount() >= ingredient.getItems()[0].getCount() )
|
||||
enough++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ingredients.size() == enough;
|
||||
}
|
||||
|
||||
protected static boolean hasEnoughOutputSpace(ItemStackHandler stackHandler,ItemStack resultItemStack){
|
||||
return stackHandler.getStackInSlot(0).isEmpty() || stackHandler.getStackInSlot(0).is(resultItemStack.getItem()) && stackHandler.getStackInSlot(0).getMaxStackSize() - stackHandler.getStackInSlot(0).getCount() >= resultItemStack.getCount() ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpdateTag() {
|
||||
this.saveAdditional(updateTag);
|
||||
return updateTag;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpdateTag(CompoundTag tag) {
|
||||
this.load(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) {
|
||||
this.load(pkt.getTag());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getProgressPercent() {
|
||||
return this.progress * 100 / this.maxProgress;
|
||||
}
|
||||
|
||||
|
||||
public void setItemStack(int slot, ItemStack itemStack,ItemStackSyncS2CPacket.SlotType slotType) {
|
||||
if(slotType == ItemStackSyncS2CPacket.SlotType.INPUT)
|
||||
inputItems.setStackInSlot(slot,itemStack);
|
||||
else if (slotType == ItemStackSyncS2CPacket.SlotType.OUTPUT)
|
||||
outputItems.setStackInSlot(slot,itemStack);
|
||||
else if (slotType == ItemStackSyncS2CPacket.SlotType.TARGET)
|
||||
targetItemHandler.setStackInSlot(slot,itemStack);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return ModLang.translate("block.display");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) {
|
||||
return new TradingStationMenu(pContainerId, pPlayerInventory, this, this.containerData);
|
||||
}
|
||||
|
||||
public void setPreferedItem(ItemStack itemStack) {
|
||||
this.targetItemHandler.setStackInSlot(0,itemStack);
|
||||
}
|
||||
|
||||
|
||||
public ItemStack getPreferedItemStack() {
|
||||
return targetItemHandler.getStackInSlot(0);
|
||||
}
|
||||
public ItemStackHandler getTargetItemHandler(){
|
||||
return targetItemHandler;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TradingStationBlockRenderer implements BlockEntityRenderer<TradingStationBlockEntity> {
|
||||
public TradingStationBlockRenderer(BlockEntityRendererProvider.Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(TradingStationBlockEntity pBlockEntity, float pPartialTick, @NotNull PoseStack pPoseStack, @NotNull MultiBufferSource pBufferSource, int pPackedLight, int pPackedOverlay) {
|
||||
if(!pBlockEntity.getPreferedItemStack().isEmpty()){
|
||||
pPoseStack.pushPose();
|
||||
pPoseStack.translate(0.5d, 1.1d, 0.5d);
|
||||
renderBlock(pPoseStack,pBufferSource, LightTexture.FULL_BRIGHT,pPackedOverlay,pBlockEntity.getPreferedItemStack());
|
||||
pPoseStack.popPose();
|
||||
}
|
||||
}
|
||||
protected void renderBlock(PoseStack ms, MultiBufferSource buffer, int light, int overlay, ItemStack stack) {
|
||||
Minecraft.getInstance()
|
||||
.getItemRenderer()
|
||||
.renderStatic(stack, ItemTransforms.TransformType.GROUND, light, overlay, ms, buffer, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
public class TradingStationConfig {
|
||||
//public static ForgeConfigSpec.IntValue MELTER_CAPACITY;
|
||||
//public static ForgeConfigSpec.IntValue MELTER_FLUID_PER_TICK;
|
||||
|
||||
public static void registerServerConfig(ForgeConfigSpec.Builder COMMON_BUILDER) {
|
||||
/* SERVER_BUILDER.comment("Settings for the trading_station").push("trading_station");
|
||||
MELTER_CAPACITY = SERVER_BUILDER
|
||||
.comment("How much liquid fits into the trading_station, in mB")
|
||||
.defineInRange("capacity", 1000, 1, Integer.MAX_VALUE);
|
||||
MELTER_FLUID_PER_TICK = SERVER_BUILDER
|
||||
.comment("How much liquid generates per tick, in mB")
|
||||
.defineInRange("liquidPerTick", 2, 1, Integer.MAX_VALUE);
|
||||
SERVER_BUILDER.pop();*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.oierbravo.trading_station.registrate.ModBlocks;
|
||||
import com.oierbravo.trading_station.registrate.ModMenus;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.*;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.SlotItemHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class TradingStationMenu extends AbstractContainerMenu {
|
||||
public final TradingStationBlockEntity blockEntity;
|
||||
public final Inventory inventory;
|
||||
private final Level level;
|
||||
private final ContainerData containerData;
|
||||
public ItemStackHandler ghostInventory;
|
||||
|
||||
|
||||
public TradingStationMenu(int pContainerId, Inventory inv, FriendlyByteBuf extraData){
|
||||
this(pContainerId, inv, inv.player.level.getBlockEntity(extraData.readBlockPos()), new SimpleContainerData(2));
|
||||
}
|
||||
|
||||
public TradingStationMenu(int pContainerId, Inventory pInv, BlockEntity pBlockEntity, ContainerData pData){
|
||||
super(ModMenus.TRADING_STATION.get(), pContainerId);
|
||||
checkContainerSize(pInv, 3);
|
||||
blockEntity = (TradingStationBlockEntity) pBlockEntity;
|
||||
this.level = pInv.player.getLevel();
|
||||
this.containerData = pData;
|
||||
this.inventory = pInv;
|
||||
addPlayerHotbar(pInv);
|
||||
addPlayerInventory(pInv);
|
||||
this.addDataSlots(pData);
|
||||
//this.blockEntity.inputItems
|
||||
this.blockEntity.getInputItemHandler().ifPresent(itemHandler -> {
|
||||
this.addSlot(new SlotItemHandler(itemHandler,0,TradingStationScreen.inputSlotX[0],TradingStationScreen.inputSlotY));
|
||||
this.addSlot(new SlotItemHandler(itemHandler,1,TradingStationScreen.inputSlotX[1],TradingStationScreen.inputSlotY));
|
||||
});
|
||||
this.blockEntity.getOutputItemHandler().ifPresent(itemHandler -> {
|
||||
this.addSlot(new SlotItemHandler(itemHandler,0,TradingStationScreen.outputSlotX,TradingStationScreen.outputSlotY));
|
||||
});
|
||||
this.addSlot(new SlotItemHandler(this.blockEntity.getTargetItemHandler(),0,87,28));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public TradingStationMenu(int pContainerId, Inventory pInventory, BlockPos sourcePos) {
|
||||
this(pContainerId, pInventory, Minecraft.getInstance().level.getBlockEntity(sourcePos), TradingStationBlockEntity.createContainerData((TradingStationBlockEntity) Minecraft.getInstance().level.getBlockEntity(sourcePos)));
|
||||
}
|
||||
|
||||
public static TradingStationMenu factory(@Nullable MenuType<TradingStationMenu> pMenuType, int pContainerId, Inventory inventory, FriendlyByteBuf buf) {
|
||||
return new TradingStationMenu(pContainerId, inventory, buf);
|
||||
}
|
||||
public int getScaledProgress() {
|
||||
int progress = this.containerData.get(0);
|
||||
int maxProgress = this.containerData.get(1); // Max Progress
|
||||
int progressArrowSize = 34; // This is the height in pixels of your arrow
|
||||
|
||||
return maxProgress != 0 && progress != 0 ? progress * progressArrowSize / maxProgress : 0;
|
||||
}
|
||||
public boolean isCrafting() {
|
||||
return containerData.get(0) > 0;
|
||||
}
|
||||
private static final int HOTBAR_SLOT_COUNT = 9;
|
||||
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
|
||||
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
|
||||
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
|
||||
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
|
||||
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
|
||||
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
|
||||
|
||||
// THIS YOU HAVE TO DEFINE!
|
||||
private static final int TE_INVENTORY_SLOT_COUNT = 2; // must be the number of slots you have!
|
||||
@Override
|
||||
public ItemStack quickMoveStack(Player playerIn, int pIndex) {
|
||||
Slot sourceSlot = slots.get(pIndex);
|
||||
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
|
||||
ItemStack sourceStack = sourceSlot.getItem();
|
||||
ItemStack copyOfSourceStack = sourceStack.copy();
|
||||
|
||||
// Check if the slot clicked is one of the vanilla container slots
|
||||
if (pIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
|
||||
// This is a vanilla container slot so merge the stack into the tile inventory
|
||||
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
|
||||
+ TE_INVENTORY_SLOT_COUNT, false)) {
|
||||
return ItemStack.EMPTY; // EMPTY_ITEM
|
||||
}
|
||||
} else if (pIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
|
||||
// This is a TE slot so merge the stack into the players inventory
|
||||
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (pIndex == TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
|
||||
// This is a TE Outpu slot so merge the stack into the players inventory
|
||||
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else {
|
||||
System.out.println("Invalid slotIndex:" + pIndex);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
// If stack size == 0 (the entire stack was moved) set slot contents to null
|
||||
if (sourceStack.getCount() == 0) {
|
||||
sourceSlot.set(ItemStack.EMPTY);
|
||||
} else {
|
||||
sourceSlot.setChanged();
|
||||
}
|
||||
sourceSlot.onTake(playerIn, sourceStack);
|
||||
return copyOfSourceStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player pPlayer) {
|
||||
return stillValid(ContainerLevelAccess.create(level, blockEntity.getBlockPos()), pPlayer, ModBlocks.TRADING_STATION.get());
|
||||
}
|
||||
private static final int PLAYER_INVENTORY_Y = 64;
|
||||
|
||||
private void addPlayerInventory(Inventory playerInventory) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int l = 0; l < 9; ++l) {
|
||||
this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, PLAYER_INVENTORY_Y + i * 18));
|
||||
}
|
||||
}
|
||||
}
|
||||
private static final int HOTBAR_Y = 122;
|
||||
|
||||
private void addPlayerHotbar(Inventory playerInventory) {
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, HOTBAR_Y));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.foundation.util.ModLang;
|
||||
import com.oierbravo.trading_station.registrate.ModRecipes;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraftforge.client.gui.widget.ExtendedButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
public class TradingStationScreen extends AbstractContainerScreen<TradingStationMenu> {
|
||||
private static final ResourceLocation TEXTURE = TradingStation.asResource("textures/gui/trading_station.png");
|
||||
|
||||
private int progressArrowX = 79;
|
||||
private int progressArrowY = 47;
|
||||
|
||||
private int targetSelectButtonX = 131;
|
||||
private int targetSelectButtonY = 18;
|
||||
|
||||
public static int inputSlotX[] = {19,42};
|
||||
public static int inputSlotY = 38;
|
||||
public static int outputSlotX = 131;
|
||||
public static int outputSlotY = 38;
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
this.titleLabelX = 4;
|
||||
this.titleLabelY = 4;
|
||||
this.inventoryLabelY = 100000;
|
||||
this.addRenderableWidget(new ExtendedButton(leftPos + targetSelectButtonX,topPos + targetSelectButtonY,16,16, ModLang.translate("select_target.button"), btn ->{
|
||||
TradingStationTargetSelectScreen screen = new TradingStationTargetSelectScreen( this.menu.blockEntity);
|
||||
Minecraft.getInstance().pushGuiLayer(screen);
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
public TradingStationScreen(TradingStationMenu pMenu, Inventory pPlayerInventory, Component pTitle) {
|
||||
super(pMenu, pPlayerInventory, pTitle);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(PoseStack pPoseStack, float pPartialTick, int pMouseX, int pMouseY) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
RenderSystem.setShaderTexture(0, TEXTURE);
|
||||
this.fillGradient(pPoseStack, 0, 0, this.width, this.height, -1072689136, -804253680);
|
||||
|
||||
int x = (width - imageWidth) / 2;
|
||||
int y = (height - imageHeight) / 2;
|
||||
this.blit(pPoseStack, x, y, 0, 0, imageWidth, imageHeight);
|
||||
|
||||
if (menu.isCrafting()) {
|
||||
this.blit(pPoseStack, x + progressArrowX, y + progressArrowY, 179, 0, menu.getScaledProgress(), 7);
|
||||
}
|
||||
|
||||
if(!menu.blockEntity.getPreferedItemStack().isEmpty()){
|
||||
Optional<TradingRecipe> recipe = ModRecipes.findByOutput(menu.blockEntity.getLevel(),menu.blockEntity.getPreferedItemStack());
|
||||
if(recipe.isPresent()){
|
||||
renderFakeRecipe(recipe.get(), pPoseStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void renderFakeRecipe(TradingRecipe recipe, PoseStack pPoseStack){
|
||||
for(int index = 0; index < recipe.getIngredients().size(); index++){
|
||||
Ingredient ingredient = recipe.getIngredients().get(index);
|
||||
if(!ingredient.isEmpty())
|
||||
FakeItemRenderer.renderFakeItem(ingredient.getItems()[0],getGuiLeft() + TradingStationScreen.inputSlotX[index],getGuiTop() + TradingStationScreen.inputSlotY, .5f);
|
||||
}
|
||||
FakeItemRenderer.renderFakeItem(recipe.getResultItem(),getGuiLeft() + TradingStationScreen.outputSlotX,getGuiTop() + TradingStationScreen.outputSlotY, .5f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render(PoseStack pPoseStack, int pMouseX, int pMouseY, float pPartialTick) {
|
||||
super.render(pPoseStack, pMouseX, pMouseY, pPartialTick);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package com.oierbravo.trading_station.content.trading_station;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.foundation.util.ModLang;
|
||||
import com.oierbravo.trading_station.network.packets.GhostItemSyncC2SPacket;
|
||||
import com.oierbravo.trading_station.registrate.ModMessages;
|
||||
import com.oierbravo.trading_station.registrate.ModRecipes;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Scroll code and loop adapted from Alchemistry/src/main/java/com/smashingmods/alchemistry/client/container/RecipeSelectorScreen.java
|
||||
*/
|
||||
public class TradingStationTargetSelectScreen extends Screen {
|
||||
private static final ResourceLocation TEXTURE = TradingStation.asResource("textures/gui/trade_select.png");
|
||||
private TradingStationBlockEntity blockEntity;
|
||||
private List<ItemStack> allPossibleOutputs;
|
||||
private LinkedList<ItemStack> displayedItemStacks = new LinkedList<>();
|
||||
|
||||
|
||||
private float scrollOffset;
|
||||
private boolean scrolling;
|
||||
private int startIndex;
|
||||
private static int MAX_DISPLAYED_RECIPES = 24;
|
||||
private static final int COLUMNS = 8;
|
||||
private static final int TARGET_BOX_SIZE = 17;
|
||||
|
||||
private int targetBoxLeftPosOffset = 7;
|
||||
private int targetBoxTopPosOffset = 19;
|
||||
|
||||
private int scrollBarXOffset = 148;
|
||||
private int scrollBarYOffset = 22;
|
||||
|
||||
protected int titleLabelX;
|
||||
protected int titleLabelY;
|
||||
protected int imageWidth = 165;
|
||||
protected int imageHeight = 83;
|
||||
protected int leftPos;
|
||||
protected int topPos;
|
||||
|
||||
protected TradingStationTargetSelectScreen(Component pTitle) {
|
||||
super(pTitle);
|
||||
}
|
||||
public TradingStationTargetSelectScreen(TradingStationBlockEntity pBlockEntity) {
|
||||
this(ModLang.translate("select_target.title"));
|
||||
this.blockEntity = pBlockEntity;
|
||||
this.allPossibleOutputs = ModRecipes.getAllOutputs(pBlockEntity.getLevel());
|
||||
resetDisplayedTargets();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
this.titleLabelX = 4;
|
||||
this.titleLabelY = 4;
|
||||
this.leftPos = (this.width - this.imageWidth) / 2;
|
||||
this.topPos = (this.height - this.imageHeight) / 2;
|
||||
addRenderableWidget(new Button(getGuiLeft() - 25, getGuiTop() + 1, 25, 20, Component.literal("<--"), (button) -> {
|
||||
Minecraft.getInstance().popGuiLayer();
|
||||
}));
|
||||
addRenderableWidget(new Button(getGuiLeft() - 25, getGuiTop() + 30, 25, 20, ModLang.translate("select_target.clear"), (button) -> {
|
||||
ModMessages.sendToServer(new GhostItemSyncC2SPacket(ItemStack.EMPTY,this.blockEntity.getBlockPos()));
|
||||
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_STONECUTTER_SELECT_RECIPE, 1.0f));
|
||||
Minecraft.getInstance().popGuiLayer();
|
||||
}));
|
||||
}
|
||||
|
||||
public int getGuiLeft() { return leftPos; }
|
||||
public int getGuiTop() { return topPos; }
|
||||
@Override
|
||||
public void tick() {
|
||||
if (displayedItemStacks.size() < MAX_DISPLAYED_RECIPES) {
|
||||
mouseScrolled(0, 0, 0);
|
||||
scrollOffset = 0.0f;
|
||||
}
|
||||
if (displayedItemStacks.size() <= MAX_DISPLAYED_RECIPES) {
|
||||
startIndex = 0;
|
||||
scrollOffset = 0;
|
||||
}
|
||||
super.tick();
|
||||
}
|
||||
@Override
|
||||
public void render(PoseStack pPoseStack, int pMouseX, int pMouseY, float pPartialTick) {
|
||||
|
||||
renderBackground(pPoseStack);
|
||||
|
||||
int lastDisplayedIndex = startIndex + MAX_DISPLAYED_RECIPES;
|
||||
|
||||
renderScrollbar(pPoseStack);
|
||||
renderSelectedTarget(pPoseStack, pMouseX, pMouseY, lastDisplayedIndex);
|
||||
renderTargetItems(pPoseStack, pMouseX, pMouseY, lastDisplayedIndex);
|
||||
renderLabels(pPoseStack, pMouseX, pMouseY);
|
||||
|
||||
super.render(pPoseStack, pMouseX, pMouseY, pPartialTick);
|
||||
}
|
||||
protected void renderLabels(PoseStack pPoseStack, int pMouseX, int pMouseY) {
|
||||
this.font.draw(pPoseStack, this.title, (float)this.titleLabelX + getGuiLeft(), (float)this.titleLabelY + getGuiTop(), 4210752);
|
||||
}
|
||||
private void renderSelectedTarget(PoseStack pPoseStack, int pMouseX, int pMouseY, int pLastDisplayedIndex) {
|
||||
LinkedList<ItemStack> displayedRecipes = getDisplayedItemStacks();
|
||||
ItemStack selectedTarget = this.blockEntity.getTargetItemHandler().getStackInSlot(0);
|
||||
for (int index = startIndex; index >= 0 && index < pLastDisplayedIndex && index < displayedRecipes.size(); index++) {
|
||||
|
||||
int firstDisplayedIndex = index - startIndex;
|
||||
ItemStack target = allPossibleOutputs.get(index);
|
||||
int xStart = getGuiLeft() + targetBoxLeftPosOffset + firstDisplayedIndex % COLUMNS * TARGET_BOX_SIZE + 1;
|
||||
int yStart = getGuiTop() + targetBoxTopPosOffset + (firstDisplayedIndex / COLUMNS) * TARGET_BOX_SIZE + 3;
|
||||
if(target.sameItem(selectedTarget))
|
||||
blit(pPoseStack, xStart, yStart, 0, imageHeight + 19, TARGET_BOX_SIZE, TARGET_BOX_SIZE);
|
||||
}
|
||||
}
|
||||
private void renderTargetItems(PoseStack pPoseStack, int pMouseX, int pMouseY, int pLastDisplayedIndex) {
|
||||
LinkedList<ItemStack> displayedRecipes = getDisplayedItemStacks();
|
||||
|
||||
for (int index = startIndex; index >= 0 && index < pLastDisplayedIndex && index < displayedRecipes.size(); index++) {
|
||||
|
||||
int firstDisplayedIndex = index - startIndex;
|
||||
ItemStack target = allPossibleOutputs.get(index);
|
||||
int xStart = getGuiLeft() + targetBoxLeftPosOffset + firstDisplayedIndex % COLUMNS * TARGET_BOX_SIZE + 1;
|
||||
int yStart = getGuiTop() + targetBoxTopPosOffset + (firstDisplayedIndex / COLUMNS) * TARGET_BOX_SIZE + 3;
|
||||
|
||||
renderFloatingItem(target, xStart, yStart);
|
||||
|
||||
if (pMouseX >= xStart - 1 && pMouseX <= xStart + 16 && pMouseY >= yStart - 1 && pMouseY <= yStart + 16) {
|
||||
renderTooltip(pPoseStack, target, pMouseX, pMouseY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LinkedList<ItemStack> getDisplayedItemStacks() {
|
||||
return displayedItemStacks;
|
||||
}
|
||||
|
||||
private void renderFloatingItem(ItemStack pItemStack, int pX, int pY) {
|
||||
RenderSystem.applyModelViewMatrix();
|
||||
setBlitOffset(2000);
|
||||
itemRenderer.blitOffset = 2000.0f;
|
||||
|
||||
itemRenderer.renderAndDecorateItem(pItemStack, pX, pY);
|
||||
itemRenderer.renderGuiItemDecorations(font, pItemStack, pX, pY, "");
|
||||
|
||||
setBlitOffset(0);
|
||||
itemRenderer.blitOffset = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void renderBackground(PoseStack pPoseStack) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
RenderSystem.setShaderTexture(0, TEXTURE);
|
||||
this.fillGradient(pPoseStack, 0, 0, this.width, this.height, -1072689136, -804253680);
|
||||
this.blit(pPoseStack, getGuiLeft(), getGuiTop(), 0, 0, imageWidth, imageHeight);
|
||||
}
|
||||
|
||||
private void renderScrollbar(PoseStack pPoseStack) {
|
||||
int scrollPosition = (int) (43.0f * scrollOffset);
|
||||
blit(pPoseStack, getGuiLeft() + scrollBarXOffset, getGuiTop() + scrollBarYOffset + scrollPosition, 0, imageHeight + 1 + (isScrollBarActive() ? 0 : 9), 7, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) {
|
||||
scrolling = false;
|
||||
|
||||
int lastDisplayedIndex = startIndex + MAX_DISPLAYED_RECIPES;
|
||||
|
||||
for (int index = startIndex; index < lastDisplayedIndex; index++) {
|
||||
int currentIndex = index - startIndex;
|
||||
double boxX = pMouseX - (double)(getGuiLeft() + targetBoxLeftPosOffset + currentIndex % COLUMNS * TARGET_BOX_SIZE);
|
||||
double boxY = pMouseY - (double)(getGuiTop() + targetBoxTopPosOffset + currentIndex / COLUMNS * TARGET_BOX_SIZE);
|
||||
|
||||
if (boxX > 0 && boxX <= TARGET_BOX_SIZE + 1 && boxY > 0 && boxY <= TARGET_BOX_SIZE + 1 && isValidRecipeIndex(index)) {
|
||||
ItemStack itemStack = getDisplayedItemStacks().get(index);
|
||||
ModMessages.sendToServer(new GhostItemSyncC2SPacket(itemStack,this.blockEntity.getBlockPos()));
|
||||
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_STONECUTTER_SELECT_RECIPE, 1.0f));
|
||||
Minecraft.getInstance().popGuiLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
int scrollMinX = leftPos + 148;
|
||||
int scrollMinY = topPos + 9;
|
||||
int scrollMaxX = scrollMinX + 6;
|
||||
int scrollMaxY = scrollMinY + 60;
|
||||
|
||||
if (pMouseX >= scrollMinX && pMouseX < scrollMaxX && pMouseY >= scrollMinY && pMouseY < scrollMaxY) {
|
||||
scrolling = true;
|
||||
}
|
||||
}
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton);
|
||||
}
|
||||
private boolean isValidRecipeIndex(int pSlot) {
|
||||
return pSlot >= 0 && pSlot < getDisplayedItemStacks().size();
|
||||
}
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
return false;
|
||||
}
|
||||
public void resetDisplayedTargets() {
|
||||
this.displayedItemStacks.clear();
|
||||
this.displayedItemStacks.addAll(allPossibleOutputs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double pMouseX, double pMouseY, int pButton, double pDragX, double pDragY) {
|
||||
if (scrolling && isScrollBarActive()) {
|
||||
int scrollbarTopPos = getGuiTop() + 9;
|
||||
int scrollbarBottomPos = scrollbarTopPos + 51;
|
||||
scrollOffset = ((float) pMouseY - (float) scrollbarTopPos - 7.5f) / ((float) (scrollbarBottomPos - scrollbarTopPos) - 9.0f);
|
||||
scrollOffset = Mth.clamp(scrollOffset, 0.0f, 1.0f);
|
||||
startIndex = (int) ((double) (scrollOffset * (float) getOffscreenRows()) + 0.5d) * COLUMNS;
|
||||
return true;
|
||||
} else {
|
||||
return super.mouseDragged(pMouseX, pMouseY, pButton, pDragX, pDragY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) {
|
||||
if (pMouseX >= leftPos && pMouseX < leftPos + imageWidth && pMouseY >= topPos && pMouseY < topPos + imageHeight && isScrollBarActive()) {
|
||||
scrollOffset = Mth.clamp(scrollOffset - (float) pDelta / (float) getOffscreenRows(), 0.0f, 1.0f);
|
||||
startIndex = (int) ((double) (scrollOffset * (float) getOffscreenRows()) + 0.5d) * COLUMNS;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private int getOffscreenRows() {
|
||||
return (displayedItemStacks.size() + 6 - 1) / 6 - 3;
|
||||
}
|
||||
private boolean isScrollBarActive() {
|
||||
return displayedItemStacks.size() > MAX_DISPLAYED_RECIPES;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.oierbravo.trading_station.content.trading_station.powered;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlock;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import com.oierbravo.trading_station.registrate.ModBlockEntities;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PoweredTradingStationBlock extends TradingStationBlock {
|
||||
public PoweredTradingStationBlock(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
|
||||
return ModBlockEntities.POWERED_TRADING_STATION.create(pPos, pState);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState, BlockEntityType<T> pBlockEntityType) {
|
||||
return createTickerHelper(pBlockEntityType, ModBlockEntities.POWERED_TRADING_STATION.get(),
|
||||
TradingStationBlockEntity::tick);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.oierbravo.trading_station.content.trading_station.powered;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class PoweredTradingStationBlockEntity extends TradingStationBlockEntity {
|
||||
public PoweredTradingStationBlockEntity(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) {
|
||||
super(pType, pWorldPosition, pBlockState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.oierbravo.trading_station.foundation.gui;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationScreen;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraftforge.client.gui.widget.ExtendedButton;
|
||||
|
||||
public class BackButton extends ExtendedButton {
|
||||
public BackButton(int pX, int pY, int pWidth, int pHeight, Component pMessage, OnPress pOnPress) {
|
||||
super(pX, pY, pWidth, pHeight, pMessage, pOnPress);
|
||||
}
|
||||
/* public BackButton(int pX, int pY, AbstractContainerScreen<TradingStationScreen> parentScreen){
|
||||
this(pX,pY,16,16,Component.literal("Back"), btn->{
|
||||
this.
|
||||
})
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.oierbravo.trading_station.foundation.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import net.minecraft.client.renderer.RenderStateShard;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RegisterShadersEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
// TODO 1.17: use custom shaders instead of vanilla ones
|
||||
public class RenderTypes extends RenderStateShard {
|
||||
|
||||
public static final ShaderStateShard GLOWING_SHADER = new ShaderStateShard(() -> Shaders.glowingShader);
|
||||
|
||||
|
||||
|
||||
|
||||
public static RenderType getOutlineTranslucent(ResourceLocation texture, boolean cull) {
|
||||
return RenderType.create(createLayerName("outline_translucent" + (cull ? "_cull" : "")),
|
||||
DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, false, true, RenderType.CompositeState.builder()
|
||||
.setShaderState(cull ? RENDERTYPE_ENTITY_TRANSLUCENT_CULL_SHADER : RENDERTYPE_ENTITY_TRANSLUCENT_SHADER)
|
||||
.setTextureState(new TextureStateShard(texture, false, false))
|
||||
.setTransparencyState(TRANSLUCENT_TRANSPARENCY)
|
||||
.setCullState(cull ? CULL : NO_CULL)
|
||||
.setLightmapState(LIGHTMAP)
|
||||
.setOverlayState(OVERLAY)
|
||||
.setWriteMaskState(COLOR_WRITE)
|
||||
.createCompositeState(false));
|
||||
}
|
||||
|
||||
public static RenderType getGlowingSolid(ResourceLocation texture) {
|
||||
return RenderType.create(createLayerName("glowing_solid"), DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256,
|
||||
true, false, RenderType.CompositeState.builder()
|
||||
.setShaderState(GLOWING_SHADER)
|
||||
.setTextureState(new TextureStateShard(texture, false, false))
|
||||
.setCullState(CULL)
|
||||
.setLightmapState(LIGHTMAP)
|
||||
.setOverlayState(OVERLAY)
|
||||
.createCompositeState(true));
|
||||
}
|
||||
|
||||
private static final RenderType GLOWING_SOLID_DEFAULT = getGlowingSolid(InventoryMenu.BLOCK_ATLAS);
|
||||
|
||||
public static RenderType getGlowingSolid() {
|
||||
return GLOWING_SOLID_DEFAULT;
|
||||
}
|
||||
|
||||
public static RenderType getGlowingTranslucent(ResourceLocation texture) {
|
||||
return RenderType.create(createLayerName("glowing_translucent"), DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS,
|
||||
256, true, true, RenderType.CompositeState.builder()
|
||||
.setShaderState(GLOWING_SHADER)
|
||||
.setTextureState(new TextureStateShard(texture, false, false))
|
||||
.setTransparencyState(TRANSLUCENT_TRANSPARENCY)
|
||||
.setLightmapState(LIGHTMAP)
|
||||
.setOverlayState(OVERLAY)
|
||||
.createCompositeState(true));
|
||||
}
|
||||
|
||||
private static final RenderType ADDITIVE = RenderType.create(createLayerName("additive"), DefaultVertexFormat.BLOCK,
|
||||
VertexFormat.Mode.QUADS, 256, true, true, RenderType.CompositeState.builder()
|
||||
.setShaderState(BLOCK_SHADER)
|
||||
.setTextureState(new TextureStateShard(InventoryMenu.BLOCK_ATLAS, false, false))
|
||||
.setTransparencyState(ADDITIVE_TRANSPARENCY)
|
||||
.setCullState(NO_CULL)
|
||||
.setLightmapState(LIGHTMAP)
|
||||
.setOverlayState(OVERLAY)
|
||||
.createCompositeState(true));
|
||||
|
||||
public static RenderType getAdditive() {
|
||||
return ADDITIVE;
|
||||
}
|
||||
|
||||
private static final RenderType GLOWING_TRANSLUCENT_DEFAULT = getGlowingTranslucent(InventoryMenu.BLOCK_ATLAS);
|
||||
|
||||
public static RenderType getGlowingTranslucent() {
|
||||
return GLOWING_TRANSLUCENT_DEFAULT;
|
||||
}
|
||||
|
||||
private static final RenderType ITEM_PARTIAL_SOLID =
|
||||
RenderType.create(createLayerName("item_partial_solid"), DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, true,
|
||||
false, RenderType.CompositeState.builder()
|
||||
.setShaderState(RENDERTYPE_ENTITY_SOLID_SHADER)
|
||||
.setTextureState(BLOCK_SHEET)
|
||||
.setCullState(CULL)
|
||||
.setLightmapState(LIGHTMAP)
|
||||
.setOverlayState(OVERLAY)
|
||||
.createCompositeState(true));
|
||||
|
||||
public static RenderType getItemPartialSolid() {
|
||||
return ITEM_PARTIAL_SOLID;
|
||||
}
|
||||
|
||||
private static final RenderType ITEM_PARTIAL_TRANSLUCENT = RenderType.create(createLayerName("item_partial_translucent"),
|
||||
DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, true, true, RenderType.CompositeState.builder()
|
||||
.setShaderState(RENDERTYPE_ENTITY_TRANSLUCENT_CULL_SHADER)
|
||||
.setTextureState(BLOCK_SHEET)
|
||||
.setTransparencyState(TRANSLUCENT_TRANSPARENCY)
|
||||
.setLightmapState(LIGHTMAP)
|
||||
.setOverlayState(OVERLAY)
|
||||
.createCompositeState(true));
|
||||
|
||||
public static RenderType getItemPartialTranslucent() {
|
||||
return ITEM_PARTIAL_TRANSLUCENT;
|
||||
}
|
||||
|
||||
private static final RenderType FLUID = RenderType.create(createLayerName("fluid"),
|
||||
DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, false, true, RenderType.CompositeState.builder()
|
||||
.setShaderState(RENDERTYPE_ENTITY_TRANSLUCENT_CULL_SHADER)
|
||||
.setTextureState(BLOCK_SHEET_MIPPED)
|
||||
.setTransparencyState(TRANSLUCENT_TRANSPARENCY)
|
||||
.setLightmapState(LIGHTMAP)
|
||||
.setOverlayState(OVERLAY)
|
||||
.createCompositeState(true));
|
||||
|
||||
public static RenderType getFluid() {
|
||||
return FLUID;
|
||||
}
|
||||
|
||||
private static String createLayerName(String name) {
|
||||
return TradingStation.MODID + ":" + name;
|
||||
}
|
||||
|
||||
// Mmm gimme those protected fields
|
||||
private RenderTypes() {
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD)
|
||||
private static class Shaders {
|
||||
private static ShaderInstance glowingShader;
|
||||
|
||||
/*@SubscribeEvent
|
||||
public static void onRegisterShaders(RegisterShadersEvent event) throws IOException {
|
||||
ResourceManager resourceManager = event.getResourceManager();
|
||||
event.registerShader(new ShaderInstance(resourceManager, TradingStation.asResource("glowing_shader"), DefaultVertexFormat.NEW_ENTITY), shader -> glowingShader = shader);
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.oierbravo.trading_station.foundation.util;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class ModLang {
|
||||
|
||||
public static Component translate(String key){
|
||||
return Component.translatable(TradingStation.MODID + '.' + key);
|
||||
}
|
||||
public static String key(String key){
|
||||
return TradingStation.MODID + '.' + key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.oierbravo.trading_station.network.packets;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class GhostItemSyncC2SPacket {
|
||||
private final ItemStack itemStack;
|
||||
private final BlockPos pos;
|
||||
|
||||
public GhostItemSyncC2SPacket(ItemStack itemStack, BlockPos pos) {
|
||||
this.itemStack = itemStack;
|
||||
this.pos = pos;
|
||||
|
||||
}
|
||||
|
||||
public GhostItemSyncC2SPacket(FriendlyByteBuf buf) {
|
||||
this.itemStack = buf.readItem();
|
||||
this.pos = buf.readBlockPos();
|
||||
|
||||
}
|
||||
|
||||
public void toBytes(FriendlyByteBuf buf) {
|
||||
buf.writeItem(itemStack);
|
||||
buf.writeBlockPos(pos);
|
||||
|
||||
}
|
||||
|
||||
public static void handle(GhostItemSyncC2SPacket message, Supplier<NetworkEvent.Context> supplier) {
|
||||
NetworkEvent.Context context = supplier.get();
|
||||
|
||||
context.enqueueWork(() -> {
|
||||
ServerPlayer sender = context.getSender();
|
||||
if (sender == null)
|
||||
return;
|
||||
|
||||
AbstractContainerMenu container = sender.containerMenu;
|
||||
if (container == null)
|
||||
return;
|
||||
|
||||
if(sender.getLevel().getBlockEntity(message.pos) instanceof TradingStationBlockEntity blockEntity) {
|
||||
blockEntity.setPreferedItem(message.itemStack);
|
||||
//blockEntity.setChanged();
|
||||
|
||||
}
|
||||
});
|
||||
context.setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.oierbravo.trading_station.network.packets;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ItemStackSyncS2CPacket {
|
||||
private final int slot;
|
||||
private final ItemStack itemStack;
|
||||
private final BlockPos pos;
|
||||
public enum SlotType {
|
||||
INPUT, OUTPUT, TARGET;
|
||||
}
|
||||
private final SlotType slotType;
|
||||
|
||||
public ItemStackSyncS2CPacket(int slot, ItemStack itemStack, BlockPos pos,SlotType slotType) {
|
||||
this.slot = slot;
|
||||
this.itemStack = itemStack;
|
||||
this.pos = pos;
|
||||
this.slotType = slotType;
|
||||
}
|
||||
|
||||
public ItemStackSyncS2CPacket(FriendlyByteBuf buf) {
|
||||
this.slot = buf.readInt();
|
||||
this.itemStack = buf.readItem();
|
||||
this.pos = buf.readBlockPos();
|
||||
this.slotType = SlotType.values()[buf.readInt()];
|
||||
}
|
||||
|
||||
public void toBytes(FriendlyByteBuf buf) {
|
||||
buf.writeInt(slot);
|
||||
buf.writeItem(itemStack);
|
||||
buf.writeBlockPos(pos);
|
||||
buf.writeInt(slotType.ordinal());
|
||||
|
||||
}
|
||||
|
||||
public static boolean handle(ItemStackSyncS2CPacket message, Supplier<NetworkEvent.Context> supplier) {
|
||||
NetworkEvent.Context context = supplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
if(Minecraft.getInstance().level.getBlockEntity(message.pos) instanceof TradingStationBlockEntity blockEntity) {
|
||||
blockEntity.setItemStack(message.slot,message.itemStack,message.slotType);
|
||||
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.oierbravo.trading_station.network.packets;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationMenu;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class OpenTargetSelectPacket {
|
||||
private BlockPos sourcePos;
|
||||
|
||||
public OpenTargetSelectPacket(BlockPos pSourcePos){
|
||||
this.sourcePos = pSourcePos;
|
||||
}
|
||||
public OpenTargetSelectPacket(FriendlyByteBuf buf){
|
||||
this(buf.readBlockPos());
|
||||
}
|
||||
|
||||
public void toBytes(FriendlyByteBuf buf) {
|
||||
buf.writeBlockPos(sourcePos);
|
||||
}
|
||||
public static boolean handle(OpenTargetSelectPacket message, Supplier<NetworkEvent.Context> supplier) {
|
||||
NetworkEvent.Context context = supplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
ServerPlayer sender = context.getSender();
|
||||
if (sender == null)
|
||||
return;
|
||||
|
||||
TradingStationMenu container = (TradingStationMenu) sender.containerMenu;
|
||||
if (container == null)
|
||||
return;
|
||||
|
||||
/*NetworkHooks.openScreen(sender, new SimpleMenuProvider(
|
||||
(windowId, playerInventory, playerEntity) -> new TradingTradeSelectMenu(windowId, message.sourcePos), Component.translatable("")), (buf -> {
|
||||
buf.writeBlockPos(message.sourcePos);
|
||||
}));*/
|
||||
NetworkHooks.openScreen(((ServerPlayer)sender), (TradingStationBlockEntity)container.blockEntity, message.sourcePos);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.oierbravo.trading_station.network.packets;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationMenu;
|
||||
import dev.latvian.mods.rhino.ast.Block;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class OpenTradingMenuPacket {
|
||||
protected BlockPos sourcePos;
|
||||
|
||||
public OpenTradingMenuPacket(BlockPos pSourcePos){
|
||||
this.sourcePos = pSourcePos;
|
||||
}
|
||||
public OpenTradingMenuPacket(FriendlyByteBuf buf){
|
||||
this(buf.readBlockPos());
|
||||
}
|
||||
|
||||
public void toBytes(FriendlyByteBuf buf) {
|
||||
buf.writeBlockPos(sourcePos);
|
||||
}
|
||||
|
||||
public BlockPos getSourcePos(){
|
||||
return sourcePos;
|
||||
}
|
||||
public static boolean handle(OpenTradingMenuPacket message, Supplier<NetworkEvent.Context> supplier) {
|
||||
NetworkEvent.Context context = supplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
ServerPlayer sender = context.getSender();
|
||||
if (sender == null)
|
||||
return;
|
||||
|
||||
AbstractContainerMenu container = sender.containerMenu;
|
||||
if (container == null)
|
||||
return;
|
||||
|
||||
NetworkHooks.openScreen(sender, new SimpleMenuProvider(
|
||||
(windowId, playerInventory, playerEntity) -> new TradingStationMenu(windowId,playerInventory,message.sourcePos), Component.translatable("trading_station.block.display")), (buf -> {
|
||||
buf.writeBlockPos(message.sourcePos);
|
||||
}));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.oierbravo.trading_station.registrate;
|
||||
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationConfig;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
//From https://github.com/McJty/TutorialV3/blob/1.19/src/main/java/com/example/tutorialv3/setup/Config.java
|
||||
public class Config {
|
||||
public static void register() {
|
||||
registerServerConfigs();
|
||||
//registerCommonConfigs();
|
||||
//registerClientConfigs();
|
||||
}
|
||||
private static void registerClientConfigs() {
|
||||
ForgeConfigSpec.Builder CLIENT_BUILDER = new ForgeConfigSpec.Builder();
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, CLIENT_BUILDER.build());
|
||||
}
|
||||
|
||||
private static void registerCommonConfigs() {
|
||||
ForgeConfigSpec.Builder COMMON_BUILDER = new ForgeConfigSpec.Builder();
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, COMMON_BUILDER.build());
|
||||
}
|
||||
|
||||
private static void registerServerConfigs() {
|
||||
ForgeConfigSpec.Builder SERVER_BUILDER = new ForgeConfigSpec.Builder();
|
||||
TradingStationConfig.registerServerConfig(SERVER_BUILDER);
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_BUILDER.build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.oierbravo.trading_station.registrate;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockRenderer;
|
||||
import com.oierbravo.trading_station.content.trading_station.powered.PoweredTradingStationBlockEntity;
|
||||
import com.tterrag.registrate.util.entry.BlockEntityEntry;
|
||||
|
||||
public class ModBlockEntities {
|
||||
public static final BlockEntityEntry<TradingStationBlockEntity> TRADING_STATION = TradingStation.registrate()
|
||||
.blockEntity("trading_station", TradingStationBlockEntity::new)
|
||||
.validBlocks(ModBlocks.TRADING_STATION)
|
||||
.renderer(() -> TradingStationBlockRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<PoweredTradingStationBlockEntity> POWERED_TRADING_STATION = TradingStation.registrate()
|
||||
.blockEntity("powered_trading_station", PoweredTradingStationBlockEntity::new)
|
||||
.validBlocks(ModBlocks.POWERED_TRADING_STATION)
|
||||
.renderer(() -> TradingStationBlockRenderer::new)
|
||||
.register();
|
||||
public static void register() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.oierbravo.trading_station.registrate;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlock;
|
||||
import com.oierbravo.trading_station.content.trading_station.powered.PoweredTradingStationBlock;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationBlockEntity;
|
||||
import com.oierbravo.trading_station.content.trading_station.powered.PoweredTradingStationBlockEntity;
|
||||
|
||||
import com.tterrag.registrate.Registrate;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraftforge.client.model.generators.ConfiguredModel;
|
||||
|
||||
public class ModBlocks {
|
||||
private static final Registrate REGISTRATE = TradingStation.registrate()
|
||||
.creativeModeTab(() -> ModCreativeTab.MAIN);
|
||||
public static final BlockEntry<TradingStationBlock> TRADING_STATION = TradingStation.registrate()
|
||||
.block("trading_station", TradingStationBlock::new)
|
||||
.lang("Trading Station")
|
||||
.blockstate((ctx, prov) ->
|
||||
prov.getVariantBuilder(ctx.getEntry()).forAllStates(state -> {
|
||||
String modelFileName = "trading_station:block/trading_station";
|
||||
if(state.getValue(BlockStateProperties.POWERED))
|
||||
modelFileName += "_powered";
|
||||
return ConfiguredModel.builder().modelFile(prov.models().getExistingFile(ResourceLocation.tryParse(modelFileName)))
|
||||
.rotationY(((int) state.getValue(BlockStateProperties.HORIZONTAL_FACING).toYRot() + 180) % 360).build();
|
||||
|
||||
})
|
||||
)
|
||||
.simpleItem()
|
||||
.blockEntity(TradingStationBlockEntity::new)
|
||||
.build()
|
||||
.register();
|
||||
public static final BlockEntry<PoweredTradingStationBlock> POWERED_TRADING_STATION = TradingStation.registrate()
|
||||
.block("powered_trading_station", PoweredTradingStationBlock::new)
|
||||
.lang("Powered Trading Station")
|
||||
.blockstate((ctx, prov) ->
|
||||
prov.getVariantBuilder(ctx.getEntry()).forAllStates(state -> {
|
||||
String modelFileName = "trading_station:block/powered_trading_station";
|
||||
if(state.getValue(BlockStateProperties.POWERED))
|
||||
modelFileName += "_powered";
|
||||
return ConfiguredModel.builder().modelFile(prov.models().getExistingFile(ResourceLocation.tryParse(modelFileName)))
|
||||
.rotationY(((int) state.getValue(BlockStateProperties.HORIZONTAL_FACING).toYRot() + 180) % 360).build();
|
||||
|
||||
})
|
||||
)
|
||||
.simpleItem()
|
||||
.blockEntity(PoweredTradingStationBlockEntity::new)
|
||||
.build()
|
||||
.register();
|
||||
public static void register() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.oierbravo.trading_station.registrate;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ModCreativeTab extends CreativeModeTab {
|
||||
public static ModCreativeTab MAIN;
|
||||
|
||||
|
||||
public ModCreativeTab() {
|
||||
super(TradingStation.DISPLAY_NAME);
|
||||
MAIN = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack makeIcon() {
|
||||
return new ItemStack(ModBlocks.TRADING_STATION.get());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.oierbravo.trading_station.registrate;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationMenu;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingStationScreen;
|
||||
import com.tterrag.registrate.util.entry.MenuEntry;
|
||||
import com.tterrag.registrate.util.entry.RegistryEntry;
|
||||
import net.minecraft.client.gui.screens.inventory.ContainerScreen;
|
||||
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.inventory.ChestMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
|
||||
public class ModMenus {
|
||||
public static final MenuEntry<TradingStationMenu> TRADING_STATION = TradingStation.registrate()
|
||||
.menu("trading_station",TradingStationMenu::factory, () -> TradingStationScreen::new)
|
||||
.register();
|
||||
|
||||
public static final MenuEntry<TradingStationMenu> TRADING_STATION_TRADE_SELECT = TradingStation.registrate()
|
||||
.menu("trading_station_trade_select",TradingStationMenu::factory, () -> TradingStationScreen::new)
|
||||
.register();
|
||||
public static void register() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.oierbravo.trading_station.registrate;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.network.packets.GhostItemSyncC2SPacket;
|
||||
import com.oierbravo.trading_station.network.packets.ItemStackSyncS2CPacket;
|
||||
import com.oierbravo.trading_station.network.packets.OpenTargetSelectPacket;
|
||||
import com.oierbravo.trading_station.network.packets.OpenTradingMenuPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
|
||||
public class ModMessages {
|
||||
private static SimpleChannel INSTANCE;
|
||||
|
||||
private static int packetId = 0;
|
||||
private static int id() {
|
||||
return packetId++;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
SimpleChannel net = NetworkRegistry.ChannelBuilder
|
||||
.named(new ResourceLocation(TradingStation.MODID, "messages"))
|
||||
.networkProtocolVersion(() -> "1.0")
|
||||
.clientAcceptedVersions(s -> true)
|
||||
.serverAcceptedVersions(s -> true)
|
||||
.simpleChannel();
|
||||
|
||||
INSTANCE = net;
|
||||
|
||||
|
||||
net.messageBuilder(ItemStackSyncS2CPacket.class, id(), NetworkDirection.PLAY_TO_CLIENT)
|
||||
.decoder(ItemStackSyncS2CPacket::new)
|
||||
.encoder(ItemStackSyncS2CPacket::toBytes)
|
||||
.consumerMainThread(ItemStackSyncS2CPacket::handle)
|
||||
.add();
|
||||
|
||||
net.messageBuilder(GhostItemSyncC2SPacket.class, id(), NetworkDirection.PLAY_TO_SERVER)
|
||||
.decoder(GhostItemSyncC2SPacket::new)
|
||||
.encoder(GhostItemSyncC2SPacket::toBytes)
|
||||
.consumerMainThread(GhostItemSyncC2SPacket::handle)
|
||||
.add();
|
||||
|
||||
net.messageBuilder(OpenTradingMenuPacket.class, id(), NetworkDirection.PLAY_TO_SERVER)
|
||||
.decoder(OpenTradingMenuPacket::new)
|
||||
.encoder(OpenTradingMenuPacket::toBytes)
|
||||
.consumerMainThread(OpenTradingMenuPacket::handle)
|
||||
.add();
|
||||
|
||||
net.messageBuilder(OpenTargetSelectPacket.class, id(), NetworkDirection.PLAY_TO_SERVER)
|
||||
.decoder(OpenTargetSelectPacket::new)
|
||||
.encoder(OpenTargetSelectPacket::toBytes)
|
||||
.consumerMainThread(OpenTargetSelectPacket::handle)
|
||||
.add();
|
||||
}
|
||||
|
||||
public static <MSG> void sendToServer(MSG message) {
|
||||
INSTANCE.sendToServer(message);
|
||||
}
|
||||
|
||||
public static <MSG> void sendToPlayer(MSG message, ServerPlayer player) {
|
||||
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
|
||||
}
|
||||
|
||||
public static <MSG> void sendToClients(MSG message) {
|
||||
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.oierbravo.trading_station.registrate;
|
||||
|
||||
import com.oierbravo.trading_station.TradingStation;
|
||||
import com.oierbravo.trading_station.content.trading_station.TradingRecipe;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ModRecipes {
|
||||
public static final DeferredRegister<RecipeSerializer<?>> SERIALIZERS =
|
||||
DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, TradingStation.MODID);
|
||||
public static final DeferredRegister<RecipeType<?>> RECIPE_TYPES = DeferredRegister.create(ForgeRegistries.RECIPE_TYPES, TradingStation.MODID);
|
||||
|
||||
public static final RegistryObject<RecipeType<TradingRecipe>> TRADING_TYPE =
|
||||
RECIPE_TYPES.register("trading",() -> TradingRecipe.Type.INSTANCE);
|
||||
|
||||
public static final RegistryObject<RecipeSerializer<TradingRecipe>> TRADING_SERIALIZER =
|
||||
SERIALIZERS.register("trading", () -> TradingRecipe.Serializer.INSTANCE);
|
||||
|
||||
public static Optional<TradingRecipe> find(SimpleContainer pInv, Level pLevel) {
|
||||
if(pLevel.isClientSide())
|
||||
return Optional.empty();
|
||||
return pLevel.getRecipeManager().getRecipeFor(TradingRecipe.Type.INSTANCE,pInv,pLevel);
|
||||
}
|
||||
/*public static List<ItemStack> getAllOutputs(Level pLevel){
|
||||
List<ItemStack> allOutputs = pLevel.getRecipeManager().getAllRecipesFor(TradingRecipe.Type.INSTANCE).stream()
|
||||
.map(TradingRecipe::getResult).toList();
|
||||
allOutputs.add(ItemStack.EMPTY);
|
||||
return allOutputs;
|
||||
|
||||
}*/
|
||||
public static List<ItemStack> getAllOutputs(Level pLevel){
|
||||
return pLevel.getRecipeManager().getAllRecipesFor(TradingRecipe.Type.INSTANCE).stream()
|
||||
.map(TradingRecipe::getResult).toList();
|
||||
|
||||
}
|
||||
public static Optional<TradingRecipe> findByOutput(Level pLevel,ItemStack targetedOutput){
|
||||
//if(pLevel.isClientSide())
|
||||
// return Optional.empty();
|
||||
return pLevel.getRecipeManager().getAllRecipesFor(TradingRecipe.Type.INSTANCE).stream()
|
||||
.filter(recipe -> recipe.matchesOutput(targetedOutput)).findFirst();
|
||||
|
||||
}
|
||||
/*public static Optional<TradingRecipe> findWithPreferdOutput(SimpleContainer pInv, Level pLevel, ItemStack preferedOutput){
|
||||
if(pLevel.isClientSide())
|
||||
return Optional.empty();
|
||||
List<TradingRecipe> allTradingRecipes = pLevel.getRecipeManager().getAllRecipesFor(TradingRecipe.Type.INSTANCE);
|
||||
|
||||
return allTradingRecipes.stream().filter(extrudingRecipe -> TradingRecipe.matches(tradingStation,tradingRecipe)).findFirst();
|
||||
|
||||
}*/
|
||||
public static void register(IEventBus eventBus) {
|
||||
SERIALIZERS.register(eventBus);
|
||||
|
||||
RECIPE_TYPES.register(eventBus);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user