PUsh current stuff including REI. REI doesn't work right yet.

This commit is contained in:
Waterpicker 2023-11-12 12:21:28 -06:00
parent 551061d57f
commit 8097a342e5
39 changed files with 1486 additions and 764 deletions

View file

@ -20,8 +20,8 @@ dependencies {
modApi("com.sk89q.worldedit:worldedit-core:${project.properties["worldedit"]}")
// modCompileOnly("me.shedaniel:RoughlyEnoughItems-api:${project.properties["rei_version"]}")
// modCompileOnly("me.shedaniel:RoughlyEnoughItems-default-plugin:${project.properties["rei_version"]}")
modCompileOnly("me.shedaniel:RoughlyEnoughItems-api:${project.properties["rei_version"]}")
modCompileOnly("me.shedaniel:RoughlyEnoughItems-default-plugin:${project.properties["rei_version"]}")
}
sourceSets.main {

View file

@ -1,6 +1,5 @@
package org.dimdev.dimdoors;
import dev.architectury.event.events.client.ClientPlayerEvent;
import dev.architectury.event.events.common.InteractionEvent;
import dev.architectury.event.events.common.TickEvent;
import dev.architectury.injectables.annotations.ExpectPlatform;
@ -18,7 +17,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.packs.PackType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.RecipeBookType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -26,15 +24,11 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
import org.dimdev.dimdoors.api.event.ChunkServedCallback;
import org.dimdev.dimdoors.api.event.UseItemOnBlockCallback;
import org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.door.DimensionalDoorBlockRegistrar;
import org.dimdev.dimdoors.block.entity.DetachedRiftBlockEntity;
import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity;
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
import org.dimdev.dimdoors.client.ModRecipeBookGroups;
import org.dimdev.dimdoors.client.ModRecipeBookTypes;
import org.dimdev.dimdoors.client.config.ModMenu;
import org.dimdev.dimdoors.command.ModCommands;
import org.dimdev.dimdoors.criteria.ModCriteria;
import org.dimdev.dimdoors.enchantment.ModEnchants;
@ -53,8 +47,6 @@ import org.dimdev.dimdoors.listener.pocket.UseBlockCallbackListener;
import org.dimdev.dimdoors.listener.pocket.UseItemCallbackListener;
import org.dimdev.dimdoors.listener.pocket.UseItemOnBlockCallbackListener;
import org.dimdev.dimdoors.network.ServerPacketHandler;
import org.dimdev.dimdoors.network.client.ClientPacketHandler;
import org.dimdev.dimdoors.network.packet.c2s.NetworkHandlerInitializedC2SPacket;
import org.dimdev.dimdoors.particle.ModParticleTypes;
import org.dimdev.dimdoors.pockets.PocketLoader;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
@ -71,17 +63,15 @@ import org.dimdev.dimdoors.util.schematic.SchemFixer;
import org.dimdev.dimdoors.world.ModBiomes;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.ModStructures;
import org.dimdev.dimdoors.world.decay.Decay;
import org.dimdev.dimdoors.world.decay.DecayPredicate;
import org.dimdev.dimdoors.world.decay.DecayProcessor;
import org.dimdev.dimdoors.world.decay.Decay;
import org.dimdev.dimdoors.world.feature.ModFeatures;
import org.dimdev.dimdoors.world.pocket.type.AbstractPocket;
import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static org.dimdev.dimdoors.block.door.WaterLoggableDoorBlock.WATERLOGGED;
@ -143,14 +133,7 @@ public class DimensionalDoors {
ModCriteria.init();
ModEnchants.init();
RegisterRecipeBookCategoriesEvent.EVENT.register(event -> {
ModRecipeBookTypes.init();
ModRecipeBookGroups.init();
event.registerAggregateCategory(ModRecipeBookGroups.TESSELATING_SEARCH.get(), List.of(ModRecipeBookGroups.TESSELATING_GENERAL.get()));
event.registerBookCategories(ModRecipeBookTypes.TESSELLATING, ModRecipeBookGroups.TESSELATING_CATEGORIES.get());
event.registerRecipeCategoryFinder(ModRecipeTypes.TESSELATING.get(), recipe -> ModRecipeBookGroups.TESSELATING_GENERAL.get());
});
// ModRecipeBookTypes.init();
dimensionalDoorItemRegistrar = new DimensionalDoorItemRegistrar();
dimensionalDoorBlockRegistrar = new DimensionalDoorBlockRegistrar(dimensionalDoorItemRegistrar);

View file

@ -14,28 +14,36 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
/*
public record RegisterRecipeBookCategoriesEvent(BiConsumer<RecipeBookCategories, List<RecipeBookCategories>> categoryAggregateCategory, BiConsumer<RecipeBookType, List<RecipeBookCategories>> bookCategories, BiConsumer<RecipeType<?>, Function<Recipe<?>, RecipeBookCategories>> recipeCategoryFinder) {
public static final Event<Consumer<RegisterRecipeBookCategoriesEvent>> EVENT = EventFactory.createConsumerLoop();
/**
* Registers the list of categories that compose an aggregate category.
*/
/**
* Registers the list of categories that compose an aggregate category.
*//*
public void registerAggregateCategory(RecipeBookCategories category, List<RecipeBookCategories> other) {
categoryAggregateCategory.accept(category, other);
}
/**
* Registers the list of categories that compose a recipe book.
*/
/**
* Registers the list of categories that compose a recipe book.
*//*
public void registerBookCategories(RecipeBookType type, List<RecipeBookCategories> categories) {
bookCategories.accept(type, categories);
}
/**
* Registers a category lookup for a certain recipe type.
*/
/**
* Registers a category lookup for a certain recipe type.
*//*
public void registerRecipeCategoryFinder(RecipeType<?> type, Function<Recipe<?>, RecipeBookCategories> categoriesFunction) {
recipeCategoryFinder.accept(type, categoriesFunction);
}
}
*/

View file

@ -235,7 +235,7 @@ public class TesselatingLoomBlockEntity extends BlockEntity implements MenuProvi
this.inventory.clear();
}
private Optional<TesselatingRecipe> getCurrentRecipe() {
private Optional<? extends TesselatingRecipe> getCurrentRecipe() {
// No need to find recipes if the inventory is empty. Cannot craft anything.
if (this.level == null || this.isEmpty()) return Optional.empty();
@ -243,12 +243,37 @@ public class TesselatingLoomBlockEntity extends BlockEntity implements MenuProvi
RecipeManager manager = this.level.getRecipeManager();
if (lastRecipe != null) {
TesselatingRecipe mapRecipe = manager.byType(ModRecipeTypes.TESSELATING.get()).get(lastRecipe);
TesselatingRecipe mapRecipe = getRecipe(lastRecipe.getId());
if (mapRecipe != null && mapRecipe.matches(this, level)) {
return Optional.of(lastRecipe);
}
}
return manager.getRecipeFor(ModRecipeTypes.TESSELATING.get(), this, level);
return getRecipe();
}
public <T extends TesselatingRecipe> TesselatingRecipe getRecipe(ResourceLocation location) {
var manager = this.level.getRecipeManager();
TesselatingRecipe recipe = manager.byType(ModRecipeTypes.SHAPED_TESSELATING.get()).get(location);
if(recipe == null) {
recipe = manager.byType(ModRecipeTypes.SHAPELESS_TESSELATING.get()).get(location);
}
return recipe;
}
public Optional<? extends TesselatingRecipe> getRecipe() {
var manager = this.level.getRecipeManager();
var recipe = manager.getRecipeFor(ModRecipeTypes.SHAPED_TESSELATING.get(), this, level);
if(recipe.isEmpty()) {
return manager.getRecipeFor(ModRecipeTypes.SHAPELESS_TESSELATING.get(), this, level);
} else {
return recipe;
}
}
@ -258,7 +283,7 @@ public class TesselatingLoomBlockEntity extends BlockEntity implements MenuProvi
return Optional.of(maybe_result.orElse(ItemStack.EMPTY));
}
protected boolean canSmelt(ItemStack result, TesselatingRecipe recipe) {
protected boolean canWeave(ItemStack result, TesselatingRecipe recipe) {
if (recipe.matches(this, null)) {
ItemStack outstack = output;
if (outstack.isEmpty()) {
@ -274,13 +299,13 @@ public class TesselatingLoomBlockEntity extends BlockEntity implements MenuProvi
}
private int getWeavingTime() {
return getCurrentRecipe().map(a -> a.weavingTime()).orElse(DEFAULT_WEAVE_TIME);
return getCurrentRecipe().map(TesselatingRecipe::weavingTime).orElse(DEFAULT_WEAVE_TIME);
}
protected void smelt(ItemStack result, TesselatingRecipe recipe) {
protected void weave(ItemStack result, TesselatingRecipe recipe) {
if(recipe.isIncomplete()) return;
if (!result.isEmpty() && this.canSmelt(result, recipe)) {
if (!result.isEmpty() && this.canWeave(result, recipe)) {
ItemStack outstack = output.copy();
if (outstack.isEmpty()) {
@ -321,10 +346,10 @@ public class TesselatingLoomBlockEntity extends BlockEntity implements MenuProvi
if (!level.isClientSide()) {
ItemStack result = tile.getResult().orElse(ItemStack.EMPTY);
Optional<TesselatingRecipe> recipe = tile.getCurrentRecipe();
Optional<? extends TesselatingRecipe> recipe = tile.getCurrentRecipe();
if (recipe.isPresent() && (!tile.isInputEmpty())) {
if (tile.canSmelt(result, recipe.get())) {
if (tile.canWeave(result, recipe.get())) {
if (tile.weaveTime <= 0) {
tile.weaveTimeTotal = tile.getWeavingTime();
tile.weaveTime = 0;
@ -337,7 +362,7 @@ public class TesselatingLoomBlockEntity extends BlockEntity implements MenuProvi
}
if (tile.weaveTime >= tile.weaveTimeTotal) {
tile.smelt(result, recipe.get());
tile.weave(result, recipe.get());
tile.weaveTime = 0;
tile.weaveTimeTotal = !tile.isInputEmpty() ? tile.getWeavingTime() : 0;

View file

@ -3,8 +3,6 @@ package org.dimdev.dimdoors.client;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import dev.architectury.event.events.client.ClientPlayerEvent;
import dev.architectury.event.events.client.ClientReloadShadersEvent;
import dev.architectury.registry.client.level.entity.EntityRendererRegistry;
import dev.architectury.registry.client.particle.ParticleProviderRegistry;
import dev.architectury.registry.client.rendering.BlockEntityRendererRegistry;
import dev.architectury.registry.menu.MenuRegistry;
import me.shedaniel.autoconfig.AutoConfig;
@ -12,22 +10,15 @@ import me.shedaniel.autoconfig.util.Utils;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.client.particle.SpriteSet;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.inventory.RecipeBookType;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeType;
import org.dimdev.dimdoors.ModConfig;
import org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
import org.dimdev.dimdoors.client.screen.TesselatingLoomScreen;
@ -37,7 +28,6 @@ import org.dimdev.dimdoors.network.packet.c2s.NetworkHandlerInitializedC2SPacket
import org.dimdev.dimdoors.particle.client.LimboAshParticle;
import org.dimdev.dimdoors.particle.client.MonolithParticle;
import org.dimdev.dimdoors.particle.client.RiftParticle;
import org.dimdev.dimdoors.recipe.ModRecipeTypes;
import org.dimdev.dimdoors.screen.ModScreenHandlerTypes;
import java.io.IOException;
@ -48,7 +38,9 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -76,7 +68,7 @@ public class DimensionalDoorsClient {
ClientPacketHandler.init();
// ModRecipeBookGroups.init();
}
@Environment(EnvType.CLIENT)

View file

@ -1,33 +1,19 @@
package org.dimdev.dimdoors.client;
import com.google.common.base.Suppliers;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.item.ModItems;
//public class ModRecipeBookGroups {
// public static final Supplier<RecipeBookCategories> TESSELATING_GENERAL = Suppliers.memoize(() -> getRecipBookCategories("TESSELATING_GENERAL", () -> ModItems.WORLD_THREAD.get().getDefaultInstance()).get());
// public static final Supplier<RecipeBookCategories> TESSELATING_SEARCH = Suppliers.memoize(() -> getRecipBookCategories("TESSELATING_SEARCH", Items.COMPASS::getDefaultInstance).get());
import java.util.List;
import java.util.function.Supplier;
// @ExpectPlatform
// private static Supplier<RecipeBookCategories> getRecipBookCategories(String name, Supplier<ItemStack> itemStack) {
// throw new RuntimeException();
// }
public class ModRecipeBookGroups {
public static final Supplier<RecipeBookCategories> TESSELATING_GENERAL = Suppliers.memoize(() -> getRecipBookCategories("TESSELATING_GENERAL", () -> ModItems.WORLD_THREAD.get().getDefaultInstance()).get());
public static final Supplier<RecipeBookCategories> TESSELATING_SEARCH = Suppliers.memoize(() -> getRecipBookCategories("TESSELATING_SEARCH", Items.COMPASS::getDefaultInstance).get());
public static final Supplier<List<RecipeBookCategories>> TESSELATING_CATEGORIES = Suppliers.memoize(() -> List.of(TESSELATING_GENERAL.get()));
@ExpectPlatform
private static Supplier<RecipeBookCategories> getRecipBookCategories(String name, Supplier<ItemStack> itemStack) {
throw new RuntimeException();
}
public static void init() {
System.out.println("Blarg: " + TESSELATING_GENERAL.get());
System.out.println("Blarg: " + TESSELATING_SEARCH.get());
System.out.println("Blarg: " + TESSELATING_CATEGORIES.get());
}
}
// public static void init() {
// RegisterRecipeBookCategoriesEvent.EVENT.register(event -> {
// event.registerBookCategories(ModRecipeBookTypes.TESSELLATING, List.of(TESSELATING_GENERAL.get(), TESSELATING_SEARCH.get()));
// event.registerAggregateCategory(ModRecipeBookGroups.TESSELATING_SEARCH.get(), List.of(ModRecipeBookGroups.TESSELATING_GENERAL.get()));
// event.registerRecipeCategoryFinder(ModRecipeTypes.TESSELATING.get(), recipe -> ModRecipeBookGroups.TESSELATING_GENERAL.get());
// });
// }
//}

View file

@ -3,14 +3,14 @@ package org.dimdev.dimdoors.client;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.world.inventory.RecipeBookType;
public class ModRecipeBookTypes {
public static RecipeBookType TESSELLATING = getRecipeBookType("TESSELLATING");
@ExpectPlatform
private static RecipeBookType getRecipeBookType(String name) {
throw new RuntimeException();
}
public static void init() {
}
}
//public class ModRecipeBookTypes {
// public static RecipeBookType TESSELLATING = getRecipeBookType("TESSELLATING");
//
// @ExpectPlatform
// private static RecipeBookType getRecipeBookType(String name) {
// throw new RuntimeException();
// }
//
// public static void init() {
// }
//}

View file

@ -28,7 +28,7 @@ import net.fabricmc.api.Environment;
// - - turn counter-clockwise by angle
// [ - save state (push to stack)
// ] - restore state (pop from stack)
@Environment(EnvType.CLIENT)
//@Environment(EnvType.CLIENT)
public final class RiftCurves {
public static final List<PolygonInfo> CURVES = new ArrayList<>();

View file

@ -13,12 +13,12 @@ import net.minecraft.world.inventory.Slot;
import org.dimdev.dimdoors.DimensionalDoors;
import org.dimdev.dimdoors.screen.TessellatingContainer;
public class TesselatingLoomScreen extends AbstractContainerScreen<TessellatingContainer> implements RecipeUpdateListener {
public class TesselatingLoomScreen extends AbstractContainerScreen<TessellatingContainer> /*implements RecipeUpdateListener*/ {
private static final ResourceLocation TEXTURE = DimensionalDoors.id("textures/screen/container/tesselating_loom.png");
private static final ResourceLocation RECIPE_BUTTON_TEXTURE = new ResourceLocation("textures/gui/recipe_button.png");
private final RecipeBookComponent recipeBook = new RecipeBookComponent();
private boolean narrow;
// private final RecipeBookComponent recipeBook = new RecipeBookComponent();
// private boolean narrow;
public TesselatingLoomScreen(TessellatingContainer handler, Inventory inventory, Component title) {
super(handler, inventory, title);
@ -26,33 +26,33 @@ public class TesselatingLoomScreen extends AbstractContainerScreen<TessellatingC
public void init() {
super.init();
this.narrow = this.width < 379;
this.recipeBook.init(this.width, this.height, this.minecraft, this.narrow, this.menu);
this.leftPos = this.recipeBook.updateScreenPosition(this.width, this.imageWidth);
this.addRenderableWidget(new ImageButton(this.leftPos + 5, this.height / 2 - 49, 20, 18, 0, 0, 19, RECIPE_BUTTON_TEXTURE, (button) -> {
this.recipeBook.toggleVisibility();
this.leftPos = this.recipeBook.updateScreenPosition(this.width, this.imageWidth);
button.setPosition(this.leftPos + 5, this.height / 2 - 49);
}));
this.addWidget(this.recipeBook);
this.setInitialFocus(this.recipeBook);
// this.narrow = this.width < 379;
// this.recipeBook.init(this.width, this.height, this.minecraft, this.narrow, this.menu);
// this.leftPos = this.recipeBook.updateScreenPosition(this.width, this.imageWidth);
// this.addRenderableWidget(new ImageButton(this.leftPos + 5, this.height / 2 - 49, 20, 18, 0, 0, 19, RECIPE_BUTTON_TEXTURE, (button) -> {
// this.recipeBook.toggleVisibility();
// this.leftPos = this.recipeBook.updateScreenPosition(this.width, this.imageWidth);
// button.setPosition(this.leftPos + 5, this.height / 2 - 49);
// }));
// this.addWidget(this.recipeBook);
// this.setInitialFocus(this.recipeBook);
this.titleLabelX = (this.imageWidth - this.font.width(this.title)) / 2;
}
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices);
if (this.recipeBook.isVisible() && this.narrow) {
this.renderBg(matrices, delta, mouseX, mouseY);
this.recipeBook.render(matrices, mouseX, mouseY, delta);
} else {
this.recipeBook.render(matrices, mouseX, mouseY, delta);
// if (this.recipeBook.isVisible() && this.narrow) {
// this.renderBg(matrices, delta, mouseX, mouseY);
// this.recipeBook.render(matrices, mouseX, mouseY, delta);
// } else {
// this.recipeBook.render(matrices, mouseX, mouseY, delta);
super.render(matrices, mouseX, mouseY, delta);
this.recipeBook.renderGhostRecipe(matrices, this.leftPos, this.topPos, true, delta);
}
// this.recipeBook.renderGhostRecipe(matrices, this.leftPos, this.topPos, true, delta);
// }
this.renderTooltip(matrices, mouseX, mouseY);
this.recipeBook.renderTooltip(matrices, this.leftPos, this.topPos, mouseX, mouseY);
// this.recipeBook.renderTooltip(matrices, this.leftPos, this.topPos, mouseX, mouseY);
}
protected void renderBg(GuiGraphics matrices, float delta, int mouseX, int mouseY) {
@ -67,33 +67,33 @@ public class TesselatingLoomScreen extends AbstractContainerScreen<TessellatingC
}
protected boolean isHovering(int x, int y, int width, int height, double pointX, double pointY) {
return (!this.narrow || !this.recipeBook.isVisible()) && super.isHovering(x, y, width, height, pointX, pointY);
return /*(!this.narrow || !this.recipeBook.isVisible()) && */super.isHovering(x, y, width, height, pointX, pointY);
}
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (this.recipeBook.mouseClicked(mouseX, mouseY, button)) {
this.setFocused(this.recipeBook);
return true;
} else {
return this.narrow && this.recipeBook.isVisible() || super.mouseClicked(mouseX, mouseY, button);
}
// if (this.recipeBook.mouseClicked(mouseX, mouseY, button)) {
// this.setFocused(this.recipeBook);
// return true;
// } else {
return /*this.narrow && this.recipeBook.isVisible() ||*/ super.mouseClicked(mouseX, mouseY, button);
// }
}
protected boolean hasClickedOutside(double mouseX, double mouseY, int left, int top, int button) {
boolean bl = mouseX < (double)left || mouseY < (double)top || mouseX >= (double)(left + this.imageWidth) || mouseY >= (double)(top + this.imageHeight);
return this.recipeBook.hasClickedOutside(mouseX, mouseY, this.leftPos, this.topPos, this.imageWidth, this.imageHeight, button) && bl;
return /*this.recipeBook.hasClickedOutside(mouseX, mouseY, this.leftPos, this.topPos, this.imageWidth, this.imageHeight, button) &&*/ bl;
}
protected void slotClicked(Slot slot, int slotId, int button, ClickType actionType) {
super.slotClicked(slot, slotId, button, actionType);
this.recipeBook.slotClicked(slot);
// this.recipeBook.slotClicked(slot);
}
public void recipesUpdated() {
this.recipeBook.recipesUpdated();
}
// public void recipesUpdated() {
// this.recipeBook.recipesUpdated();
// }
public RecipeBookComponent getRecipeBookComponent() {
return this.recipeBook;
}
// public RecipeBookComponent getRecipeBookComponent() {
// return this.recipeBook;
// }
}

View file

@ -0,0 +1,94 @@
package org.dimdev.dimdoors.compat.rei;
import com.google.common.collect.Lists;
import me.shedaniel.math.Point;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.gui.Renderer;
import me.shedaniel.rei.api.client.gui.widgets.Slot;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.api.client.registry.display.DisplayCategory;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.DisplayMerger;
import me.shedaniel.rei.api.common.entry.EntryIngredient;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.entry.InputIngredient;
import me.shedaniel.rei.api.common.util.EntryStacks;
import net.minecraft.network.chat.Component;
import org.dimdev.dimdoors.block.ModBlocks;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import java.util.List;
public class DefaultTesselatingCategory implements DisplayCategory<DefaultTesselatingDisplay<?>> {
@Override
public CategoryIdentifier<? extends DefaultTesselatingDisplay<?>> getCategoryIdentifier() {
return TesselatingReiCompatClient.TESSELATING;
}
@Override
public Renderer getIcon() {
return EntryStacks.of(ModBlocks.TESSELATING_LOOM.get());
}
@Override
public Component getTitle() {
return Component.translatable("category.dimdoors.tesselating");
}
@Override
public List<Widget> setupDisplay(DefaultTesselatingDisplay<?> display, Rectangle bounds) {
Point startPoint = new Point(bounds.getCenterX() - 58, bounds.getCenterY() - 27);
List<Widget> widgets = Lists.newArrayList();
widgets.add(Widgets.createRecipeBase(bounds));
widgets.add(Widgets.createArrow(new Point(startPoint.x + 60, startPoint.y + 18)).animationDurationTicks(display.getWeavingTime()));
widgets.add(Widgets.createResultSlotBackground(new Point(startPoint.x + 95, startPoint.y + 19)));
List<InputIngredient<EntryStack<?>>> input = display.getInputIngredients(3, 3);
List<Slot> slots = Lists.newArrayList();
for (int y = 0; y < 3; y++)
for (int x = 0; x < 3; x++)
slots.add(Widgets.createSlot(new Point(startPoint.x + 1 + x * 18, startPoint.y + 1 + y * 18)).markInput());
for (InputIngredient<EntryStack<?>> ingredient : input) {
slots.get(ingredient.getIndex()).entries(ingredient.get());
}
widgets.addAll(slots);
widgets.add(Widgets.createSlot(new Point(startPoint.x + 95, startPoint.y + 19)).entries(display.getOutputEntries().get(0)).disableBackground().markOutput());
if (display.isShapeless()) {
widgets.add(Widgets.createShapelessIcon(bounds));
}
return widgets;
}
@Override
@Nullable
public DisplayMerger<DefaultTesselatingDisplay<?>> getDisplayMerger() {
return new DisplayMerger<>() {
@Override
public boolean canMerge(DefaultTesselatingDisplay<?> first, DefaultTesselatingDisplay<?> second) {
if (!first.getCategoryIdentifier().equals(second.getCategoryIdentifier())) return false;
if (!equals(first.getOrganisedInputEntries(3, 3), second.getOrganisedInputEntries(3, 3))) return false;
if (!equals(first.getOutputEntries(), second.getOutputEntries())) return false;
if (first.isShapeless() != second.isShapeless()) return false;
if (first.getWidth() != second.getWidth()) return false;
if (first.getHeight() != second.getHeight()) return false;
return true;
}
@Override
public int hashOf(DefaultTesselatingDisplay<?> display) {
return display.getCategoryIdentifier().hashCode() * 31 * 31 * 31 + display.getOrganisedInputEntries(3, 3).hashCode() * 31 * 31 + display.getOutputEntries().hashCode();
}
private boolean equals(List<EntryIngredient> l1, List<EntryIngredient> l2) {
if (l1.size() != l2.size()) return false;
Iterator<EntryIngredient> it1 = l1.iterator();
Iterator<EntryIngredient> it2 = l2.iterator();
while (it1.hasNext() && it2.hasNext()) {
if (!it1.next().equals(it2.next())) return false;
}
return true;
}
};
}
}

View file

@ -0,0 +1,221 @@
package org.dimdev.dimdoors.compat.rei;
import dev.architectury.platform.Platform;
import it.unimi.dsi.fastutil.ints.IntIntImmutablePair;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.SimpleGridMenuDisplay;
import me.shedaniel.rei.api.common.display.basic.BasicDisplay;
import me.shedaniel.rei.api.common.entry.EntryIngredient;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.entry.InputIngredient;
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes;
import me.shedaniel.rei.api.common.transfer.info.MenuInfo;
import me.shedaniel.rei.api.common.transfer.info.MenuSerializationContext;
import me.shedaniel.rei.api.common.transfer.info.simple.SimpleGridMenuInfo;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.api.common.util.EntryIngredients;
import me.shedaniel.rei.plugin.common.BuiltinPlugin;
import me.shedaniel.rei.plugin.common.displays.crafting.*;
import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.ShapedRecipe;
import org.dimdev.dimdoors.recipe.ShapedTesselatingRecipe;
import org.dimdev.dimdoors.recipe.TesselatingShapelessRecipe;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
@SuppressWarnings("removal")
public abstract class DefaultTesselatingDisplay<C extends Recipe<?>> extends BasicDisplay implements SimpleGridMenuDisplay {
protected Optional<C> recipe;
private final int weavingTime;
public DefaultTesselatingDisplay(List<EntryIngredient> inputs, List<EntryIngredient> outputs, Optional<C> recipe, int weavingTime) {
this(inputs, outputs, recipe.map(Recipe::getId), recipe, weavingTime);
}
public DefaultTesselatingDisplay(List<EntryIngredient> inputs, List<EntryIngredient> outputs, Optional<ResourceLocation> location, Optional<C> recipe, int weavingTime) {
super(inputs, outputs, location);
this.recipe = recipe;
this.weavingTime = weavingTime;
}
// private static final List<CraftingRecipeSizeProvider<?>> SIZE_PROVIDER = new ArrayList<>();
// static {
// try {
// Class.forName("me.shedaniel.rei.plugin.common.displays.crafting.%s.DefaultCraftingDisplayImpl".formatted(Platform.isForge() ? "forge" : "fabric"))
// .getDeclaredMethod("registerPlatformSizeProvider")
// .invoke(null);
// } catch (IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) {
// throw new RuntimeException(e);
// }
// }
// /**
// * Registers a size provider for crafting recipes.
// * This is not reloadable, please statically register your provider, and
// * do not repeatedly register it.
// *
// * @param sizeProvider the provider to register
// * @param <R> the recipe type
// */
// public static <R extends Recipe<?>> void registerSizeProvider(CraftingRecipeSizeProvider<R> sizeProvider) {
// SIZE_PROVIDER.add(0, sizeProvider);
// }
@Nullable
public static DefaultTesselatingDisplay<?> of(Recipe<?> recipe) {
if (recipe instanceof TesselatingShapelessRecipe) {
return new DefaultTesselatingShapelessDisplay((TesselatingShapelessRecipe) recipe);
} else if (recipe instanceof ShapedTesselatingRecipe) {
return new DefaultTesselatingShapedDisplay((ShapedTesselatingRecipe) recipe);
} /*else if (!recipe.isSpecial()) {
NonNullList<Ingredient> ingredients = recipe.getIngredients();
for (CraftingRecipeSizeProvider<?> pair : SIZE_PROVIDER) {
CraftingRecipeSizeProvider.Size size = ((CraftingRecipeSizeProvider<Recipe<?>>) pair).getSize(recipe);
if (size != null) {
return new DefaultCustomShapedDisplay(recipe, EntryIngredients.ofIngredients(recipe.getIngredients()),
Collections.singletonList(EntryIngredients.of(recipe.getResultItem(BasicDisplay.registryAccess()))),
size.getWidth(), size.getHeight());
}
}
return new DefaultCustomDisplay(recipe, EntryIngredients.ofIngredients(recipe.getIngredients()),
Collections.singletonList(EntryIngredients.of(recipe.getResultItem(BasicDisplay.registryAccess()))));
}*/
return null;
}
@Override
public CategoryIdentifier<?> getCategoryIdentifier() {
return BuiltinPlugin.CRAFTING;
}
public Optional<C> getOptionalRecipe() {
return recipe;
}
@Override
public Optional<ResourceLocation> getDisplayLocation() {
return getOptionalRecipe().map(Recipe::getId);
}
public <T extends AbstractContainerMenu> List<List<ItemStack>> getOrganisedInputEntries(SimpleGridMenuInfo<T, DefaultCraftingDisplay<?>> menuInfo, T container) {
return CollectionUtils.map(getOrganisedInputEntries(menuInfo.getCraftingWidth(container), menuInfo.getCraftingHeight(container)), ingredient ->
CollectionUtils.<EntryStack<?>, ItemStack>filterAndMap(ingredient, stack -> stack.getType() == VanillaEntryTypes.ITEM,
EntryStack::castValue));
}
public <T extends AbstractContainerMenu> List<EntryIngredient> getOrganisedInputEntries(int menuWidth, int menuHeight) {
List<EntryIngredient> list = new ArrayList<>(menuWidth * menuHeight);
for (int i = 0; i < menuWidth * menuHeight; i++) {
list.add(EntryIngredient.empty());
}
for (int i = 0; i < getInputEntries().size(); i++) {
list.set(getSlotWithSize(this, i, menuWidth), getInputEntries().get(i));
}
return list;
}
public boolean isShapeless() {
return false;
}
public static int getSlotWithSize(DefaultTesselatingDisplay<?> display, int index, int craftingGridWidth) {
return getSlotWithSize(display.getInputWidth(craftingGridWidth, 3), index, craftingGridWidth);
}
public static int getSlotWithSize(int recipeWidth, int index, int craftingGridWidth) {
int x = index % recipeWidth;
int y = (index - x) / recipeWidth;
return craftingGridWidth * y + x;
}
// public static BasicDisplay.Serializer<DefaultTesselatingDisplay<?>> serializer() {
// return BasicDisplay.Serializer.<DefaultTesselatingDisplay<?>>of((input, output, location, tag) -> {
// if (tag.contains("REIRecipeType")) {
// String type = tag.getString("REIRecipeType");
// return switch (type) {
// case "Shapeless" -> DefaultCustomShapelessDisplay.simple(input, output, location);
// case "Shaped" -> DefaultCustomShapedDisplay.simple(input, output, tag.getInt("RecipeWidth"), tag.getInt("RecipeHeight"), location);
// default -> throw new IllegalArgumentException("Unknown recipe type: " + type);
// };
// } else {
// return DefaultCustomDisplay.simple(input, output, location);
// }
// }, (display, tag) -> {
// tag.putString("REIRecipeType", display.isShapeless() ? "Shapeless" : "Shaped");
// if (!display.isShapeless()) {
// tag.putInt("RecipeWidth", display.getInputWidth(3, 3));
// tag.putInt("RecipeHeight", display.getInputHeight(3, 3));
// }
// });
// }
//
// @Override
public List<InputIngredient<EntryStack<?>>> getInputIngredients(MenuSerializationContext<?, ?, ?> context, MenuInfo<?, ?> info, boolean fill) {
int craftingWidth = 3, craftingHeight = 3;
if (info instanceof SimpleGridMenuInfo && fill) {
craftingWidth = ((SimpleGridMenuInfo<AbstractContainerMenu, ?>) info).getCraftingWidth(context.getMenu());
craftingHeight = ((SimpleGridMenuInfo<AbstractContainerMenu, ?>) info).getCraftingHeight(context.getMenu());
}
return getInputIngredients(craftingWidth, craftingHeight);
}
@Override
public List<InputIngredient<EntryStack<?>>> getInputIngredients(@Nullable AbstractContainerMenu menu, @Nullable Player player) {
return getInputIngredients(3, 3);
}
public List<InputIngredient<EntryStack<?>>> getInputIngredients(int craftingWidth, int craftingHeight) {
int inputWidth = getInputWidth(craftingWidth, craftingHeight);
int inputHeight = getInputHeight(craftingWidth, craftingHeight);
Map<IntIntPair, InputIngredient<EntryStack<?>>> grid = new HashMap<>();
List<EntryIngredient> inputEntries = getInputEntries();
for (int i = 0; i < inputEntries.size(); i++) {
EntryIngredient stacks = inputEntries.get(i);
if (stacks.isEmpty()) {
continue;
}
int index = getSlotWithSize(inputWidth, i, craftingWidth);
int x = i % inputWidth;
int y = i / inputWidth;
grid.put(new IntIntImmutablePair(x, y), InputIngredient.of(index, 3 * y + x, stacks));
}
List<InputIngredient<EntryStack<?>>> list = new ArrayList<>(craftingWidth * craftingHeight);
for (int i = 0, n = craftingWidth * craftingHeight; i < n; i++) {
list.add(InputIngredient.empty(i));
}
for (int x = 0; x < craftingWidth; x++) {
for (int y = 0; y < craftingHeight; y++) {
InputIngredient<EntryStack<?>> ingredient = grid.get(new IntIntImmutablePair(x, y));
if (ingredient != null) {
int index = craftingWidth * y + x;
list.set(index, ingredient);
}
}
}
return list;
}
public int getWeavingTime() {
return weavingTime;
}
}

View file

@ -0,0 +1,31 @@
package org.dimdev.dimdoors.compat.rei;
import me.shedaniel.rei.api.common.display.basic.BasicDisplay;
import me.shedaniel.rei.api.common.util.EntryIngredients;
import org.dimdev.dimdoors.recipe.ShapedTesselatingRecipe;
import java.util.Collections;
import java.util.Optional;
public class DefaultTesselatingShapedDisplay extends DefaultTesselatingDisplay<ShapedTesselatingRecipe> {
public DefaultTesselatingShapedDisplay(ShapedTesselatingRecipe recipe) {
super(
EntryIngredients.ofIngredients(recipe.getIngredients()),
Collections.singletonList(EntryIngredients.of(recipe.getResultItem(BasicDisplay.registryAccess()))),
Optional.of(recipe),
recipe.weavingTime()
);
}
@SuppressWarnings("OptionalGetWithoutIsPresent")
@Override
public int getWidth() {
return recipe.get().getWidth();
}
@SuppressWarnings("OptionalGetWithoutIsPresent")
@Override
public int getHeight() {
return recipe.get().getHeight();
}
}

View file

@ -0,0 +1,55 @@
package org.dimdev.dimdoors.compat.rei;
import me.shedaniel.rei.api.common.display.basic.BasicDisplay;
import me.shedaniel.rei.api.common.util.EntryIngredients;
import org.dimdev.dimdoors.recipe.TesselatingShapelessRecipe;
import java.util.Collections;
import java.util.Optional;
@SuppressWarnings("ALL")
public class DefaultTesselatingShapelessDisplay extends DefaultTesselatingDisplay<TesselatingShapelessRecipe> {
public DefaultTesselatingShapelessDisplay(TesselatingShapelessRecipe recipe) {
super(
EntryIngredients.ofIngredients(recipe.getIngredients()),
Collections.singletonList(EntryIngredients.of(recipe.getResultItem(BasicDisplay.registryAccess()))),
Optional.of(recipe),
recipe.weavingTime()
);
}
@Override
public int getWidth() {
return getInputEntries().size() > 4 ? 3 : 2;
}
@Override
public int getHeight() {
return getInputEntries().size() > 4 ? 3 : 2;
}
@Override
public int getInputWidth() {
return Math.min(getInputEntries().size(), 3);
}
@Override
public int getInputWidth(int craftingWidth, int craftingHeight) {
return craftingWidth * craftingHeight <= getInputEntries().size() ? craftingWidth : Math.min(getInputEntries().size(), 3);
}
@Override
public int getInputHeight() {
return (int) Math.ceil(getInputEntries().size() / (double) getInputWidth());
}
@Override
public int getInputHeight(int craftingWidth, int craftingHeight) {
return (int) Math.ceil(getInputEntries().size() / (double) getInputWidth(craftingWidth, craftingHeight));
}
@Override
public boolean isShapeless() {
return true;
}
}

View file

@ -0,0 +1,59 @@
package org.dimdev.dimdoors.compat.rei;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.plugins.REIClientPlugin;
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry;
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry;
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry;
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry;
import me.shedaniel.rei.api.client.registry.transfer.simple.SimpleTransferHandler;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.Display;
import me.shedaniel.rei.api.common.util.EntryStacks;
import net.minecraft.world.item.crafting.RecipeType;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.client.screen.TesselatingLoomScreen;
import org.dimdev.dimdoors.recipe.ModRecipeTypes;
import org.dimdev.dimdoors.recipe.ShapedTesselatingRecipe;
import org.dimdev.dimdoors.recipe.TesselatingRecipe;
import org.dimdev.dimdoors.screen.TessellatingContainer;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
public class TesselatingReiCompatClient implements REIClientPlugin {
public static final CategoryIdentifier<? extends DefaultTesselatingDisplay<?>> TESSELATING = CategoryIdentifier.of("dimdoors", "tesselating");
@Override
public void registerCategories(CategoryRegistry registry) {
registry.add(new DefaultTesselatingCategory(), new Consumer<CategoryRegistry.CategoryConfiguration<DefaultTesselatingDisplay<?>>>() {
@Override
public void accept(CategoryRegistry.CategoryConfiguration<DefaultTesselatingDisplay<?>> configuration) {
configuration.addWorkstations(EntryStacks.of(ModBlocks.TESSELATING_LOOM.get()));
}
});
}
@Override
public void registerDisplays(DisplayRegistry registry) {
registry.registerFiller(ShapedTesselatingRecipe.class, DefaultTesselatingDisplay::of);
}
@Override
public void registerScreens(ScreenRegistry registry) {
registry.registerContainerClickArea(new Rectangle(137, 29, 10, 13), TesselatingLoomScreen.class, TESSELATING);
}
@Override
public void registerTransferHandlers(TransferHandlerRegistry registry) {
registry.register(SimpleTransferHandler.create(TessellatingContainer.class, TESSELATING, new SimpleTransferHandler.IntRange(1, 10)));
}
@Override
public double getPriority() {
return -300;
}
}

View file

@ -1,20 +1,18 @@
package org.dimdev.dimdoors.recipe;
import dev.architectury.registry.registries.DeferredRegister;
import dev.architectury.registry.registries.Registrar;
import dev.architectury.registry.registries.RegistrarManager;
import dev.architectury.registry.registries.RegistrySupplier;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import org.dimdev.dimdoors.DimensionalDoors;
import java.util.function.Supplier;
public class ModRecipeSerializers {
public static DeferredRegister<RecipeSerializer<?>> RECIPE_SERIALIZERS = DeferredRegister.create(DimensionalDoors.MOD_ID, Registries.RECIPE_SERIALIZER);
public static RegistrySupplier<RecipeSerializer<TesselatingRecipe>> TESSELATING = register("tesselating", TesselatingRecipe.Serializer::new);
public static RegistrySupplier<RecipeSerializer<ShapedTesselatingRecipe>> SHAPED_TESSELATING = register("shaped_tesselating", ShapedTesselatingRecipe.Serializer::new);
public static RegistrySupplier<RecipeSerializer<TesselatingShapelessRecipe>> SHAPELESS_TESSELATING = register("shapeless_tesselating", TesselatingShapelessRecipe.Serializer::new);
public static void init() {
RECIPE_SERIALIZERS.register();

View file

@ -4,12 +4,14 @@ import dev.architectury.registry.registries.DeferredRegister;
import dev.architectury.registry.registries.RegistrySupplier;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.ShapedRecipe;
import net.minecraft.world.item.crafting.ShapelessRecipe;
import org.dimdev.dimdoors.DimensionalDoors;
public class ModRecipeTypes {
public static final DeferredRegister<RecipeType<?>> RECIPES_TYPES = DeferredRegister.create(DimensionalDoors.MOD_ID, Registries.RECIPE_TYPE);
public static RegistrySupplier<RecipeType<TesselatingRecipe>> TESSELATING = register("tesselating");
public static RegistrySupplier<RecipeType<ShapedTesselatingRecipe>> SHAPED_TESSELATING = register("shaped_tesselating");
public static RegistrySupplier<RecipeType<TesselatingShapelessRecipe>> SHAPELESS_TESSELATING = register("shapeless_tesselating");
private static <T extends TesselatingRecipe> RegistrySupplier<RecipeType<T>> register(String name) {
var id = DimensionalDoors.id(name);

View file

@ -0,0 +1,324 @@
package org.dimdev.dimdoors.recipe;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.*;
import net.minecraft.core.NonNullList;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.dimdev.dimdoors.block.entity.TesselatingLoomBlockEntity;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
public class ShapedTesselatingRecipe implements TesselatingRecipe {
private final int width;
final int height;
final NonNullList<Ingredient> recipeItems;
final ItemStack result;
private final ResourceLocation id;
final String group;
final boolean showNotification;
private final int weavingTime;
public ShapedTesselatingRecipe(ResourceLocation id, String group, int width, int height, NonNullList<Ingredient> recipeItems, ItemStack result, int weavingTime, boolean showNotification) {
this.id = id;
this.group = group;
this.width = width;
this.height = height;
this.recipeItems = recipeItems;
this.result = result;
this.weavingTime = weavingTime;
this.showNotification = showNotification;
}
public ShapedTesselatingRecipe(ResourceLocation id, String group, int width, int height, NonNullList<Ingredient> recipeItems, ItemStack result, int weavingTime) {
this(id, group, width, height, recipeItems, result, weavingTime, true);
}
@Override
public @NotNull ResourceLocation getId() {
return this.id;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return ModRecipeSerializers.SHAPED_TESSELATING.get();
}
@Override
public @NotNull String getGroup() {
return this.group;
}
@Override
public @NotNull RecipeType<?> getType() {
return ModRecipeTypes.SHAPED_TESSELATING.get();
}
@Override
public @NotNull ItemStack getResultItem(@NotNull RegistryAccess registryAccess) {
return this.result;
}
@Override
public @NotNull NonNullList<Ingredient> getIngredients() {
return this.recipeItems;
}
@Override
public boolean showNotification() {
return this.showNotification;
}
@Override
public boolean canCraftInDimensions(int width, int height) {
return width >= this.width && height >= this.height;
}
/**
* Used to check if a recipe matches current crafting inventory
*/
@Override
public boolean matches(TesselatingLoomBlockEntity inv, Level level) {
for (int i = 0; i <= 3 - this.width; ++i) {
for (int j = 0; j <= 3 - this.height; ++j) {
if (this.matches(inv, i, j, true)) {
return true;
}
if (!this.matches(inv, i, j, false)) continue;
return true;
}
}
return false;
}
/**
* Checks if the region of a crafting inventory is match for the recipe.
*/
private boolean matches(TesselatingLoomBlockEntity craftingInventory, int width, int height, boolean mirrored) {
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
int k = x - width;
int l = y - height;
Ingredient ingredient = Ingredient.EMPTY;
if (k >= 0 && l >= 0 && k < this.width && l < this.height) {
ingredient = mirrored ? this.recipeItems.get(this.width - k - 1 + l * this.width) : this.recipeItems.get(k + l * this.width);
}
if (ingredient.test(craftingInventory.getItem(x + y * 3 + 1))) continue;
return false;
}
}
return true;
}
public @NotNull NonNullList<ItemStack> getRemainingItems(TesselatingLoomBlockEntity container) {
NonNullList<ItemStack> nonNullList = NonNullList.withSize(container.getContainerSize(), ItemStack.EMPTY);
for (int i = 1; i < nonNullList.size(); ++i) {
Item item = container.getItem(i).getItem();
if (!item.hasCraftingRemainingItem()) continue;
nonNullList.set(i, new ItemStack(item.getCraftingRemainingItem()));
}
return nonNullList;
}
@Override
public @NotNull ItemStack assemble(@NotNull TesselatingLoomBlockEntity container, @NotNull RegistryAccess registryAccess) {
return this.getResultItem(registryAccess).copy();
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public static NonNullList<Ingredient> dissolvePattern(String[] pattern, Map<String, Ingredient> keys, int patternWidth, int patternHeight) {
NonNullList<Ingredient> nonNullList = NonNullList.withSize(patternWidth * patternHeight, Ingredient.EMPTY);
HashSet<String> set = Sets.newHashSet(keys.keySet());
set.remove(" ");
for (int i = 0; i < pattern.length; ++i) {
for (int j = 0; j < pattern[i].length(); ++j) {
String string = pattern[i].substring(j, j + 1);
Ingredient ingredient = keys.get(string);
if (ingredient == null) {
throw new JsonSyntaxException("Pattern references symbol '" + string + "' but it's not defined in the key");
}
set.remove(string);
nonNullList.set(j + patternWidth * i, ingredient);
}
}
if (!set.isEmpty()) {
throw new JsonSyntaxException("Key defines symbols that aren't used in pattern: " + set);
}
return nonNullList;
}
@VisibleForTesting
public static String[] shrink(String ... toShrink) {
int i = Integer.MAX_VALUE;
int j = 0;
int k = 0;
int l = 0;
for (int m = 0; m < toShrink.length; ++m) {
String string = toShrink[m];
i = Math.min(i, firstNonSpace(string));
int n = lastNonSpace(string);
j = Math.max(j, n);
if (n < 0) {
if (k == m) {
++k;
}
++l;
continue;
}
l = 0;
}
if (toShrink.length == l) {
return new String[0];
}
String[] strings = new String[toShrink.length - l - k];
for (int o = 0; o < strings.length; ++o) {
strings[o] = toShrink[o + k].substring(i, j + 1);
}
return strings;
}
@Override
public boolean isIncomplete() {
NonNullList<Ingredient> nonNullList = this.getIngredients();
return nonNullList.isEmpty() || nonNullList.stream().filter(ingredient -> !ingredient.isEmpty()).anyMatch(ingredient -> ingredient.getItems().length == 0);
}
private static int firstNonSpace(String entry) {
int i;
for (i = 0; i < entry.length() && entry.charAt(i) == ' '; ++i) {
}
return i;
}
private static int lastNonSpace(String entry) {
int i;
for (i = entry.length() - 1; i >= 0 && entry.charAt(i) == ' '; --i) {
}
return i;
}
public static String[] patternFromJson(JsonArray patternArray) {
String[] strings = new String[patternArray.size()];
if (strings.length > 3) {
throw new JsonSyntaxException("Invalid pattern: too many rows, 3 is maximum");
}
if (strings.length == 0) {
throw new JsonSyntaxException("Invalid pattern: empty pattern not allowed");
}
for (int i = 0; i < strings.length; ++i) {
String string = GsonHelper.convertToString(patternArray.get(i), "pattern[" + i + "]");
if (string.length() > 3) {
throw new JsonSyntaxException("Invalid pattern: too many columns, 3 is maximum");
}
if (i > 0 && strings[0].length() != string.length()) {
throw new JsonSyntaxException("Invalid pattern: each row must be the same width");
}
strings[i] = string;
}
return strings;
}
/**
* Returns a key json object as a Java HashMap.
*/
public static Map<String, Ingredient> keyFromJson(JsonObject keyEntry) {
HashMap<String, Ingredient> map = Maps.newHashMap();
for (Map.Entry<String, JsonElement> entry : keyEntry.entrySet()) {
if (entry.getKey().length() != 1) {
throw new JsonSyntaxException("Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only).");
}
if (" ".equals(entry.getKey())) {
throw new JsonSyntaxException("Invalid key entry: ' ' is a reserved symbol.");
}
map.put(entry.getKey(), Ingredient.fromJson(entry.getValue()));
}
map.put(" ", Ingredient.EMPTY);
return map;
}
public static ItemStack itemStackFromJson(JsonObject stackObject) {
Item item = itemFromJson(stackObject);
if (stackObject.has("data")) {
throw new JsonParseException("Disallowed data tag found");
}
int i = GsonHelper.getAsInt(stackObject, "count", 1);
if (i < 1) {
throw new JsonSyntaxException("Invalid output count: " + i);
}
return new ItemStack(item, i);
}
public static Item itemFromJson(JsonObject itemObject) {
String string = GsonHelper.getAsString(itemObject, "item");
Item item = BuiltInRegistries.ITEM.getOptional(new ResourceLocation(string)).orElseThrow(() -> new JsonSyntaxException("Unknown item '" + string + "'"));
if (item == Items.AIR) {
throw new JsonSyntaxException("Invalid item: " + string);
}
return item;
}
public int weavingTime() {
return weavingTime;
}
public static class Serializer implements RecipeSerializer<ShapedTesselatingRecipe> {
@Override
public @NotNull ShapedTesselatingRecipe fromJson(@NotNull ResourceLocation recipeId, @NotNull JsonObject json) {
String string = GsonHelper.getAsString(json, "group", "");
Map<String, Ingredient> map = keyFromJson(GsonHelper.getAsJsonObject(json, "key"));
String[] strings = shrink(patternFromJson(GsonHelper.getAsJsonArray(json, "pattern")));
int i = strings[0].length();
int j = strings.length;
NonNullList<Ingredient> nonNullList = dissolvePattern(strings, map, i, j);
ItemStack itemStack = itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
int weavingTime = GsonHelper.getAsInt(json, "weavingtime", 200);
boolean bl = GsonHelper.getAsBoolean(json, "show_notification", true);
return new ShapedTesselatingRecipe(recipeId, string, i, j, nonNullList, itemStack, weavingTime, bl);
}
@Override
public @NotNull ShapedTesselatingRecipe fromNetwork(@NotNull ResourceLocation recipeId, FriendlyByteBuf buffer) {
int i = buffer.readVarInt();
int j = buffer.readVarInt();
String string = buffer.readUtf();
NonNullList<Ingredient> nonNullList = NonNullList.withSize(i * j, Ingredient.EMPTY);
nonNullList.replaceAll(ignored -> Ingredient.fromNetwork(buffer));
ItemStack itemStack = buffer.readItem();
int weavingTime = buffer.readInt();
boolean bl = buffer.readBoolean();
return new ShapedTesselatingRecipe(recipeId, string, i, j, nonNullList, itemStack, weavingTime, bl);
}
@Override
public void toNetwork(FriendlyByteBuf buffer, ShapedTesselatingRecipe recipe) {
buffer.writeVarInt(recipe.width);
buffer.writeVarInt(recipe.height);
buffer.writeUtf(recipe.group);
recipe.recipeItems.forEach(ingredient -> ingredient.toNetwork(buffer));
buffer.writeItem(recipe.result);
buffer.writeInt(recipe.weavingTime);
buffer.writeBoolean(recipe.showNotification);
}
}
}

View file

@ -1,333 +1,12 @@
package org.dimdev.dimdoors.recipe;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.*;
import net.minecraft.core.NonNullList;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.Container;
import net.minecraft.world.inventory.CraftingContainer;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.Level;
import org.dimdev.dimdoors.block.entity.TesselatingLoomBlockEntity;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
public interface TesselatingRecipe extends Recipe<TesselatingLoomBlockEntity> {
public class TesselatingRecipe implements Recipe<Container> {
private final int width;
final int height;
final NonNullList<Ingredient> recipeItems;
final ItemStack result;
private final ResourceLocation id;
final String group;
final boolean showNotification;
private final float experience;
private final int weavingTime;
boolean matches(TesselatingLoomBlockEntity inv, Level level);
public TesselatingRecipe(ResourceLocation id, String group, int width, int height, NonNullList<Ingredient> recipeItems, ItemStack result, float experience, int weavingTime, boolean showNotification) {
this.id = id;
this.group = group;
this.width = width;
this.height = height;
this.recipeItems = recipeItems;
this.result = result;
this.experience = experience;
this.weavingTime = weavingTime;
this.showNotification = showNotification;
}
public TesselatingRecipe(ResourceLocation id, String group, int width, int height, NonNullList<Ingredient> recipeItems, ItemStack result, float experience, int weavingTime) {
this(id, group, width, height, recipeItems, result, experience, weavingTime, true);
}
@Override
public ResourceLocation getId() {
return this.id;
}
@Override
public RecipeSerializer<?> getSerializer() {
return ModRecipeSerializers.TESSELATING.get();
}
@Override
public String getGroup() {
return this.group;
}
@Override
public RecipeType<?> getType() {
return ModRecipeTypes.TESSELATING.get();
}
@Override
public ItemStack getResultItem(RegistryAccess registryAccess) {
return this.result;
}
@Override
public NonNullList<Ingredient> getIngredients() {
return this.recipeItems;
}
@Override
public boolean showNotification() {
return this.showNotification;
}
@Override
public boolean canCraftInDimensions(int width, int height) {
return width >= this.width && height >= this.height;
}
/**
* Used to check if a recipe matches current crafting inventory
*/
@Override
public boolean matches(Container inv, Level level) {
for (int i = 0; i <= 3 - this.width; ++i) {
for (int j = 0; j <= 3 - this.height; ++j) {
if (this.matches(inv, i, j, true)) {
return true;
}
if (!this.matches(inv, i, j, false)) continue;
return true;
}
}
return false;
}
/**
* Checks if the region of a crafting inventory is match for the recipe.
*/
private boolean matches(Container craftingInventory, int width, int height, boolean mirrored) {
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
int k = x - width;
int l = y - height;
Ingredient ingredient = Ingredient.EMPTY;
if (k >= 0 && l >= 0 && k < this.width && l < this.height) {
ingredient = mirrored ? this.recipeItems.get(this.width - k - 1 + l * this.width) : this.recipeItems.get(k + l * this.width);
}
if (ingredient.test(craftingInventory.getItem(x + y * 3 + 1))) continue;
return false;
}
}
return true;
}
public NonNullList<ItemStack> getRemainingItems(Container container) {
NonNullList<ItemStack> nonNullList = NonNullList.withSize(container.getContainerSize(), ItemStack.EMPTY);
for (int i = 1; i < nonNullList.size(); ++i) {
Item item = container.getItem(i).getItem();
if (!item.hasCraftingRemainingItem()) continue;
nonNullList.set(i, new ItemStack(item.getCraftingRemainingItem()));
}
return nonNullList;
}
@Override
public ItemStack assemble(Container container, RegistryAccess registryAccess) {
return this.getResultItem(registryAccess).copy();
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public static NonNullList<Ingredient> dissolvePattern(String[] pattern, Map<String, Ingredient> keys, int patternWidth, int patternHeight) {
NonNullList<Ingredient> nonNullList = NonNullList.withSize(patternWidth * patternHeight, Ingredient.EMPTY);
HashSet<String> set = Sets.newHashSet(keys.keySet());
set.remove(" ");
for (int i = 0; i < pattern.length; ++i) {
for (int j = 0; j < pattern[i].length(); ++j) {
String string = pattern[i].substring(j, j + 1);
Ingredient ingredient = keys.get(string);
if (ingredient == null) {
throw new JsonSyntaxException("Pattern references symbol '" + string + "' but it's not defined in the key");
}
set.remove(string);
nonNullList.set(j + patternWidth * i, ingredient);
}
}
if (!set.isEmpty()) {
throw new JsonSyntaxException("Key defines symbols that aren't used in pattern: " + set);
}
return nonNullList;
}
@VisibleForTesting
public static String[] shrink(String ... toShrink) {
int i = Integer.MAX_VALUE;
int j = 0;
int k = 0;
int l = 0;
for (int m = 0; m < toShrink.length; ++m) {
String string = toShrink[m];
i = Math.min(i, firstNonSpace(string));
int n = lastNonSpace(string);
j = Math.max(j, n);
if (n < 0) {
if (k == m) {
++k;
}
++l;
continue;
}
l = 0;
}
if (toShrink.length == l) {
return new String[0];
}
String[] strings = new String[toShrink.length - l - k];
for (int o = 0; o < strings.length; ++o) {
strings[o] = toShrink[o + k].substring(i, j + 1);
}
return strings;
}
@Override
public boolean isIncomplete() {
NonNullList<Ingredient> nonNullList = this.getIngredients();
return nonNullList.isEmpty() || nonNullList.stream().filter(ingredient -> !ingredient.isEmpty()).anyMatch(ingredient -> ingredient.getItems().length == 0);
}
private static int firstNonSpace(String entry) {
int i;
for (i = 0; i < entry.length() && entry.charAt(i) == ' '; ++i) {
}
return i;
}
private static int lastNonSpace(String entry) {
int i;
for (i = entry.length() - 1; i >= 0 && entry.charAt(i) == ' '; --i) {
}
return i;
}
public static String[] patternFromJson(JsonArray patternArray) {
String[] strings = new String[patternArray.size()];
if (strings.length > 3) {
throw new JsonSyntaxException("Invalid pattern: too many rows, 3 is maximum");
}
if (strings.length == 0) {
throw new JsonSyntaxException("Invalid pattern: empty pattern not allowed");
}
for (int i = 0; i < strings.length; ++i) {
String string = GsonHelper.convertToString(patternArray.get(i), "pattern[" + i + "]");
if (string.length() > 3) {
throw new JsonSyntaxException("Invalid pattern: too many columns, 3 is maximum");
}
if (i > 0 && strings[0].length() != string.length()) {
throw new JsonSyntaxException("Invalid pattern: each row must be the same width");
}
strings[i] = string;
}
return strings;
}
/**
* Returns a key json object as a Java HashMap.
*/
public static Map<String, Ingredient> keyFromJson(JsonObject keyEntry) {
HashMap<String, Ingredient> map = Maps.newHashMap();
for (Map.Entry<String, JsonElement> entry : keyEntry.entrySet()) {
if (entry.getKey().length() != 1) {
throw new JsonSyntaxException("Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only).");
}
if (" ".equals(entry.getKey())) {
throw new JsonSyntaxException("Invalid key entry: ' ' is a reserved symbol.");
}
map.put(entry.getKey(), Ingredient.fromJson(entry.getValue()));
}
map.put(" ", Ingredient.EMPTY);
return map;
}
public static ItemStack itemStackFromJson(JsonObject stackObject) {
Item item = itemFromJson(stackObject);
if (stackObject.has("data")) {
throw new JsonParseException("Disallowed data tag found");
}
int i = GsonHelper.getAsInt(stackObject, "count", 1);
if (i < 1) {
throw new JsonSyntaxException("Invalid output count: " + i);
}
return new ItemStack(item, i);
}
public static Item itemFromJson(JsonObject itemObject) {
String string = GsonHelper.getAsString(itemObject, "item");
Item item = BuiltInRegistries.ITEM.getOptional(new ResourceLocation(string)).orElseThrow(() -> new JsonSyntaxException("Unknown item '" + string + "'"));
if (item == Items.AIR) {
throw new JsonSyntaxException("Invalid item: " + string);
}
return item;
}
public int weavingTime() {
return weavingTime;
}
public float experience() {
return experience;
}
public static class Serializer implements RecipeSerializer<TesselatingRecipe> {
@Override
public TesselatingRecipe fromJson(ResourceLocation recipeId, JsonObject json) {
String string = GsonHelper.getAsString(json, "group", "");
Map<String, Ingredient> map = keyFromJson(GsonHelper.getAsJsonObject(json, "key"));
String[] strings = shrink(patternFromJson(GsonHelper.getAsJsonArray(json, "pattern")));
int i = strings[0].length();
int j = strings.length;
NonNullList<Ingredient> nonNullList = dissolvePattern(strings, map, i, j);
ItemStack itemStack = itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
float experience = GsonHelper.getAsFloat(json, "experience", 0.0F);
int weavingTime = GsonHelper.getAsInt(json, "weavingtime", 200);
boolean bl = GsonHelper.getAsBoolean(json, "show_notification", true);
return new TesselatingRecipe(recipeId, string, i, j, nonNullList, itemStack, experience, weavingTime, bl);
}
@Override
public TesselatingRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) {
int i = buffer.readVarInt();
int j = buffer.readVarInt();
String string = buffer.readUtf();
NonNullList<Ingredient> nonNullList = NonNullList.withSize(i * j, Ingredient.EMPTY);
nonNullList.replaceAll(ignored -> Ingredient.fromNetwork(buffer));
ItemStack itemStack = buffer.readItem();
float experience = buffer.readFloat();
int weavingTime = buffer.readInt();
boolean bl = buffer.readBoolean();
return new TesselatingRecipe(recipeId, string, i, j, nonNullList, itemStack, experience, weavingTime, bl);
}
@Override
public void toNetwork(FriendlyByteBuf buffer, TesselatingRecipe recipe) {
buffer.writeVarInt(recipe.width);
buffer.writeVarInt(recipe.height);
buffer.writeUtf(recipe.group);
recipe.recipeItems.forEach(ingredient -> ingredient.toNetwork(buffer));
buffer.writeItem(recipe.result);
buffer.writeFloat(recipe.experience);
buffer.writeInt(recipe.weavingTime);
buffer.writeBoolean(recipe.showNotification);
}
}
int weavingTime();
}

View file

@ -0,0 +1,162 @@
package org.dimdev.dimdoors.recipe;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.core.NonNullList;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.player.StackedContents;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CraftingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import org.dimdev.dimdoors.block.entity.TesselatingLoomBlockEntity;
import static org.dimdev.dimdoors.recipe.ShapedTesselatingRecipe.itemStackFromJson;
public class TesselatingShapelessRecipe implements TesselatingRecipe {
final NonNullList<Ingredient> ingredients;
private final ResourceLocation id;
final ItemStack result;
final String group;
final boolean showNotification;
private final float experience;
private final int weavingTime;
public TesselatingShapelessRecipe(ResourceLocation id, String group, ItemStack result, NonNullList<Ingredient> ingredients, float experience, int weavingTime, boolean showNotification) {
this.id = id;
this.group = group;
this.result = result;
this.ingredients = ingredients;
this.experience = experience;
this.weavingTime = weavingTime;
this.showNotification = showNotification;
}
@Override
public ResourceLocation getId() {
return this.id;
}
@Override
public RecipeSerializer<?> getSerializer() {
return ModRecipeSerializers.SHAPELESS_TESSELATING.get();
}
@Override
public RecipeType<?> getType() {
return ModRecipeTypes.SHAPELESS_TESSELATING.get();
}
@Override
public String getGroup() {
return this.group;
}
@Override
public ItemStack getResultItem(RegistryAccess registryAccess) {
return this.result;
}
@Override
public NonNullList<Ingredient> getIngredients() {
return this.ingredients;
}
/**
* Used to check if a recipe matches current crafting inventory
*/
@Override
public boolean matches(TesselatingLoomBlockEntity inv, Level level) {
StackedContents stackedContents = new StackedContents();
int i = 0;
for (int j = 0; j < inv.getContainerSize(); ++j) {
ItemStack itemStack = inv.getItem(j);
if (itemStack.isEmpty()) continue;
++i;
stackedContents.accountStack(itemStack, 1);
}
return i == this.ingredients.size() && stackedContents.canCraft(this, null);
}
@Override
public int weavingTime() {
return weavingTime;
}
@Override
public ItemStack assemble(TesselatingLoomBlockEntity container, RegistryAccess registryAccess) {
return this.result.copy();
}
@Override
public boolean canCraftInDimensions(int width, int height) {
return width * height >= this.ingredients.size();
}
public static class Serializer
implements RecipeSerializer<TesselatingShapelessRecipe> {
@Override
public TesselatingShapelessRecipe fromJson(ResourceLocation recipeId, JsonObject json) {
String string = GsonHelper.getAsString(json, "group", "");
NonNullList<Ingredient> nonNullList = itemsFromJson(GsonHelper.getAsJsonArray(json, "ingredients"));
if (nonNullList.isEmpty()) {
throw new JsonParseException("No ingredients for shapeless recipe");
}
if (nonNullList.size() > 9) {
throw new JsonParseException("Too many ingredients for shapeless recipe");
}
ItemStack itemStack = itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
float experience = GsonHelper.getAsFloat(json, "experience", 0.0F);
int weavingTime = GsonHelper.getAsInt(json, "weavingtime", 200);
boolean bl = GsonHelper.getAsBoolean(json, "show_notification", true);
return new TesselatingShapelessRecipe(recipeId, string, itemStack, nonNullList, experience, weavingTime, bl);
}
private static NonNullList<Ingredient> itemsFromJson(JsonArray ingredientArray) {
NonNullList<Ingredient> nonNullList = NonNullList.create();
for (int i = 0; i < ingredientArray.size(); ++i) {
Ingredient ingredient = Ingredient.fromJson(ingredientArray.get(i), false);
if (ingredient.isEmpty()) continue;
nonNullList.add(ingredient);
}
return nonNullList;
}
@Override
public TesselatingShapelessRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) {
String string = buffer.readUtf();
int i = buffer.readVarInt();
NonNullList<Ingredient> nonNullList = NonNullList.withSize(i, Ingredient.EMPTY);
for (int j = 0; j < nonNullList.size(); ++j) {
nonNullList.set(j, Ingredient.fromNetwork(buffer));
}
ItemStack itemStack = buffer.readItem();
float experience = buffer.readFloat();
int weavingTime = buffer.readInt();
boolean bl = buffer.readBoolean();
return new TesselatingShapelessRecipe(recipeId, string, itemStack, nonNullList, experience, weavingTime, bl);
}
@Override
public void toNetwork(FriendlyByteBuf buffer, TesselatingShapelessRecipe recipe) {
buffer.writeUtf(recipe.group);
buffer.writeVarInt(recipe.ingredients.size());
for (Ingredient ingredient : recipe.ingredients) {
ingredient.toNetwork(buffer);
}
buffer.writeItem(recipe.result);
}
}
}

View file

@ -10,9 +10,9 @@ import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;
import org.dimdev.dimdoors.block.entity.TesselatingLoomBlockEntity;
import org.dimdev.dimdoors.client.ModRecipeBookTypes;
//import org.dimdev.dimdoors.client.ModRecipeBookTypes;
public class TessellatingContainer extends RecipeBookMenu<Container> {
public class TessellatingContainer extends AbstractContainerMenu /*RecipeBookMenu<Container>*/ {
public static final int INPUT1_SLOT = 0;
public static final int INPUT2_SLOT = 1;
public static final int INPUT3_SLOT = 2;
@ -56,60 +56,60 @@ public class TessellatingContainer extends RecipeBookMenu<Container> {
this.addDataSlots(data);
}
@Override
public void fillCraftSlotsStackedContents(StackedContents stackedContents) {
if(this.recipeInv instanceof StackedContentsCompatible provider) {
provider.fillStackedContents(stackedContents);
}
}
// @Override
// public void fillCraftSlotsStackedContents(StackedContents stackedContents) {
// if(this.recipeInv instanceof StackedContentsCompatible provider) {
// provider.fillStackedContents(stackedContents);
// }
// }
@Override
public void clearCraftingContent() {
this.getSlot(1).set(ItemStack.EMPTY);
this.getSlot(2).set(ItemStack.EMPTY);
this.getSlot(3).set(ItemStack.EMPTY);
this.getSlot(4).set(ItemStack.EMPTY);
this.getSlot(5).set(ItemStack.EMPTY);
this.getSlot(6).set(ItemStack.EMPTY);
this.getSlot(7).set(ItemStack.EMPTY);
this.getSlot(8).set(ItemStack.EMPTY);
this.getSlot(9).set(ItemStack.EMPTY);
}
// @Override
// public void clearCraftingContent() {
// this.getSlot(1).set(ItemStack.EMPTY);
// this.getSlot(2).set(ItemStack.EMPTY);
// this.getSlot(3).set(ItemStack.EMPTY);
// this.getSlot(4).set(ItemStack.EMPTY);
// this.getSlot(5).set(ItemStack.EMPTY);
// this.getSlot(6).set(ItemStack.EMPTY);
// this.getSlot(7).set(ItemStack.EMPTY);
// this.getSlot(8).set(ItemStack.EMPTY);
// this.getSlot(9).set(ItemStack.EMPTY);
// }
@Override
public boolean recipeMatches(Recipe<? super Container> recipe) {
return recipe.matches(recipeInv, playerInventory.player.level());
}
// @Override
// public boolean recipeMatches(Recipe<? super Container> recipe) {
// return recipe.matches(recipeInv, playerInventory.player.level());
// }
//
// @Override
// public int getResultSlotIndex() {
// return 0;
// }
@Override
public int getResultSlotIndex() {
return 0;
}
// @Override
// public int getGridWidth() {
// return 3;
// }
//
// @Override
// public int getGridHeight() {
// return 3;
// }
@Override
public int getGridWidth() {
return 3;
}
@Override
public int getGridHeight() {
return 3;
}
@Override
public int getSize() {
return 10;
}
@Override
public RecipeBookType getRecipeBookType() {
return ModRecipeBookTypes.TESSELLATING;
}
@Override
public boolean shouldMoveToInventory(int index) {
return index != 0;
}
// @Override
// public int getSize() {
// return 10;
// }
//
// @Override
// public RecipeBookType getRecipeBookType() {
// return ModRecipeBookTypes.TESSELLATING;
// }
//
// @Override
// public boolean shouldMoveToInventory(int index) {
// return index != 0;
// }
@Override
public ItemStack quickMoveStack(Player player, int index) {

View file

@ -71,7 +71,7 @@ dependencies {
modApi "mcp.mobius.waila:wthit:fabric-${wthitVersion}"
modApi "com.terraformersmc:modmenu:7.2.2"
// modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:$rei_version"
modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:$rei_version"
// modCompileOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:$rei_version"
// modCompileOnly "me.shedaniel:RoughlyEnoughItems-default-plugin-fabric:$rei_version"
}

View file

@ -30,7 +30,7 @@ public class DimdoorsRecipeProvider extends RecipeProvider {
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.STONE_DOOR.get()).pattern("XX").pattern("XX").pattern("XX").define('X', Blocks.STONE).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(Blocks.STONE)).save(exporter, DimensionalDoors.id("stone_door"));
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.GOLD_DOOR.get(), 3).pattern("XX").pattern("XX").pattern("XX").define('X', GOLD_INGOTS).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(Items.GOLD_INGOT)).save(exporter, DimensionalDoors.id("gold_door"));
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.QUARTZ_DOOR.get()).pattern("XX").pattern("XX").pattern("XX").define('X', Items.QUARTZ).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(Items.QUARTZ)).save(exporter, DimensionalDoors.id("quartz_door"));
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.RIFT_BLADE.get()).requires(Items.IRON_SWORD).requires(Items.ENDER_PEARL, 2).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(Items.IRON_SWORD)).save(exporter, DimensionalDoors.id("rift_blade"));
TesselatingShapelessRecipeBuilder.shapeless(ModItems.RIFT_BLADE.get()).requires(Items.IRON_SWORD).requires(Items.ENDER_PEARL, 2).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(Items.IRON_SWORD)).save(exporter, DimensionalDoors.id("rift_blade"));
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModItems.RIFT_REMOVER.get()).pattern(" # ").pattern("#X#").pattern(" # ").define('#', GOLD_INGOTS).define('X', Items.ENDER_PEARL).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(ModItems.RIFT_BLADE.get())).save(exporter, DimensionalDoors.id("rift_remover"));
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModItems.RIFT_REMOVER.get()).pattern("###").pattern("#X#").pattern("###").define('#', GOLD_INGOTS).define('X', ModItems.STABLE_FABRIC.get()).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(ModItems.STABLE_FABRIC.get())).save(exporter, DimensionalDoors.id("rift_remover_stable_fabric"));
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModItems.RIFT_SIGNATURE.get()).pattern(" # ").pattern("#X#").pattern(" # ").define('#', IRON_INGOTS).define('X', Items.ENDER_PEARL).unlockedBy("inventory_changed", InventoryChangeTrigger.TriggerInstance.hasItems(ModItems.RIFT_BLADE.get())).save(exporter, DimensionalDoors.id("rift_signature"));

View file

@ -14,7 +14,6 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.data.recipes.CraftingRecipeBuilder;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.data.recipes.RecipeBuilder;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
@ -30,7 +29,6 @@ import java.util.Set;
import java.util.function.Consumer;
public class TesselatingRecipeJsonBuilder extends CraftingRecipeBuilder {
private final RecipeCategory category;
private final Item output;
private final int outputCount;
private final List<String> pattern = Lists.newArrayList();
@ -40,11 +38,9 @@ public class TesselatingRecipeJsonBuilder extends CraftingRecipeBuilder {
@Nullable
private String group;
private float experience = 1.0f;
private int weavingTime = 200;
public TesselatingRecipeJsonBuilder(ItemLike output, int outputCount) {
this.category = RecipeCategory.MISC; //TODO: FIND out if need to be different
this.output = output.asItem();
this.outputCount = outputCount;
}
@ -95,11 +91,6 @@ public class TesselatingRecipeJsonBuilder extends CraftingRecipeBuilder {
return this;
}
public TesselatingRecipeJsonBuilder experience(float experience) {
this.experience = experience;
return this;
}
public TesselatingRecipeJsonBuilder weavingTime(int weavingTime) {
this.weavingTime = weavingTime;
return this;
@ -114,7 +105,7 @@ public class TesselatingRecipeJsonBuilder extends CraftingRecipeBuilder {
this.validate(recipeId);
this.advancementBuilder.parent(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT).addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(recipeId)).rewards(AdvancementRewards.Builder.recipe(recipeId)).requirements(RequirementsStrategy.OR);
exporter.accept(new TesselatingRecipeJsonProvider(recipeId, this.output, this.outputCount, this.group == null ? "" : this.group, this.pattern, this.inputs, this.advancementBuilder, recipeId.withPrefix("recipes/tesselating/"), experience, weavingTime));
exporter.accept(new TesselatingRecipeJsonProvider(recipeId, this.output, this.outputCount, this.group == null ? "" : this.group, this.pattern, this.inputs, this.advancementBuilder, recipeId.withPrefix("recipes/tesselating/"), weavingTime));
}
private void validate(ResourceLocation recipeId) {
@ -154,10 +145,9 @@ public class TesselatingRecipeJsonBuilder extends CraftingRecipeBuilder {
private final Map<Character, Ingredient> inputs;
private final Advancement.Builder advancementBuilder;
private final ResourceLocation advancementId;
private final float experience;
private final int weavingTime;
public TesselatingRecipeJsonProvider(ResourceLocation recipeId, Item output, int resultCount, String group, List<String> pattern, Map<Character, Ingredient> inputs, Advancement.Builder advancementBuilder, ResourceLocation advancementId, float experience, int weavingTime) {
public TesselatingRecipeJsonProvider(ResourceLocation recipeId, Item output, int resultCount, String group, List<String> pattern, Map<Character, Ingredient> inputs, Advancement.Builder advancementBuilder, ResourceLocation advancementId, int weavingTime) {
this.recipeId = recipeId;
this.output = output;
this.resultCount = resultCount;
@ -166,7 +156,6 @@ public class TesselatingRecipeJsonBuilder extends CraftingRecipeBuilder {
this.inputs = inputs;
this.advancementBuilder = advancementBuilder;
this.advancementId = advancementId;
this.experience = experience;
this.weavingTime = weavingTime;
}
@ -197,13 +186,12 @@ public class TesselatingRecipeJsonBuilder extends CraftingRecipeBuilder {
}
json.add("result", jsonObject2);
json.addProperty("experience", experience);
json.addProperty("weavingtime", weavingTime);
}
@Override
public RecipeSerializer<?> getType() {
return ModRecipeSerializers.TESSELATING.get();
return ModRecipeSerializers.SHAPED_TESSELATING.get();
}
public ResourceLocation getId() {

View file

@ -0,0 +1,204 @@
package org.dimdev.dimdoors.datagen;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementRewards;
import net.minecraft.advancements.CriterionTriggerInstance;
import net.minecraft.advancements.RequirementsStrategy;
import net.minecraft.advancements.critereon.RecipeUnlockedTrigger;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.data.recipes.CraftingRecipeBuilder;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.data.recipes.RecipeBuilder;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.CraftingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.ItemLike;
import org.dimdev.dimdoors.recipe.ModRecipeSerializers;
import org.dimdev.dimdoors.recipe.TesselatingShapelessRecipe;
public class TesselatingShapelessRecipeBuilder extends CraftingRecipeBuilder implements RecipeBuilder {
private final Item result;
private final int count;
private final List<Ingredient> ingredients = Lists.newArrayList();
private final Advancement.Builder advancement = Advancement.Builder.recipeAdvancement();
@Nullable
private String group;
private int weavingTime = 200;
public TesselatingShapelessRecipeBuilder(ItemLike result, int count) {
this.result = result.asItem();
this.count = count;
}
/**
* Creates a new builder for a shapeless recipe.
*/
public static TesselatingShapelessRecipeBuilder shapeless(ItemLike result) {
return new TesselatingShapelessRecipeBuilder(result, 1);
}
/**
* Creates a new builder for a shapeless recipe.
*/
public static TesselatingShapelessRecipeBuilder shapeless(ItemLike result, int count) {
return new TesselatingShapelessRecipeBuilder(result, count);
}
/**
* Adds an ingredient that can be any item in the given tag.
*/
public TesselatingShapelessRecipeBuilder requires(TagKey<Item> tag) {
return this.requires(Ingredient.of(tag));
}
public TesselatingShapelessRecipeBuilder weavingTime(int weavingTime) {
this.weavingTime = weavingTime;
return this;
}
/**
* Adds an ingredient of the given item.
*/
public TesselatingShapelessRecipeBuilder requires(ItemLike item) {
return this.requires(item, 1);
}
/**
* Adds the given ingredient multiple times.
*/
public TesselatingShapelessRecipeBuilder requires(ItemLike item, int quantity) {
for (int i = 0; i < quantity; ++i) {
this.requires(Ingredient.of(item));
}
return this;
}
/**
* Adds an ingredient.
*/
public TesselatingShapelessRecipeBuilder requires(Ingredient ingredient) {
return this.requires(ingredient, 1);
}
/**
* Adds an ingredient multiple times.
*/
public TesselatingShapelessRecipeBuilder requires(Ingredient ingredient, int quantity) {
for (int i = 0; i < quantity; ++i) {
this.ingredients.add(ingredient);
}
return this;
}
@Override
public TesselatingShapelessRecipeBuilder unlockedBy(String criterionName, CriterionTriggerInstance criterionTrigger) {
this.advancement.addCriterion(criterionName, criterionTrigger);
return this;
}
@Override
public TesselatingShapelessRecipeBuilder group(@Nullable String groupName) {
this.group = groupName;
return this;
}
@Override
public Item getResult() {
return this.result;
}
@Override
public void save(Consumer<FinishedRecipe> finishedRecipeConsumer, ResourceLocation recipeId) {
recipeId = recipeId.withPrefix("tesselating/");
this.ensureValid(recipeId);
this.advancement.parent(ROOT_RECIPE_ADVANCEMENT).addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(recipeId)).rewards(AdvancementRewards.Builder.recipe(recipeId)).requirements(RequirementsStrategy.OR);
finishedRecipeConsumer.accept(new TesselatingShapelessRecipeBuilder.Result(recipeId, this.result, this.count, this.group == null ? "" : this.group, this.ingredients, this.advancement, recipeId.withPrefix("recipes/tesselating/"), weavingTime));
}
/**
* Makes sure that this recipe is valid and obtainable.
*/
private void ensureValid(ResourceLocation id) {
if (this.advancement.getCriteria().isEmpty()) {
throw new IllegalStateException("No way of obtaining recipe " + id);
}
}
public static class Result implements FinishedRecipe {
private final ResourceLocation id;
private final Item result;
private final int count;
private final String group;
private final List<Ingredient> ingredients;
private final Advancement.Builder advancement;
private final ResourceLocation advancementId;
private final int weavingTime;
public Result(ResourceLocation id, Item result, int count, String group, List<Ingredient> ingredients, Advancement.Builder advancement, ResourceLocation advancementId, int weavingTime) {
this.id = id;
this.result = result;
this.count = count;
this.group = group;
this.ingredients = ingredients;
this.advancement = advancement;
this.advancementId = advancementId;
this.weavingTime = weavingTime;
}
@Override
public void serializeRecipeData(JsonObject json) {
if (!this.group.isEmpty()) {
json.addProperty("group", this.group);
}
JsonArray jsonArray = new JsonArray();
for (Ingredient ingredient : this.ingredients) {
jsonArray.add(ingredient.toJson());
}
json.add("ingredients", jsonArray);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("item", BuiltInRegistries.ITEM.getKey(this.result).toString());
if (this.count > 1) {
jsonObject.addProperty("count", this.count);
}
json.add("result", jsonObject);
json.addProperty("weavingtime", weavingTime);
}
@Override
public RecipeSerializer<?> getType() {
return ModRecipeSerializers.SHAPELESS_TESSELATING.get();
}
@Override
public ResourceLocation getId() {
return this.id;
}
@Override
@Nullable
public JsonObject serializeAdvancement() {
return this.advancement.serializeToJson();
}
@Override
@Nullable
public ResourceLocation getAdvancementId() {
return this.advancementId;
}
}
}

View file

@ -1,35 +1,12 @@
package org.dimdev.dimdoors;
import dev.architectury.event.EventResult;
import dev.architectury.event.events.common.BlockEvent;
import dev.architectury.utils.value.IntValue;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.fabricmc.fabric.api.tag.convention.v1.ConventionalBiomeTags;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
import net.minecraft.world.level.levelgen.GenerationStep;
import org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.DetachedRiftBlockEntity;
import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity;
import org.dimdev.dimdoors.client.ModRecipeBookGroups;
import org.dimdev.dimdoors.client.ModRecipeBookTypes;
import org.dimdev.dimdoors.recipe.ModRecipeTypes;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static org.dimdev.dimdoors.block.door.WaterLoggableDoorBlock.WATERLOGGED;
import static org.dimdev.dimdoors.world.feature.ModFeatures.Placed.*;
public class DimensionalDoorsFabric implements ModInitializer {

View file

@ -11,16 +11,16 @@ import org.dimdev.dimdoors.item.ModItems;
public class EarlyRiser implements Runnable {
@Override
public void run() {
String recipeBookType = FabricLoader.getInstance().getMappingResolver().mapClassName("intermediary", "net.minecraft.class_5421");
ClassTinkerers.enumBuilder(recipeBookType).addEnum("TESSELLATING").build();
if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
MappingResolver remapper = FabricLoader.getInstance().getMappingResolver();
String recipeBookGroup = remapper.mapClassName("intermediary", "net.minecraft.class_314");
String itemStack1 = "[L" + remapper.mapClassName("intermediary", "net.minecraft.class_1799") + ";";
ClassTinkerers.enumBuilder(recipeBookGroup, itemStack1)
.addEnum("TESSELATING_GENERAL", () -> new Object[] {new ItemStack[]{ModItems.WORLD_THREAD.get().getDefaultInstance()}})
.addEnum("TESSELATING_SEARCH", () -> new Object[] {new ItemStack[]{Items.COMPASS.getDefaultInstance()}}).build();
}
// String recipeBookType = FabricLoader.getInstance().getMappingResolver().mapClassName("intermediary", "net.minecraft.class_5421");
// ClassTinkerers.enumBuilder(recipeBookType).addEnum("TESSELLATING").build();
//
// if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
// MappingResolver remapper = FabricLoader.getInstance().getMappingResolver();
// String recipeBookGroup = remapper.mapClassName("intermediary", "net.minecraft.class_314");
// String itemStack1 = "[L" + remapper.mapClassName("intermediary", "net.minecraft.class_1799") + ";";
// ClassTinkerers.enumBuilder(recipeBookGroup, itemStack1)
// .addEnum("TESSELATING_GENERAL", () -> new Object[] {new ItemStack[]{ModItems.WORLD_THREAD.get().getDefaultInstance()}})
// .addEnum("TESSELATING_SEARCH", () -> new Object[] {new ItemStack[]{Items.COMPASS.getDefaultInstance()}}).build();
// }
}
}

View file

@ -29,6 +29,6 @@ public class DimensionalDoorsClientFabric implements ClientModInitializer {
(particleType, spriteSetFunction) -> ParticleFactoryRegistry.getInstance().register(particleType, (ParticleFactoryRegistry.PendingParticleFactory) spriteSetFunction::apply));
DimensionalDoorsClient.initEntitiesClient(EntityRendererRegistry::register);
ModEntityModelLayers.initClient((modelLayerLocation, layerDefinitionSupplier) -> EntityModelLayerRegistry.registerModelLayer(modelLayerLocation, layerDefinitionSupplier::get));
RecipeBookManager.init();
// RecipeBookManager.init();
}
}

View file

@ -1,67 +1,49 @@
package org.dimdev.dimdoors.client;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import net.fabricmc.fabric.impl.content.registry.util.ImmutableCollectionUtils;
import net.fabricmc.fabric.mixin.content.registry.AxeItemAccessor;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.world.inventory.RecipeBookType;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.Block;
import org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent;
import org.dimdev.dimdoors.fabric.mixin.client.RecipeBookCategoriesAccessor;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import static net.minecraft.client.RecipeBookCategories.*;
/**
* Manager for {@link RecipeBookType recipe book types} and {@link RecipeBookCategories categories}.
* <p>
* Provides a recipe category lookup.
*/
public final class RecipeBookManager
{
// Not using ConcurrentHashMap here because it's slower for lookups, so we only use it during init
private static final Map<RecipeBookCategories, List<RecipeBookCategories>> AGGREGATE_CATEGORIES = new HashMap<>();
private static final Map<RecipeBookType, List<RecipeBookCategories>> TYPE_CATEGORIES = new HashMap<>();
private static final Map<RecipeType<?>, Function<Recipe<?>, RecipeBookCategories>> RECIPE_CATEGORY_LOOKUPS = new HashMap<>();
/**
* Finds the category the specified recipe should display in, or null if none.
*/
@Nullable
public static RecipeBookCategories findCategories(RecipeType<?> type, Recipe<?> recipe)
{
var lookup = RECIPE_CATEGORY_LOOKUPS.get(type);
return lookup != null ? lookup.apply(recipe) : null;
}
@ApiStatus.Internal
public static List<RecipeBookCategories> getCustomCategoriesOrEmpty(RecipeBookType recipeBookType)
{
return TYPE_CATEGORIES.getOrDefault(recipeBookType, List.of());
}
@ApiStatus.Internal
public static void init()
{
// The ImmutableMap is the patched out value of AGGREGATE_CATEGORIES
var typeCategories = new HashMap<RecipeBookType, List<RecipeBookCategories>>();
var recipeCategoryLookups = new HashMap<RecipeType<?>, Function<Recipe<?>, RecipeBookCategories>>();
var event = new RegisterRecipeBookCategoriesEvent(getRegistry()::put, typeCategories::put, recipeCategoryLookups::put);
RegisterRecipeBookCategoriesEvent.EVENT.invoker().accept(event);
TYPE_CATEGORIES.putAll(typeCategories);
RECIPE_CATEGORY_LOOKUPS.putAll(recipeCategoryLookups);
}
private static Map<RecipeBookCategories, List<RecipeBookCategories>> getRegistry() {
return ImmutableCollectionUtils.getAsMutableMap(RecipeBookCategoriesAccessor::aggregateCategories, RecipeBookCategoriesAccessor::setAggregateCategories);
}
}
//public final class RecipeBookManager
//{
// // Not using ConcurrentHashMap here because it's slower for lookups, so we only use it during init
// private static final Map<RecipeBookCategories, List<RecipeBookCategories>> AGGREGATE_CATEGORIES = new HashMap<>();
// private static final Map<RecipeBookType, List<RecipeBookCategories>> TYPE_CATEGORIES = new HashMap<>();
// private static final Map<RecipeType<?>, Function<Recipe<?>, RecipeBookCategories>> RECIPE_CATEGORY_LOOKUPS = new HashMap<>();
//
// /**
// * Finds the category the specified recipe should display in, or null if none.
// */
// @Nullable
// public static RecipeBookCategories findCategories(RecipeType<?> type, Recipe<?> recipe)
// {
// var lookup = RECIPE_CATEGORY_LOOKUPS.get(type);
// return lookup != null ? lookup.apply(recipe) : null;
// }
//
// @ApiStatus.Internal
// public static List<RecipeBookCategories> getCustomCategoriesOrEmpty(RecipeBookType recipeBookType)
// {
// return TYPE_CATEGORIES.getOrDefault(recipeBookType, List.of());
// }
//
// @ApiStatus.Internal
// public static void init()
// {
// // The ImmutableMap is the patched out value of AGGREGATE_CATEGORIES
// var typeCategories = new HashMap<RecipeBookType, List<RecipeBookCategories>>();
// var recipeCategoryLookups = new HashMap<RecipeType<?>, Function<Recipe<?>, RecipeBookCategories>>();
// var event = new RegisterRecipeBookCategoriesEvent(getRegistry()::put, typeCategories::put, recipeCategoryLookups::put);
// RegisterRecipeBookCategoriesEvent.EVENT.invoker().accept(event);
// TYPE_CATEGORIES.putAll(typeCategories);
// RECIPE_CATEGORY_LOOKUPS.putAll(recipeCategoryLookups);
// }
//
// private static Map<RecipeBookCategories, List<RecipeBookCategories>> getRegistry() {
// return ImmutableCollectionUtils.getAsMutableMap(RecipeBookCategoriesAccessor::aggregateCategories, RecipeBookCategoriesAccessor::setAggregateCategories);
// }
//}

View file

@ -10,9 +10,8 @@ import net.minecraft.world.item.Items;
import java.util.function.Supplier;
public class ModRecipeBookGroupsImpl {
public static Supplier<RecipeBookCategories> getRecipBookCategories(String name, Supplier<ItemStack> itemStack) {
// ClassTinkerers.enumBuilder(name)
return () -> ClassTinkerers.getEnum(RecipeBookCategories.class, name);
}
// public static Supplier<RecipeBookCategories> getRecipBookCategories(String name, Supplier<ItemStack> itemStack) {
//
// return () -> ClassTinkerers.getEnum(RecipeBookCategories.class, name);
// }
}

View file

@ -4,65 +4,65 @@ import net.minecraft.recipebook.PlaceRecipe;
import net.minecraft.util.Mth;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.ShapedRecipe;
import org.dimdev.dimdoors.recipe.TesselatingRecipe;
import org.dimdev.dimdoors.recipe.ShapedTesselatingRecipe;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Iterator;
@Mixin(PlaceRecipe.class)
public interface PlaceRecipeMixin {
@Shadow void addItemToSlot(Iterator var1, int var2, int var3, int var4, int var5);
/**
* @author
* @reason
*/
@Overwrite
default public void placeRecipe(int width, int height, int outputSlot, Recipe<?> recipe, Iterator ingredients, int maxAmount) {
int i = width;
int j = height;
if (recipe instanceof ShapedRecipe shapedRecipe) {
i = shapedRecipe.getWidth();
j = shapedRecipe.getHeight();
} else if (recipe instanceof TesselatingRecipe shapedRecipe) {
i = shapedRecipe.getWidth();
j = shapedRecipe.getHeight();
}
int k = 0;
block0: for (int l = 0; l < height; ++l) {
if (k == outputSlot) {
++k;
}
boolean bl = (float)j < (float)height / 2.0f;
int m = Mth.floor((float)height / 2.0f - (float)j / 2.0f);
if (bl && m > l) {
k += width;
++l;
}
for (int n = 0; n < width; ++n) {
boolean bl2;
if (!ingredients.hasNext()) {
return;
}
bl = (float)i < (float)width / 2.0f;
m = Mth.floor((float)width / 2.0f - (float)i / 2.0f);
int o = i;
boolean bl3 = bl2 = n < i;
if (bl) {
o = m + i;
boolean bl4 = bl2 = m <= n && n < m + i;
}
if (bl2) {
addItemToSlot(ingredients, k, maxAmount, l, n);
} else if (o == n) {
k += width - n;
continue block0;
}
++k;
}
}
}
}
//@Mixin(PlaceRecipe.class)
//public interface PlaceRecipeMixin {
// @Shadow void addItemToSlot(Iterator var1, int var2, int var3, int var4, int var5);
//
// /**
// * @author
// * @reason
// */
// @Overwrite
// default public void placeRecipe(int width, int height, int outputSlot, Recipe<?> recipe, Iterator ingredients, int maxAmount) {
// int i = width;
// int j = height;
// if (recipe instanceof ShapedRecipe shapedRecipe) {
// i = shapedRecipe.getWidth();
// j = shapedRecipe.getHeight();
// } else if (recipe instanceof ShapedTesselatingRecipe shapedRecipe) {
// i = shapedRecipe.getWidth();
// j = shapedRecipe.getHeight();
// }
// int k = 0;
// block0: for (int l = 0; l < height; ++l) {
// if (k == outputSlot) {
// ++k;
// }
// boolean bl = (float)j < (float)height / 2.0f;
// int m = Mth.floor((float)height / 2.0f - (float)j / 2.0f);
// if (bl && m > l) {
// k += width;
// ++l;
// }
// for (int n = 0; n < width; ++n) {
// boolean bl2;
// if (!ingredients.hasNext()) {
// return;
// }
// bl = (float)i < (float)width / 2.0f;
// m = Mth.floor((float)width / 2.0f - (float)i / 2.0f);
// int o = i;
// boolean bl3 = bl2 = n < i;
// if (bl) {
// o = m + i;
// boolean bl4 = bl2 = m <= n && n < m + i;
// }
// if (bl2) {
// addItemToSlot(ingredients, k, maxAmount, l, n);
// } else if (o == n) {
// k += width - n;
// continue block0;
// }
// ++k;
// }
// }
// }
//
//}

View file

@ -1,24 +1,15 @@
package org.dimdev.dimdoors.fabric.mixin.client;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.world.inventory.RecipeBookType;
import org.dimdev.dimdoors.client.ModRecipeBookGroups;
import org.dimdev.dimdoors.client.ModRecipeBookTypes;
import org.dimdev.dimdoors.client.RecipeBookManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(RecipeBookCategories.class)
public class RecipeBookCategoriesMixin {
@Inject(method = "getCategories(Lnet/minecraft/world/inventory/RecipeBookType;)Ljava/util/List;", at = @At("HEAD"), cancellable = true)
private static void getCategories(RecipeBookType recipeBookType, CallbackInfoReturnable<List<RecipeBookCategories>> cir) {
var categories = RecipeBookManager.getCustomCategoriesOrEmpty(recipeBookType);
if(!categories.isEmpty()) cir.setReturnValue(categories);
}
// @Inject(method = "getCategories(Lnet/minecraft/world/inventory/RecipeBookType;)Ljava/util/List;", at = @At("HEAD"), cancellable = true)
// private static void getCategories(RecipeBookType recipeBookType, CallbackInfoReturnable<List<RecipeBookCategories>> cir) {
// var categories = RecipeBookManager.getCustomCategoriesOrEmpty(recipeBookType);
//
// if(!categories.isEmpty()) cir.setReturnValue(categories);
// }
}

View file

@ -1,20 +1,14 @@
package org.dimdev.dimdoors.fabric.mixin.client;
import net.minecraft.client.ClientRecipeBook;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.world.item.crafting.Recipe;
import org.dimdev.dimdoors.client.RecipeBookManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientRecipeBook.class)
public class RecipeBookManagerMixin {
@Inject(method = "getCategory(Lnet/minecraft/world/item/crafting/Recipe;)Lnet/minecraft/client/RecipeBookCategories;", at = @At("HEAD"), cancellable = true)
private static void getCategory(Recipe<?> recipe, CallbackInfoReturnable<RecipeBookCategories> cir) {
var category = RecipeBookManager.findCategories(recipe.getType(), recipe);
if(category != null) cir.setReturnValue(category);
}
// @Inject(method = "getCategory(Lnet/minecraft/world/item/crafting/Recipe;)Lnet/minecraft/client/RecipeBookCategories;", at = @At("HEAD"), cancellable = true)
// private static void getCategory(Recipe<?> recipe, CallbackInfoReturnable<RecipeBookCategories> cir) {
// var category = RecipeBookManager.findCategories(recipe.getType(), recipe);
//
// if(category != null) cir.setReturnValue(category);
// }
}

View file

@ -4,13 +4,8 @@
"compatibilityLevel": "JAVA_17",
"minVersion": "0.8",
"client": [
"client.RecipeBookCategoriesAccessor",
"client.RecipeBookCategoriesMixin",
"client.RecipeBookManagerMixin",
"client.PlaceRecipeMixin"
],
"mixins": [
"RecipeBookSettingsAccessor",
],
"injectors": {
"defaultRequire": 1

View file

@ -37,6 +37,9 @@
"modmenu": [ "org.dimdev.dimdoors.compat.ModMenuCompat" ],
"mm:early_risers": [
"org.dimdev.dimdoors.EarlyRiser"
],
"rei_client": [
"org.dimdev.dimdoors.compat.rei.TesselatingReiCompatClient"
]
},
"mixins": [

View file

@ -44,7 +44,7 @@ dependencies {
// modApi "lol.bai:badpackets:forge-0.4.2"
modApi "com.sk89q.worldedit:worldedit-forge-mc${rootProject.world_edit_minecraft_version}:${rootProject.worldedit}"
// modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-forge:$rei_version"
modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-forge:$rei_version"
// modCompileOnly "me.shedaniel:RoughlyEnoughItems-api-forge:$rei_version"
// modCompileOnly "me.shedaniel:RoughlyEnoughItems-default-plugin-forge:$rei_version"
}

View file

@ -1,33 +1,14 @@
package org.dimdev.dimdoors;
import dev.architectury.platform.forge.EventBuses;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.ConfigScreenHandler;
import net.minecraftforge.client.event.RegisterParticleProvidersEvent;
import net.minecraftforge.client.event.RegisterRecipeBookCategoriesEvent;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import org.dimdev.dimdoors.api.util.WeightedList;
import org.dimdev.dimdoors.client.DimensionalDoorsClient;
import org.dimdev.dimdoors.client.ModRecipeBookGroups;
import org.dimdev.dimdoors.client.ModRecipeBookTypes;
import org.dimdev.dimdoors.client.config.ModMenu;
import org.dimdev.dimdoors.item.component.forge.CounterComponentImpl;
import org.dimdev.dimdoors.recipe.ModRecipeTypes;
import org.dimdev.dimdoors.world.ModBiomeModifiers;
import org.dimdev.dimdoors.world.level.component.ChunkLazilyGeneratedComponent;
import org.dimdev.dimdoors.world.level.component.forge.ChunkLazilyGeneratedComponentImpl;
import org.dimdev.dimdoors.world.level.registry.DimensionalRegistry;
import org.dimdev.dimdoors.world.level.registry.forge.DimensionalRegistryImpl;
import java.util.List;
import java.util.function.Consumer;
@Mod(DimensionalDoors.MOD_ID)
@ -39,8 +20,6 @@ public class DimensionalDoorsForge {
ModBiomeModifiers.init();
FMLJavaModLoadingContext.get().getModEventBus().addListener((Consumer<RegisterRecipeBookCategoriesEvent>) event -> org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent.EVENT.invoker().accept(new org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent(event::registerAggregateCategory, event::registerBookCategories, event::registerRecipeCategoryFinder)));
FMLJavaModLoadingContext.get().getModEventBus().addListener((Consumer<RegisterCapabilitiesEvent>) registerCapabilitiesEvent -> {
registerCapabilitiesEvent.register(CounterComponentImpl.class);
registerCapabilitiesEvent.register(ChunkLazilyGeneratedComponent.class);

View file

@ -8,23 +8,15 @@ import net.minecraftforge.client.ConfigScreenHandler;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.RegisterDimensionSpecialEffectsEvent;
import net.minecraftforge.client.event.RegisterParticleProvidersEvent;
import net.minecraftforge.client.event.RegisterRecipeBookCategoriesEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.dimdev.dimdoors.DimensionalDoors;
import org.dimdev.dimdoors.client.DimensionalDoorsClient;
import org.dimdev.dimdoors.client.ModEntityModelLayers;
import org.dimdev.dimdoors.client.ModRecipeBookGroups;
import org.dimdev.dimdoors.client.ModRecipeBookTypes;
import org.dimdev.dimdoors.client.config.ModMenu;
import org.dimdev.dimdoors.client.effect.LimboDimensionEffect;
import org.dimdev.dimdoors.recipe.ModRecipeTypes;
import java.util.List;
import java.util.function.Consumer;
@Mod.EventBusSubscriber(modid = DimensionalDoors.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public class DimensionalDoorsForgeClient {
@ -32,6 +24,7 @@ public class DimensionalDoorsForgeClient {
@SubscribeEvent
public static void setupClient(FMLClientSetupEvent event) {
ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory((minecraft, screen) -> ModMenu.getConfigScreen(screen)));
// FMLJavaModLoadingContext.get().getModEventBus().addListener((Consumer<RegisterRecipeBookCategoriesEvent>) event1 -> org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent.EVENT.invoker().accept(new org.dimdev.dimdoors.api.util.RegisterRecipeBookCategoriesEvent(event1::registerAggregateCategory, event1::registerBookCategories, event1::registerRecipeCategoryFinder)));
DimensionalDoorsClient.init();
}

View file

@ -2,26 +2,24 @@ package org.dimdev.dimdoors.mixin.forge;
import net.minecraft.world.Container;
import net.minecraftforge.common.crafting.IShapedRecipe;
import org.dimdev.dimdoors.recipe.TesselatingRecipe;
import org.spongepowered.asm.mixin.Final;
import org.dimdev.dimdoors.recipe.ShapedTesselatingRecipe;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@Mixin(TesselatingRecipe.class)
public abstract class TessellatingRecipeMixin implements IShapedRecipe<Container> {
@Unique
private TesselatingRecipe self() {
return (TesselatingRecipe) (Object) this;
}
@Override
public int getRecipeWidth() {
return self().getWidth();
}
@Override
public int getRecipeHeight() {
return self().getHeight();
}
}
//@Mixin(ShapedTesselatingRecipe.class)
//public abstract class TessellatingRecipeMixin implements IShapedRecipe<Container> {
// @Unique
// private ShapedTesselatingRecipe self() {
// return (ShapedTesselatingRecipe) (Object) this;
// }
//
// @Override
// public int getRecipeWidth() {
// return self().getWidth();
// }
//
// @Override
// public int getRecipeHeight() {
// return self().getHeight();
// }
//}

View file

@ -28,6 +28,6 @@ wthitVersion=8.4.0
world_edit_minecraft_version=1.20
worldedit=7.3.0-SNAPSHOT
rei_version=12.0.665
rei_version=12.0.674
cloth_config=11.1.106