*WIP*: Merge commit 'ce4cb8974f
' into 1.18
This commit is contained in:
commit
c6a7a1d4f7
76 changed files with 2754 additions and 738 deletions
11
bclib.gradle
11
bclib.gradle
|
@ -167,3 +167,14 @@ publishing {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
dev {
|
||||
canBeResolved = false
|
||||
canBeConsumed = true
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
dev jar
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ loom_version=0.10-SNAPSHOT
|
|||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/versions.html
|
||||
minecraft_version= 21w40a
|
||||
loader_version= 0.12.1
|
||||
fabric_version = 0.40.8+1.18
|
||||
minecraft_version= 1.18-pre1
|
||||
loader_version= 0.12.5
|
||||
fabric_version = 0.42.2+1.18
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 0.4.1
|
||||
mod_version = 0.5.1
|
||||
maven_group = ru.bclib
|
||||
archives_base_name = bclib
|
||||
|
||||
|
|
11
src/main/java/org/anti_ad/mc/ipn/api/IPNIgnore.java
Normal file
11
src/main/java/org/anti_ad/mc/ipn/api/IPNIgnore.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package org.anti_ad.mc.ipn.api;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
// Included from "Inventory Profiles Next" (https://github.com/blackd/Inventory-Profiles)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface IPNIgnore {}
|
|
@ -13,7 +13,6 @@ import ru.bclib.api.dataexchange.handler.autosync.HelloClient;
|
|||
import ru.bclib.api.dataexchange.handler.autosync.HelloServer;
|
||||
import ru.bclib.api.dataexchange.handler.autosync.RequestFiles;
|
||||
import ru.bclib.api.dataexchange.handler.autosync.SendFiles;
|
||||
import ru.bclib.api.datafixer.DataFixerAPI;
|
||||
import ru.bclib.config.Configs;
|
||||
import ru.bclib.recipes.CraftingRecipes;
|
||||
import ru.bclib.registry.BaseBlockEntities;
|
||||
|
@ -53,8 +52,7 @@ public class BCLib implements ModInitializer {
|
|||
Chunker.DESCRIPTOR
|
||||
));
|
||||
|
||||
DataFixerAPI.registerPatch(() -> new BCLibPatch());
|
||||
|
||||
BCLibPatch.register();
|
||||
Configs.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
package ru.bclib;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import ru.bclib.api.datafixer.DataFixerAPI;
|
||||
import ru.bclib.api.datafixer.Patch;
|
||||
import ru.bclib.api.datafixer.PatchFunction;
|
||||
|
||||
public final class BCLibPatch extends Patch {
|
||||
|
||||
|
||||
public final class BCLibPatch {
|
||||
public static void register(){
|
||||
DataFixerAPI.registerPatch(BiomeSourcePatch::new);
|
||||
}
|
||||
}
|
||||
|
||||
final class BiomeSourcePatch extends Patch {
|
||||
private static final String NETHER_BIOME_SOURCE = "bclib:nether_biome_source";
|
||||
private static final String END_BIOME_SOURCE = "bclib:end_biome_source";
|
||||
|
||||
protected BCLibPatch() {
|
||||
protected BiomeSourcePatch() {
|
||||
super(BCLib.MOD_ID, "0.4.0");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,42 @@
|
|||
package ru.bclib.api;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.biome.v1.NetherBiomes;
|
||||
import net.fabricmc.fabric.impl.biome.NetherBiomeData;
|
||||
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
|
||||
import net.fabricmc.fabric.impl.biome.InternalBiomeData;
|
||||
import net.fabricmc.fabric.mixin.biome.modification.GenerationSettingsAccessor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.Biome.ClimateParameters;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.biome.Climate;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import ru.bclib.util.MHelper;
|
||||
import ru.bclib.world.biomes.BCLBiome;
|
||||
import ru.bclib.world.biomes.FabricBiomesData;
|
||||
import ru.bclib.world.features.BCLFeature;
|
||||
import ru.bclib.world.generator.BiomePicker;
|
||||
import ru.bclib.world.structures.BCLStructureFeature;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BiomeAPI {
|
||||
/**
|
||||
|
@ -39,6 +53,9 @@ public class BiomeAPI {
|
|||
private static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap();
|
||||
private static Registry<Biome> biomeRegistry;
|
||||
|
||||
private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Biome>>> MODIFICATIONS = Maps.newHashMap();
|
||||
private static final Set<ResourceLocation> MODIFIED_BIOMES = Sets.newHashSet();
|
||||
|
||||
public static final BCLBiome NETHER_WASTES_BIOME = registerNetherBiome(getFromRegistry(Biomes.NETHER_WASTES));
|
||||
public static final BCLBiome CRIMSON_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.CRIMSON_FOREST));
|
||||
public static final BCLBiome WARPED_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.WARPED_FOREST));
|
||||
|
@ -325,4 +342,143 @@ public class BiomeAPI {
|
|||
private static boolean pickerHasBiome(BiomePicker picker, ResourceLocation key) {
|
||||
return picker.getBiomes().stream().filter(biome -> biome.getID().equals(key)).findFirst().isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new biome modification for specified dimension. Will work both for mod and datapack biomes.
|
||||
* @param dimensionID {@link ResourceLocation} dimension ID, example: Level.OVERWORLD or "minecraft:overworld".
|
||||
* @param modification {@link BiConsumer} with {@link ResourceKey} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
public static void registerBiomeModification(ResourceKey dimensionID, BiConsumer<ResourceLocation, Biome> modification) {
|
||||
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.get(dimensionID);
|
||||
if (modifications == null) {
|
||||
modifications = Lists.newArrayList();
|
||||
MODIFICATIONS.put(dimensionID, modifications);
|
||||
}
|
||||
modifications.add(modification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new biome modification for the Overworld. Will work both for mod and datapack biomes.
|
||||
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
public static void registerOverworldBiomeModification(BiConsumer<ResourceLocation, Biome> modification) {
|
||||
registerBiomeModification(Level.OVERWORLD, modification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new biome modification for the Nether. Will work both for mod and datapack biomes.
|
||||
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
public static void registerNetherBiomeModification(BiConsumer<ResourceLocation, Biome> modification) {
|
||||
registerBiomeModification(Level.NETHER, modification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new biome modification for the End. Will work both for mod and datapack biomes.
|
||||
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
public static void registerEndBiomeModification(BiConsumer<ResourceLocation, Biome> modification) {
|
||||
registerBiomeModification(Level.END, modification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will apply biome modifications to world, internal usage only.
|
||||
* @param level
|
||||
*/
|
||||
public static void applyModifications(ServerLevel level) {
|
||||
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.get(level.dimension());
|
||||
if (modifications == null) {
|
||||
return;
|
||||
}
|
||||
BiomeSource source = level.getChunkSource().getGenerator().getBiomeSource();
|
||||
List<Biome> biomes = source.possibleBiomes();
|
||||
|
||||
biomes.forEach(biome -> {
|
||||
ResourceLocation biomeID = getBiomeID(biome);
|
||||
boolean modify = isDatapackBiome(biomeID);
|
||||
if (!modify && !MODIFIED_BIOMES.contains(biomeID)) {
|
||||
MODIFIED_BIOMES.add(biomeID);
|
||||
modify = true;
|
||||
}
|
||||
if (modify) {
|
||||
modifications.forEach(consumer -> {
|
||||
consumer.accept(biomeID, biome);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new features to existing biome.
|
||||
* @param biome {@link Biome} to add features in.
|
||||
* @param feature {@link ConfiguredFeature} to add.
|
||||
* @param step a {@link Decoration} step for the feature.
|
||||
*/
|
||||
public static void addBiomeFeature(Biome biome, ConfiguredFeature feature, Decoration step) {
|
||||
GenerationSettingsAccessor accessor = (GenerationSettingsAccessor) biome.getGenerationSettings();
|
||||
List<List<Supplier<ConfiguredFeature<?, ?>>>> biomeFeatures = getMutableList(accessor.fabric_getFeatures());
|
||||
int index = step.ordinal();
|
||||
if (biomeFeatures.size() < index) {
|
||||
for (int i = biomeFeatures.size(); i <= index; i++) {
|
||||
biomeFeatures.add(Lists.newArrayList());
|
||||
}
|
||||
}
|
||||
List<Supplier<ConfiguredFeature<?, ?>>> list = getMutableList(biomeFeatures.get(index));
|
||||
list.add(() -> feature);
|
||||
accessor.fabric_setFeatures(biomeFeatures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new features to existing biome.
|
||||
* @param biome {@link Biome} to add features in.
|
||||
* @param features array of {@link BCLFeature} to add.
|
||||
*/
|
||||
public static void addBiomeFeatures(Biome biome, BCLFeature... features) {
|
||||
GenerationSettingsAccessor accessor = (GenerationSettingsAccessor) biome.getGenerationSettings();
|
||||
List<List<Supplier<ConfiguredFeature<?, ?>>>> biomeFeatures = getMutableList(accessor.fabric_getFeatures());
|
||||
for (BCLFeature feature: features) {
|
||||
int index = feature.getFeatureStep().ordinal();
|
||||
if (biomeFeatures.size() < index) {
|
||||
for (int i = biomeFeatures.size(); i <= index; i++) {
|
||||
biomeFeatures.add(Lists.newArrayList());
|
||||
}
|
||||
}
|
||||
List<Supplier<ConfiguredFeature<?, ?>>> list = getMutableList(biomeFeatures.get(index));
|
||||
list.add(feature::getFeatureConfigured);
|
||||
}
|
||||
accessor.fabric_setFeatures(biomeFeatures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new structure feature to existing biome.
|
||||
* @param biome {@link Biome} to add structure feature in.
|
||||
* @param structure {@link ConfiguredStructureFeature} to add.
|
||||
*/
|
||||
public static void addBiomeStructure(Biome biome, ConfiguredStructureFeature structure) {
|
||||
GenerationSettingsAccessor accessor = (GenerationSettingsAccessor) biome.getGenerationSettings();
|
||||
List<Supplier<ConfiguredStructureFeature<?, ?>>> biomeStructures = getMutableList(accessor.fabric_getStructureFeatures());
|
||||
biomeStructures.add(() -> structure);
|
||||
accessor.fabric_setStructureFeatures(biomeStructures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new structure features to existing biome.
|
||||
* @param biome {@link Biome} to add structure features in.
|
||||
* @param structures array of {@link BCLStructureFeature} to add.
|
||||
*/
|
||||
public static void addBiomeStructures(Biome biome, BCLStructureFeature... structures) {
|
||||
GenerationSettingsAccessor accessor = (GenerationSettingsAccessor) biome.getGenerationSettings();
|
||||
List<Supplier<ConfiguredStructureFeature<?, ?>>> biomeStructures = getMutableList(accessor.fabric_getStructureFeatures());
|
||||
for (BCLStructureFeature structure: structures) {
|
||||
biomeStructures.add(structure::getFeatureConfigured);
|
||||
}
|
||||
accessor.fabric_setStructureFeatures(biomeStructures);
|
||||
}
|
||||
|
||||
private static <T extends Object> List<T> getMutableList(List<T> input) {
|
||||
if (input instanceof ImmutableList) {
|
||||
return Lists.newArrayList(input);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,16 @@ public class TagAPI {
|
|||
public static final Tag.Named<Block> BLOCK_END_GROUND = makeBlockTag(BCLib.MOD_ID, "end_ground");
|
||||
|
||||
public static final Tag.Named<Block> BLOCK_CHEST = makeCommonBlockTag("chest");
|
||||
public static final Tag.Named<Block> BLOCK_WOODEN_CHEST = makeCommonBlockTag("wooden_chests");
|
||||
public static final Tag.Named<Block> BLOCK_BARREL = makeCommonBlockTag("barrel");
|
||||
public static final Tag.Named<Block> BLOCK_WOODEN_BARREL = makeCommonBlockTag("wooden_barrels");
|
||||
public static final Tag.Named<Block> BLOCK_END_STONES = makeCommonBlockTag("end_stones");
|
||||
public static final Tag.Named<Block> BLOCK_NETHER_STONES = makeCommonBlockTag("nether_stones");
|
||||
public static final Tag.Named<Block> BLOCK_WORKBENCHES = makeCommonBlockTag("workbenches");
|
||||
public static final Tag.Named<Block> BLOCK_NETHER_PORTAL_FRAME = makeCommonBlockTag("nether_pframe");
|
||||
public static final Tag.Named<Block> BLOCK_WORKBENCHES = makeCommonBlockTag("workbench");
|
||||
public static final Tag.Named<Block> BLOCK_SAPLINGS = makeCommonBlockTag("saplings");
|
||||
public static final Tag.Named<Block> BLOCK_LEAVES = makeCommonBlockTag("leaves");
|
||||
public static final Tag.Named<Block> BLOCK_IMMOBILE = makeCommonBlockTag("immobile");
|
||||
|
||||
public static final Tag.Named<Block> BLOCK_DRAGON_IMMUNE = getMCBlockTag("dragon_immune");
|
||||
|
||||
|
@ -47,11 +54,19 @@ public class TagAPI {
|
|||
|
||||
// Item Tags
|
||||
public static final Tag.Named<Item> ITEM_CHEST = makeCommonItemTag("chest");
|
||||
public static final Tag.Named<Item> ITEM_WOODEN_CHEST = makeCommonItemTag("wooden_chests");
|
||||
public static final Tag.Named<Item> ITEM_BARREL = makeCommonItemTag("barrel");
|
||||
public static final Tag.Named<Item> ITEM_WOODEN_BARREL = makeCommonItemTag("wooden_barrels");
|
||||
public static final Tag.Named<Item> ITEM_IRON_INGOTS = makeCommonItemTag("iron_ingots");
|
||||
public static final Tag.Named<Item> ITEM_FURNACES = makeCommonItemTag("furnaces");
|
||||
public static final Tag.Named<Item> ITEM_WORKBENCHES = makeCommonItemTag("workbenches");
|
||||
public static final Tag.Named<Item> ITEM_WORKBENCHES = makeCommonItemTag("workbench");
|
||||
public final static Tag.Named<Item> ITEM_HAMMERS = makeCommonItemTag("hammers");
|
||||
|
||||
public static final Tag.Named<Item> ITEM_SAPLINGS = makeCommonItemTag("saplings");
|
||||
public static final Tag.Named<Item> ITEM_LEAVES = makeCommonItemTag("leaves");
|
||||
public static final Tag.Named<Item> ITEM_SHEARS = getMCItemTag("shears");
|
||||
public static final Tag.Named<Item> ITEM_COMMON_SHEARS = makeCommonItemTag("shears");
|
||||
|
||||
|
||||
/**
|
||||
* Get or create {@link Tag.Named}.
|
||||
*
|
||||
|
@ -122,6 +137,18 @@ public class TagAPI {
|
|||
return tag == null ? (Named<Block>) TagFactory.BLOCK.create(id): (Named<Block>) tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create Minecraft {@link Item} {@link Tag.Named}.
|
||||
*
|
||||
* @param name - {@link String} tag name.
|
||||
* @return {@link Item} {@link Tag.Named}.
|
||||
*/
|
||||
public static Tag.Named<Item> getMCItemTag(String name) {
|
||||
ResourceLocation id = new ResourceLocation(name);
|
||||
Tag<Item> tag = ItemTags.getAllTags().getTag(id);
|
||||
return tag == null ? (Named<Item>) TagRegistry.item(id) : (Named<Item>) tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link Block} to NETHER_GROUND and GEN_TERRAIN tags to process it properly in terrain generators and block logic.
|
||||
*
|
||||
|
|
|
@ -135,7 +135,7 @@ public class AutoSync {
|
|||
}
|
||||
|
||||
private static boolean didRegisterAdditionalMods = false;
|
||||
//we call this from HelloClient on the Srérver to prepare transfer
|
||||
//we call this from HelloClient on the Server to prepare transfer
|
||||
protected static void loadSyncFolder() {
|
||||
if (Configs.SERVER_CONFIG.isOfferingFiles()) {
|
||||
syncFolderDescriptions.forEach(desc -> desc.loadCache());
|
||||
|
|
|
@ -4,10 +4,10 @@ import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
|||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.ProgressListener;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.ProgressListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import ru.bclib.BCLib;
|
||||
|
|
|
@ -16,6 +16,7 @@ import ru.bclib.api.dataexchange.DataHandlerDescriptor;
|
|||
import ru.bclib.api.dataexchange.handler.autosync.AutoSyncID.WithContentOverride;
|
||||
import ru.bclib.api.dataexchange.handler.autosync.SyncFolderDescriptor.SubFile;
|
||||
import ru.bclib.config.Configs;
|
||||
import ru.bclib.config.ServerConfig;
|
||||
import ru.bclib.gui.screens.ModListScreen;
|
||||
import ru.bclib.gui.screens.ProgressScreen;
|
||||
import ru.bclib.gui.screens.SyncFilesScreen;
|
||||
|
@ -91,6 +92,11 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
mods = mods
|
||||
.stream()
|
||||
.filter(entry -> !Configs.SERVER_CONFIG.get(ServerConfig.EXCLUDED_MODS).contains(entry))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//write Plugin Versions
|
||||
buf.writeInt(mods.size());
|
||||
|
@ -394,6 +400,9 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
requestBCLibDownload();
|
||||
|
||||
this.onCloseSyncFilesScreen();
|
||||
} else {
|
||||
Minecraft.getInstance()
|
||||
.setScreen(null);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import ru.bclib.api.WorldDataAPI;
|
|||
import ru.bclib.config.Configs;
|
||||
import ru.bclib.gui.screens.AtomicProgressListener;
|
||||
import ru.bclib.gui.screens.ConfirmFixScreen;
|
||||
import ru.bclib.gui.screens.LevelFixErrorScreen;
|
||||
import ru.bclib.gui.screens.LevelFixErrorScreen.Listener;
|
||||
import ru.bclib.gui.screens.ProgressScreen;
|
||||
import ru.bclib.util.Logger;
|
||||
|
||||
|
@ -39,6 +41,7 @@ import java.util.function.BiConsumer;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
/**
|
||||
* API to manage Patches that need to get applied to a world
|
||||
|
@ -47,6 +50,24 @@ public class DataFixerAPI {
|
|||
static final Logger LOGGER = new Logger("DataFixerAPI");
|
||||
static class State {
|
||||
public boolean didFail = false;
|
||||
protected ArrayList<String> errors = new ArrayList<>();
|
||||
|
||||
public void addError(String s){
|
||||
errors.add(s);
|
||||
}
|
||||
|
||||
public boolean hasError(){
|
||||
return errors.size()>0;
|
||||
}
|
||||
|
||||
public String getErrorMessage(){
|
||||
return errors.stream().reduce("", (a, b) -> a + " - " + b + "\n");
|
||||
}
|
||||
|
||||
public String[] getErrorMessages(){
|
||||
String[] res = new String[errors.size()];
|
||||
return errors.toArray(res);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
@ -200,30 +221,48 @@ public class DataFixerAPI {
|
|||
progress = null;
|
||||
}
|
||||
|
||||
Runnable runner = () -> {
|
||||
Supplier<State> runner = () -> {
|
||||
if (createBackup) {
|
||||
progress.progressStage(new TranslatableComponent("message.bclib.datafixer.progress.waitbackup"));
|
||||
EditWorldScreen.makeBackupAndShowToast(Minecraft.getInstance().getLevelSource(), levelID);
|
||||
}
|
||||
|
||||
if (applyFixes) {
|
||||
runDataFixes(dir, profile, progress);
|
||||
return runDataFixes(dir, profile, progress);
|
||||
}
|
||||
|
||||
return new State();
|
||||
};
|
||||
|
||||
if (showUI) {
|
||||
Thread fixerThread = new Thread(() -> {
|
||||
runner.run();
|
||||
|
||||
Minecraft.getInstance().execute(() -> {
|
||||
if (profile != null && showUI) {
|
||||
onResume.accept(applyFixes);
|
||||
}
|
||||
});
|
||||
final State state = runner.get();
|
||||
|
||||
Minecraft.getInstance()
|
||||
.execute(() -> {
|
||||
if (profile != null && showUI) {
|
||||
//something went wrong, show the user our error
|
||||
if (state.didFail || state.hasError()){
|
||||
showLevelFixErrorScreen(state, (markFixed)->{
|
||||
if (markFixed) {
|
||||
profile.markApplied();
|
||||
}
|
||||
onResume.accept(applyFixes);
|
||||
});
|
||||
} else {
|
||||
onResume.accept(applyFixes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
fixerThread.start();
|
||||
} else {
|
||||
runner.run();
|
||||
State state = runner.get();
|
||||
if (state.hasError()){
|
||||
LOGGER.error("There were Errors while fixing the Level:");
|
||||
LOGGER.error(state.getErrorMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -240,6 +279,11 @@ public class DataFixerAPI {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
@Environment(EnvType.CLIENT)
|
||||
private static void showLevelFixErrorScreen(State state, Listener onContinue){
|
||||
Minecraft.getInstance()
|
||||
.setScreen(new LevelFixErrorScreen(Minecraft.getInstance().screen, state.getErrorMessages(), onContinue));
|
||||
}
|
||||
|
||||
private static MigrationProfile loadProfileIfNeeded(File levelBaseDir){
|
||||
if (!Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_PATCH_CATEGORY, "applyPatches", true)) {
|
||||
|
@ -270,7 +314,7 @@ public class DataFixerAPI {
|
|||
Minecraft.getInstance().setScreen(new ConfirmFixScreen((Screen) null, whenFinished::accept));
|
||||
}
|
||||
|
||||
private static void runDataFixes(File dir, MigrationProfile profile, AtomicProgressListener progress) {
|
||||
private static State runDataFixes(File dir, MigrationProfile profile, AtomicProgressListener progress) {
|
||||
State state = new State();
|
||||
progress.resetAtomic();
|
||||
|
||||
|
@ -295,6 +339,7 @@ public class DataFixerAPI {
|
|||
profile.patchWorldData();
|
||||
} catch (PatchDidiFailException e){
|
||||
state.didFail = true;
|
||||
state.addError("Failed fixing worldconfig (" + e.getMessage() + ")");
|
||||
BCLib.LOGGER.error(e.getMessage());
|
||||
}
|
||||
progress.incAtomic(maxProgress);
|
||||
|
@ -313,6 +358,8 @@ public class DataFixerAPI {
|
|||
progress.incAtomic(maxProgress);
|
||||
|
||||
progress.stop();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
private static void fixLevel(MigrationProfile profile, State state, File levelBaseDir) {
|
||||
|
@ -342,15 +389,17 @@ public class DataFixerAPI {
|
|||
}
|
||||
catch (Exception e) {
|
||||
BCLib.LOGGER.error("Failed fixing Level-Data.");
|
||||
state.addError("Failed fixing Level-Data in level.dat (" + e.getMessage() + ")");
|
||||
state.didFail = true;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void fixPlayer(MigrationProfile data, State state, File file) {
|
||||
try {
|
||||
LOGGER.info("Inspecting " + file);
|
||||
CompoundTag player = NbtIo.readCompressed(file);
|
||||
|
||||
CompoundTag player = readNbt(file);
|
||||
boolean[] changed = { false };
|
||||
fixPlayerNbt(player, changed, data);
|
||||
|
||||
|
@ -361,11 +410,12 @@ public class DataFixerAPI {
|
|||
}
|
||||
catch (Exception e) {
|
||||
BCLib.LOGGER.error("Failed fixing Player-Data.");
|
||||
state.addError("Failed fixing Player-Data in " + file.getName() + " (" + e.getMessage() + ")");
|
||||
state.didFail = true;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void fixPlayerNbt(CompoundTag player, boolean[] changed, MigrationProfile data) {
|
||||
//Checking Inventory
|
||||
ListTag inventory = player.getList("Inventory", Tag.TAG_COMPOUND);
|
||||
|
@ -416,7 +466,7 @@ public class DataFixerAPI {
|
|||
for (int z = 0; z < 32; z++) {
|
||||
ChunkPos pos = new ChunkPos(x, z);
|
||||
changed[0] = false;
|
||||
if (region.hasChunk(pos)) {
|
||||
if (region.hasChunk(pos) && !state.didFail) {
|
||||
DataInputStream input = region.getChunkDataInputStream(pos);
|
||||
CompoundTag root = NbtIo.read(input);
|
||||
// if ((root.toString().contains("betternether:chest") || root.toString().contains("bclib:chest"))) {
|
||||
|
@ -442,6 +492,17 @@ public class DataFixerAPI {
|
|||
CompoundTag blockTagCompound = ((CompoundTag) blockTag);
|
||||
changed[0] |= data.replaceStringFromIDs(blockTagCompound, "Name");
|
||||
});
|
||||
|
||||
try {
|
||||
changed[0] |= data.patchBlockState(palette, ((CompoundTag) tag).getList("BlockStates", Tag.TAG_LONG));
|
||||
}
|
||||
catch (PatchDidiFailException e) {
|
||||
BCLib.LOGGER.error("Failed fixing BlockState in " + pos);
|
||||
state.addError("Failed fixing BlockState in " + pos + " (" + e.getMessage() + ")");
|
||||
state.didFail = true;
|
||||
changed[0] = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
if (changed[0]) {
|
||||
|
@ -450,7 +511,6 @@ public class DataFixerAPI {
|
|||
DataOutputStream output = region.getChunkDataOutputStream(pos);
|
||||
NbtIo.write(root, output);
|
||||
output.close();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -458,12 +518,13 @@ public class DataFixerAPI {
|
|||
region.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
BCLib.LOGGER.error("Failed fixing Player Data.");
|
||||
BCLib.LOGGER.error("Failed fixing Region.");
|
||||
state.addError("Failed fixing Region in " + file.getName() + " (" + e.getMessage() + ")");
|
||||
state.didFail = true;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static CompoundTag patchConfTag = null;
|
||||
static CompoundTag getPatchData(){
|
||||
if (patchConfTag==null) {
|
||||
|
@ -540,4 +601,12 @@ public class DataFixerAPI {
|
|||
Patch.getALL().add(patch.get());
|
||||
}
|
||||
|
||||
private static CompoundTag readNbt(File file) throws IOException {
|
||||
try {
|
||||
return NbtIo.readCompressed(file);
|
||||
} catch (ZipException e){
|
||||
return NbtIo.read(file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
47
src/main/java/ru/bclib/api/datafixer/ForcedLevelPatch.java
Normal file
47
src/main/java/ru/bclib/api/datafixer/ForcedLevelPatch.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
package ru.bclib.api.datafixer;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* A Patch for level.dat that is always executed no matter what Patchlevel is set in a world.
|
||||
*/
|
||||
public abstract class ForcedLevelPatch extends Patch {
|
||||
protected ForcedLevelPatch(@NotNull String modID, String version) {
|
||||
super(modID, version, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String, String> getIDReplacements() {
|
||||
return new HashMap<String, String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PatchFunction<CompoundTag, Boolean> getWorldDataPatcher() { return null; }
|
||||
|
||||
@Override
|
||||
public final PatchBiFunction<ListTag, ListTag, Boolean> getBlockStatePatcher() { return null; }
|
||||
|
||||
@Override
|
||||
public final List<String> getWorldDataIDPaths() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PatchFunction<CompoundTag, Boolean> getLevelDatPatcher() { return this::runLevelDatPatch; }
|
||||
|
||||
/**
|
||||
* Called with the contents of level.dat in {@code root}
|
||||
* @param root The contents of level.dat
|
||||
* @param profile The active migration profile
|
||||
* @return true, if the run did change the contents of root
|
||||
*/
|
||||
abstract protected Boolean runLevelDatPatch(CompoundTag root, MigrationProfile profile);
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import ru.bclib.util.ModUtil;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
@ -23,6 +24,7 @@ public class MigrationProfile {
|
|||
final Set<String> mods;
|
||||
final Map<String, String> idReplacements;
|
||||
final List<PatchFunction<CompoundTag, Boolean>> levelPatchers;
|
||||
final List<PatchBiFunction<ListTag, ListTag, Boolean>> statePatchers;
|
||||
final List<Patch> worldDataPatchers;
|
||||
final Map<String, List<String>> worldDataIDPaths;
|
||||
|
||||
|
@ -33,7 +35,7 @@ public class MigrationProfile {
|
|||
private boolean didRunPrePatch;
|
||||
private Exception prePatchException;
|
||||
|
||||
MigrationProfile(CompoundTag config) {
|
||||
MigrationProfile(CompoundTag config, boolean applyAll) {
|
||||
this.config = config;
|
||||
|
||||
this.mods = Collections.unmodifiableSet(Patch.getALL()
|
||||
|
@ -44,6 +46,7 @@ public class MigrationProfile {
|
|||
HashMap<String, String> replacements = new HashMap<String, String>();
|
||||
List<PatchFunction<CompoundTag, Boolean>> levelPatches = new LinkedList<>();
|
||||
List<Patch> worldDataPatches = new LinkedList<>();
|
||||
List<PatchBiFunction<ListTag, ListTag, Boolean>> statePatches = new LinkedList<>();
|
||||
HashMap<String, List<String>> worldDataIDPaths = new HashMap<>();
|
||||
for (String modID : mods) {
|
||||
|
||||
|
@ -54,12 +57,14 @@ public class MigrationProfile {
|
|||
List<String> paths = patch.getWorldDataIDPaths();
|
||||
if (paths!=null) worldDataIDPaths.put(modID, paths);
|
||||
|
||||
if (currentPatchLevel(modID) < patch.level) {
|
||||
if (applyAll || currentPatchLevel(modID) < patch.level || patch.alwaysApply) {
|
||||
replacements.putAll(patch.getIDReplacements());
|
||||
if (patch.getLevelDatPatcher()!=null)
|
||||
levelPatches.add(patch.getLevelDatPatcher());
|
||||
if (patch.getWorldDataPatcher()!=null)
|
||||
worldDataPatches.add(patch);
|
||||
if (patch.getBlockStatePatcher()!=null)
|
||||
statePatches.add(patch.getBlockStatePatcher());
|
||||
DataFixerAPI.LOGGER.info("Applying " + patch);
|
||||
}
|
||||
else {
|
||||
|
@ -72,6 +77,54 @@ public class MigrationProfile {
|
|||
this.idReplacements = Collections.unmodifiableMap(replacements);
|
||||
this.levelPatchers = Collections.unmodifiableList(levelPatches);
|
||||
this.worldDataPatchers = Collections.unmodifiableList(worldDataPatches);
|
||||
this.statePatchers = Collections.unmodifiableList(statePatches);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is supposed to be used by developers to apply id-patches to custom nbt structures. It is only
|
||||
* available in Developer-Mode
|
||||
*
|
||||
*/
|
||||
public static void fixCustomFolder(File dir){
|
||||
if (!BCLib.isDevEnvironment()) return;
|
||||
MigrationProfile profile = Patch.createMigrationData();
|
||||
List<File> nbts = getAllNbts(dir, null);
|
||||
nbts.parallelStream().forEach((file) -> {
|
||||
DataFixerAPI.LOGGER.info("Loading NBT " + file);
|
||||
try {
|
||||
CompoundTag root = NbtIo.readCompressed(file);
|
||||
boolean[] changed = {false};
|
||||
if (root.contains("palette")){
|
||||
ListTag items = root.getList("palette", Tag.TAG_COMPOUND);
|
||||
items.forEach(inTag -> {
|
||||
CompoundTag tag = (CompoundTag)inTag;
|
||||
changed[0] |= profile.replaceStringFromIDs(tag, "Name");
|
||||
});
|
||||
}
|
||||
|
||||
if (changed[0]){
|
||||
DataFixerAPI.LOGGER.info("Writing NBT " + file);
|
||||
NbtIo.writeCompressed(root, file);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static List<File> getAllNbts(File dir, List<File> list) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
for (File file : dir.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
getAllNbts(file, list);
|
||||
} else if (file.isFile() && file.getName().endsWith(".nbt")) {
|
||||
list.add(file);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
final public CompoundTag getLevelDat(File levelBaseDir){
|
||||
|
@ -124,12 +177,13 @@ public class MigrationProfile {
|
|||
final public void markApplied() {
|
||||
for (String modID : mods) {
|
||||
DataFixerAPI.LOGGER.info("Updating Patch-Level for '{}' from {} to {}", modID, ModUtil.convertModVersion(currentPatchLevel(modID)), ModUtil.convertModVersion(Patch.maxPatchLevel(modID)));
|
||||
config.putString(modID, Patch.maxPatchVersion(modID));
|
||||
if (config!=null)
|
||||
config.putString(modID, Patch.maxPatchVersion(modID));
|
||||
}
|
||||
}
|
||||
|
||||
public String currentPatchVersion(@NotNull String modID) {
|
||||
if (!config.contains(modID)) return "0.0.0";
|
||||
if (config==null || !config.contains(modID)) return "0.0.0";
|
||||
return config.getString(modID);
|
||||
}
|
||||
|
||||
|
@ -255,4 +309,12 @@ public class MigrationProfile {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean patchBlockState(ListTag palette, ListTag states) throws PatchDidiFailException{
|
||||
boolean changed = false;
|
||||
for (PatchBiFunction<ListTag, ListTag, Boolean> f : statePatchers) {
|
||||
changed |= f.apply(palette, states, this);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ru.bclib.api.datafixer;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import ru.bclib.util.ModUtil;
|
||||
|
||||
|
@ -30,6 +31,11 @@ public abstract class Patch {
|
|||
@NotNull
|
||||
public final String modID;
|
||||
|
||||
/**
|
||||
* This Mod is tested for each level start
|
||||
*/
|
||||
public final boolean alwaysApply;
|
||||
|
||||
static List<Patch> getALL() {
|
||||
return ALL;
|
||||
}
|
||||
|
@ -81,6 +87,19 @@ public abstract class Patch {
|
|||
* {@link Patch#maxPatchVersion(String)}
|
||||
*/
|
||||
protected Patch(@NotNull String modID, String version) {
|
||||
this(modID, version, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal Constructor used to create patches that can allways run (no matter what patchlevel a level has)
|
||||
* @param modID The ID of the Mod
|
||||
* @param version The mod-version that introduces the patch. When {@Code runAllways} is set, this version will
|
||||
* determine the patchlevel that is written to the level
|
||||
* @param alwaysApply When true, this patch is always active, no matter the patchlevel of the world.
|
||||
* This should be used sparingly and just for patches that apply to level.dat (as they only take
|
||||
* effect when changes are detected). Use {@link ForcedLevelPatch} to instatiate.
|
||||
*/
|
||||
Patch(@NotNull String modID, String version, boolean alwaysApply) {
|
||||
//Patchlevels need to be unique and registered in ascending order
|
||||
if (modID == null || "".equals(modID)) {
|
||||
throw new RuntimeException("[INTERNAL ERROR] Patches need a valid modID!");
|
||||
|
@ -91,6 +110,7 @@ public abstract class Patch {
|
|||
}
|
||||
|
||||
this.version = version;
|
||||
this.alwaysApply = alwaysApply;
|
||||
this.level = ModUtil.convertModVersion(version);
|
||||
if (!ALL.stream()
|
||||
.filter(p -> p.modID
|
||||
|
@ -145,22 +165,46 @@ public abstract class Patch {
|
|||
*/
|
||||
public PatchFunction<CompoundTag, Boolean> getWorldDataPatcher() { return null; }
|
||||
|
||||
/**
|
||||
* Return a {@link PatchBiFunction} that is called with pallette and blockstate of
|
||||
* each chunk in every region. This method is called AFTER all ID replacements
|
||||
* from {@link #getIDReplacements()} were applied to the pallete.
|
||||
*
|
||||
* The first parameter is the palette and the second is the blockstate.
|
||||
*
|
||||
* The function needs to return {@code true}, if changes were made to the data.
|
||||
* If an error occurs, the method should throw a {@link PatchDidiFailException}
|
||||
*
|
||||
* The default implementation of this method returns null.
|
||||
*
|
||||
* @return {@code true} if changes were applied and we need to save the data
|
||||
*/
|
||||
public PatchBiFunction<ListTag, ListTag, Boolean> getBlockStatePatcher() { return null; }
|
||||
|
||||
/**
|
||||
* Generates ready to use data for all currently registered patches. The list of
|
||||
* patches is selected by the current patch-level of the world.
|
||||
* <p>
|
||||
* A {@link #Patch} with a given {@link #level} is only included if the patch-level of the
|
||||
* world is less
|
||||
* @param config The current patch-level configuration
|
||||
* @param levelBaseDir The location of the level
|
||||
* @param config The current patch-level configuration*
|
||||
* @return a new {@link MigrationProfile} Object.
|
||||
*/
|
||||
static MigrationProfile createMigrationData(CompoundTag config) {
|
||||
return new MigrationProfile(config);
|
||||
return new MigrationProfile(config, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is supposed to be used by developers to apply id-patches to custom nbt structures. It is only
|
||||
* available in Developer-Mode
|
||||
*
|
||||
*/
|
||||
static MigrationProfile createMigrationData() {
|
||||
return new MigrationProfile(null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of paths,where your mod may IDs in your {@link ru.bclib.api.WorldDataAPI}-File.
|
||||
* Returns a list of paths where your mod stores IDs in your {@link ru.bclib.api.WorldDataAPI}-File.
|
||||
* <p>
|
||||
* {@link DataFixerAPI} will use information from the latest patch that returns a non-null-result. This list is used
|
||||
* to automatically fix changed IDs from all active patches (see {@link Patch#getIDReplacements()}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package ru.bclib.api.datafixer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PatchBiFunction<U, V, R> {
|
||||
R apply(U t, V v, MigrationProfile profile) throws PatchDidiFailException;
|
||||
}
|
|
@ -25,7 +25,7 @@ import java.util.List;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider, RenderLayerProvider {
|
||||
private final Block sapling;
|
||||
protected final Block sapling;
|
||||
|
||||
private static FabricBlockSettings makeLeaves(MaterialColor color) {
|
||||
return FabricBlockSettings.copyOf(Blocks.OAK_LEAVES)
|
||||
|
@ -37,12 +37,12 @@ public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider,
|
|||
.suffocates((state, world, pos) -> false)
|
||||
.blockVision((state, world, pos) -> false);
|
||||
}
|
||||
|
||||
|
||||
public BaseLeavesBlock(Block sapling, MaterialColor color, Consumer<FabricBlockSettings> customizeProperties) {
|
||||
super(BaseBlock.acceptAndReturn(customizeProperties, makeLeaves(color)));
|
||||
this.sapling = sapling;
|
||||
}
|
||||
|
||||
|
||||
public BaseLeavesBlock(Block sapling, MaterialColor color, int light, Consumer<FabricBlockSettings> customizeProperties) {
|
||||
super(BaseBlock.acceptAndReturn(customizeProperties, makeLeaves(color).luminance(light)));
|
||||
this.sapling = sapling;
|
||||
|
|
|
@ -9,6 +9,7 @@ import net.minecraft.world.item.Item;
|
|||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.OreBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
@ -28,11 +29,16 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider {
|
|||
private final int maxCount;
|
||||
|
||||
public BaseOreBlock(Item drop, int minCount, int maxCount, int experience) {
|
||||
super(FabricBlockSettings.of(Material.STONE, MaterialColor.SAND)
|
||||
this(drop, minCount, maxCount, experience, FabricBlockSettings.of(Material.STONE, MaterialColor.SAND)
|
||||
.hardness(3F)
|
||||
.resistance(9F)
|
||||
.requiresCorrectToolForDrops()
|
||||
.sound(SoundType.STONE), UniformInt.of(1, experience));
|
||||
.sound(SoundType.STONE));
|
||||
|
||||
}
|
||||
|
||||
public BaseOreBlock(Item drop, int minCount, int maxCount, int experience, Properties properties) {
|
||||
super(properties, UniformInt.of(experience>0?1:0, experience));
|
||||
this.dropItem = drop;
|
||||
this.minCount = minCount;
|
||||
this.maxCount = maxCount;
|
||||
|
@ -41,10 +47,14 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider {
|
|||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
|
||||
return getDroppedItems(this, dropItem, maxCount, minCount, state, builder);
|
||||
}
|
||||
|
||||
public static List<ItemStack> getDroppedItems(ItemLike block, Item dropItem, int maxCount, int minCount, BlockState state, LootContext.Builder builder) {
|
||||
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
|
||||
if (tool != null && tool.isCorrectToolForDrops(state)) {
|
||||
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
return Collections.singletonList(new ItemStack(block));
|
||||
}
|
||||
int count;
|
||||
int enchantment = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package ru.bclib.blocks;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public abstract class FeatureHangingSaplingBlock extends FeatureSaplingBlockCommon{
|
||||
private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12);
|
||||
public FeatureHangingSaplingBlock() {
|
||||
super();
|
||||
}
|
||||
|
||||
public FeatureHangingSaplingBlock(int light) {
|
||||
super(light);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(BlockState blockState, LevelReader levelReader, BlockPos blockPos) {
|
||||
final BlockPos target = blockPos.above();
|
||||
return this.mayPlaceOn(levelReader.getBlockState(target), levelReader, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
|
||||
return SHAPE;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,134 +1,26 @@
|
|||
package ru.bclib.blocks;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.SaplingBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import ru.bclib.client.models.BasePatterns;
|
||||
import ru.bclib.client.models.ModelsHelper;
|
||||
import ru.bclib.client.models.PatternsHelper;
|
||||
import ru.bclib.client.render.BCLRenderLayer;
|
||||
import ru.bclib.interfaces.BlockModelProvider;
|
||||
import ru.bclib.interfaces.RenderLayerProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProvider, BlockModelProvider {
|
||||
public abstract class FeatureSaplingBlock extends FeatureSaplingBlockCommon {
|
||||
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
|
||||
|
||||
public FeatureSaplingBlock() {
|
||||
super(
|
||||
null,
|
||||
FabricBlockSettings.of(Material.PLANT)
|
||||
.breakByHand(true)
|
||||
.collidable(false)
|
||||
.instabreak()
|
||||
.sound(SoundType.GRASS)
|
||||
.randomTicks()
|
||||
);
|
||||
super();
|
||||
}
|
||||
|
||||
public FeatureSaplingBlock(int light) {
|
||||
super(
|
||||
null,
|
||||
FabricBlockSettings.of(Material.PLANT)
|
||||
.breakByHand(true)
|
||||
.collidable(false)
|
||||
.luminance(light)
|
||||
.instabreak()
|
||||
.sound(SoundType.GRASS)
|
||||
.randomTicks()
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract Feature<?> getFeature();
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
super(light);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
|
||||
return SHAPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
|
||||
if (!canSurvive(state, world, pos)) return Blocks.AIR.defaultBlockState();
|
||||
else return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) {
|
||||
return random.nextInt(16) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void advanceTree(ServerLevel world, BlockPos pos, BlockState blockState, Random random) {
|
||||
FeaturePlaceContext context = new FeaturePlaceContext(
|
||||
Optional.empty(),
|
||||
world,
|
||||
world.getChunkSource().getGenerator(),
|
||||
random,
|
||||
pos,
|
||||
null
|
||||
);
|
||||
getFeature().place(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
|
||||
this.tick(state, world, pos, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
|
||||
super.tick(state, world, pos, random);
|
||||
if (isBonemealSuccess(world, random, pos, state)) {
|
||||
performBonemeal(world, random, pos, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BCLRenderLayer getRenderLayer() {
|
||||
return BCLRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public BlockModel getItemModel(ResourceLocation resourceLocation) {
|
||||
return ModelsHelper.createBlockItem(resourceLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
|
||||
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation);
|
||||
return ModelsHelper.fromPattern(pattern);
|
||||
}
|
||||
}
|
||||
|
|
129
src/main/java/ru/bclib/blocks/FeatureSaplingBlockCommon.java
Normal file
129
src/main/java/ru/bclib/blocks/FeatureSaplingBlockCommon.java
Normal file
|
@ -0,0 +1,129 @@
|
|||
package ru.bclib.blocks;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.SaplingBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import ru.bclib.client.models.BasePatterns;
|
||||
import ru.bclib.client.models.ModelsHelper;
|
||||
import ru.bclib.client.models.PatternsHelper;
|
||||
import ru.bclib.client.render.BCLRenderLayer;
|
||||
import ru.bclib.interfaces.BlockModelProvider;
|
||||
import ru.bclib.interfaces.RenderLayerProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
|
||||
abstract class FeatureSaplingBlockCommon extends SaplingBlock implements RenderLayerProvider, BlockModelProvider {
|
||||
public FeatureSaplingBlockCommon() {
|
||||
super(
|
||||
null,
|
||||
FabricBlockSettings.of(Material.PLANT)
|
||||
.breakByHand(true)
|
||||
.collidable(false)
|
||||
.instabreak()
|
||||
.sound(SoundType.GRASS)
|
||||
.randomTicks()
|
||||
);
|
||||
}
|
||||
|
||||
public FeatureSaplingBlockCommon(int light) {
|
||||
super(
|
||||
null,
|
||||
FabricBlockSettings.of(Material.PLANT)
|
||||
.breakByHand(true)
|
||||
.collidable(false)
|
||||
.luminance(light)
|
||||
.instabreak()
|
||||
.sound(SoundType.GRASS)
|
||||
.randomTicks()
|
||||
);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* Override {@link #getFeature(BlockState)} directly. Will be removed in 5.x
|
||||
*/
|
||||
protected Feature<?> getFeature() { return null; }
|
||||
|
||||
protected Feature<?> getFeature(BlockState state){
|
||||
return getFeature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
|
||||
if (!canSurvive(state, world, pos)) return Blocks.AIR.defaultBlockState();
|
||||
else return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) {
|
||||
return random.nextInt(16) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void advanceTree(ServerLevel world, BlockPos pos, BlockState blockState, Random random) {
|
||||
FeaturePlaceContext context = new FeaturePlaceContext(
|
||||
world,
|
||||
world.getChunkSource().getGenerator(),
|
||||
random,
|
||||
pos,
|
||||
null
|
||||
);
|
||||
getFeature(blockState).place(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
|
||||
this.tick(state, world, pos, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
|
||||
super.tick(state, world, pos, random);
|
||||
if (isBonemealSuccess(world, random, pos, state)) {
|
||||
performBonemeal(world, random, pos, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BCLRenderLayer getRenderLayer() {
|
||||
return BCLRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public BlockModel getItemModel(ResourceLocation resourceLocation) {
|
||||
return ModelsHelper.createBlockItem(resourceLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
|
||||
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation);
|
||||
return ModelsHelper.fromPattern(pattern);
|
||||
}
|
||||
}
|
16
src/main/java/ru/bclib/blocks/LeveledAnvilBlock.java
Normal file
16
src/main/java/ru/bclib/blocks/LeveledAnvilBlock.java
Normal file
|
@ -0,0 +1,16 @@
|
|||
package ru.bclib.blocks;
|
||||
|
||||
import net.minecraft.world.level.material.MaterialColor;
|
||||
|
||||
public class LeveledAnvilBlock extends BaseAnvilBlock{
|
||||
protected final int level;
|
||||
|
||||
public LeveledAnvilBlock(MaterialColor color, int level) {
|
||||
super(color);
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public int getCraftingLevel() {
|
||||
return level;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
|||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.material.MaterialColor;
|
||||
import ru.bclib.api.TagAPI;
|
||||
import ru.bclib.client.render.BCLRenderLayer;
|
||||
import ru.bclib.interfaces.RenderLayerProvider;
|
||||
|
||||
|
@ -17,6 +18,8 @@ public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerPr
|
|||
.isValidSpawn((state, world, pos, type) -> false)
|
||||
.isSuffocating((state, world, pos) -> false)
|
||||
.isViewBlocking((state, world, pos) -> false));
|
||||
|
||||
TagAPI.addTags(this, TagAPI.BLOCK_LEAVES);
|
||||
}
|
||||
|
||||
public SimpleLeavesBlock(MaterialColor color, int light) {
|
||||
|
@ -29,6 +32,8 @@ public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerPr
|
|||
.isValidSpawn((state, world, pos, type) -> false)
|
||||
.isSuffocating((state, world, pos) -> false)
|
||||
.isViewBlocking((state, world, pos) -> false));
|
||||
|
||||
TagAPI.addTags(this, TagAPI.BLOCK_LEAVES);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -88,18 +88,21 @@ public class ModelsHelper {
|
|||
|
||||
public static class MultiPartBuilder {
|
||||
|
||||
private final static MultiPartBuilder BUILDER = new MultiPartBuilder();
|
||||
//private final static MultiPartBuilder BUILDER = new MultiPartBuilder();
|
||||
|
||||
public static MultiPartBuilder create(StateDefinition<Block, BlockState> stateDefinition) {
|
||||
BUILDER.stateDefinition = stateDefinition;
|
||||
BUILDER.modelParts.clear();
|
||||
return BUILDER;
|
||||
// BUILDER.stateDefinition = stateDefinition;
|
||||
//BUILDER.modelParts.clear();
|
||||
// return BUILDER;
|
||||
return new MultiPartBuilder(stateDefinition);
|
||||
}
|
||||
|
||||
private final List<ModelPart> modelParts = Lists.newArrayList();
|
||||
private StateDefinition<Block, BlockState> stateDefinition;
|
||||
|
||||
private MultiPartBuilder() {}
|
||||
private MultiPartBuilder(StateDefinition<Block, BlockState> stateDefinition) {
|
||||
this.stateDefinition = stateDefinition;
|
||||
}
|
||||
|
||||
public ModelPart part(ResourceLocation modelId) {
|
||||
ModelPart part = new ModelPart(modelId);
|
||||
|
|
|
@ -3,6 +3,7 @@ package ru.bclib.client.render;
|
|||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
|
@ -22,46 +23,77 @@ public class CustomBackgroundRenderer {
|
|||
private static final MutableBlockPos MUT_POS = new MutableBlockPos();
|
||||
private static final float[] FOG_DENSITY = new float[8];
|
||||
private static final int GRID_SIZE = 32;
|
||||
private static float fogStart = 0;
|
||||
private static float fogEnd = 192;
|
||||
|
||||
public static boolean applyFogDensity(Camera camera, FogRenderer.FogMode fogMode, float viewDistance, boolean thickFog) {
|
||||
Entity entity = camera.getEntity();
|
||||
FogType fogType = camera.getFluidInCamera();
|
||||
if (fogType != FogType.WATER) {
|
||||
if (shouldIgnore(entity.level, (int) entity.getX(), (int) entity.getEyeY(), (int) entity.getZ())) {
|
||||
return false;
|
||||
}
|
||||
float fog = getFogDensity(entity.level, entity.getX(), entity.getEyeY(), entity.getZ());
|
||||
BackgroundInfo.fogDensity = fog;
|
||||
float start = viewDistance * 0.75F / fog;
|
||||
float end = viewDistance / fog;
|
||||
|
||||
if (entity instanceof LivingEntity) {
|
||||
LivingEntity livingEntity = (LivingEntity) entity;
|
||||
MobEffectInstance effect = livingEntity.getEffect(MobEffects.BLINDNESS);
|
||||
if (effect != null) {
|
||||
int duration = effect.getDuration();
|
||||
if (duration > 20) {
|
||||
start = 0;
|
||||
end *= 0.03F;
|
||||
BackgroundInfo.blindness = 1;
|
||||
}
|
||||
else {
|
||||
float delta = (float) duration / 20F;
|
||||
BackgroundInfo.blindness = delta;
|
||||
start = Mth.lerp(delta, start, 0);
|
||||
end = Mth.lerp(delta, end, end * 0.03F);
|
||||
}
|
||||
|
||||
if (fogType == FogType.WATER || fogType == FogType.LAVA || fogMode != FogMode.FOG_SKY) {
|
||||
BackgroundInfo.fogDensity = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
Entity entity = camera.getEntity();
|
||||
|
||||
if (!isForcedDimension(entity.level) && shouldIgnoreArea(entity.level, (int) entity.getX(), (int) entity.getEyeY(), (int) entity.getZ())) {
|
||||
BackgroundInfo.fogDensity = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
float fog = getFogDensity(entity.level, entity.getX(), entity.getEyeY(), entity.getZ());
|
||||
BackgroundInfo.fogDensity = fog;
|
||||
|
||||
if (thickFog) {
|
||||
fogStart = viewDistance * 0.05F / fog;
|
||||
fogEnd = Math.min(viewDistance, 192.0F) * 0.5F / fog;
|
||||
}
|
||||
else {
|
||||
fogStart = viewDistance * 0.75F / fog;
|
||||
fogEnd = viewDistance / fog;
|
||||
}
|
||||
|
||||
if (entity instanceof LivingEntity) {
|
||||
LivingEntity livingEntity = (LivingEntity) entity;
|
||||
MobEffectInstance effect = livingEntity.getEffect(MobEffects.BLINDNESS);
|
||||
if (effect != null) {
|
||||
int duration = effect.getDuration();
|
||||
if (duration > 20) {
|
||||
fogStart = 0;
|
||||
fogEnd *= 0.03F;
|
||||
BackgroundInfo.blindness = 1;
|
||||
}
|
||||
else {
|
||||
BackgroundInfo.blindness = 0;
|
||||
float delta = (float) duration / 20F;
|
||||
BackgroundInfo.blindness = delta;
|
||||
fogStart = Mth.lerp(delta, fogStart, 0);
|
||||
fogEnd = Mth.lerp(delta, fogEnd, fogEnd * 0.03F);
|
||||
}
|
||||
}
|
||||
|
||||
RenderSystem.setShaderFogStart(start);
|
||||
RenderSystem.setShaderFogEnd(end);
|
||||
return true;
|
||||
else {
|
||||
BackgroundInfo.blindness = 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
RenderSystem.setShaderFogStart(fogStart);
|
||||
RenderSystem.setShaderFogEnd(fogEnd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isForcedDimension(Level level) {
|
||||
return level.dimension() == Level.END || level.dimension() == Level.NETHER;
|
||||
}
|
||||
|
||||
private static boolean shouldIgnoreArea(Level level, int x, int y, int z) {
|
||||
for (int i = -8; i <= 8; i += 8) {
|
||||
for (int j = -8; j <= 8; j += 8) {
|
||||
if (!shouldIgnore(level, x + i, y, z + j)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean shouldIgnore(Level level, int x, int y, int z) {
|
||||
|
|
|
@ -39,358 +39,372 @@ import ru.bclib.complexmaterials.entry.RecipeEntry;
|
|||
import ru.bclib.recipes.GridRecipe;
|
||||
|
||||
public class WoodenComplexMaterial extends ComplexMaterial {
|
||||
public static final ResourceLocation MATERIAL_ID = BCLib.makeID("wooden_material");
|
||||
|
||||
public static final String BLOCK_CRAFTING_TABLE = "crafting_table";
|
||||
public static final String BLOCK_STRIPPED_BARK = "stripped_bark";
|
||||
public static final String BLOCK_STRIPPED_LOG = "stripped_log";
|
||||
public static final String BLOCK_PRESSURE_PLATE = "plate";
|
||||
public static final String BLOCK_BOOKSHELF = "bookshelf";
|
||||
public static final String BLOCK_COMPOSTER = "composter";
|
||||
public static final String BLOCK_TRAPDOOR = "trapdoor";
|
||||
public static final String BLOCK_BARREL = "barrel";
|
||||
public static final String BLOCK_BUTTON = "button";
|
||||
public static final String BLOCK_LADDER = "ladder";
|
||||
public static final String BLOCK_PLANKS = "planks";
|
||||
public static final String BLOCK_STAIRS = "stairs";
|
||||
public static final String BLOCK_CHEST = "chest";
|
||||
public static final String BLOCK_FENCE = "fence";
|
||||
public static final String BLOCK_BARK = "bark";
|
||||
public static final String BLOCK_DOOR = "door";
|
||||
public static final String BLOCK_GATE = "gate";
|
||||
public static final String BLOCK_SIGN = "sign";
|
||||
public static final String BLOCK_SLAB = "slab";
|
||||
public static final String BLOCK_LOG = "log";
|
||||
|
||||
public static final String TAG_LOGS = "logs";
|
||||
|
||||
public final MaterialColor planksColor;
|
||||
public final MaterialColor woodColor;
|
||||
|
||||
public WoodenComplexMaterial(String modID, String baseName, String receipGroupPrefix, MaterialColor woodColor, MaterialColor planksColor) {
|
||||
super(modID, baseName, receipGroupPrefix);
|
||||
this.planksColor = planksColor;
|
||||
this.woodColor = woodColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FabricBlockSettings getBlockSettings() {
|
||||
return FabricBlockSettings.copyOf(Blocks.OAK_PLANKS).mapColor(planksColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getMaterialID() {
|
||||
return MATERIAL_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTags() {
|
||||
addBlockTag(TagAPI.makeBlockTag(getModID(), getBaseName() + "_logs"));
|
||||
addItemTag(TagAPI.makeItemTag(getModID(), getBaseName() + "_logs"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initDefault(FabricBlockSettings blockSettings, FabricItemSettings itemSettings) {
|
||||
initBase(blockSettings, itemSettings);
|
||||
initStorage(blockSettings, itemSettings);
|
||||
initDecorations(blockSettings, itemSettings);
|
||||
}
|
||||
|
||||
final protected void initBase(FabricBlockSettings blockSettings, FabricItemSettings itemSettings) {
|
||||
Tag.Named<Block> tagBlockLog = getBlockTag(TAG_LOGS);
|
||||
Tag.Named<Item> tagItemLog = getItemTag(TAG_LOGS);
|
||||
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_STRIPPED_LOG, (complexMaterial, settings) -> {
|
||||
return new BaseRotatedPillarBlock(settings);
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_STRIPPED_BARK, (complexMaterial, settings) -> {
|
||||
return new BaseBarkBlock(settings);
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_LOG, (complexMaterial, settings) -> {
|
||||
return new BaseStripableLogBlock(woodColor, getBlock(BLOCK_STRIPPED_LOG));
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_BARK, (complexMaterial, settings) -> {
|
||||
return new StripableBarkBlock(woodColor, getBlock(BLOCK_STRIPPED_BARK));
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
addBlockEntry(new BlockEntry(BLOCK_PLANKS, (complexMaterial, settings) -> {
|
||||
return new BaseBlock(settings);
|
||||
}).setBlockTags(BlockTags.PLANKS).setItemTags(ItemTags.PLANKS));
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_STAIRS, (complexMaterial, settings) -> {
|
||||
return new BaseStairsBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.WOODEN_STAIRS, BlockTags.STAIRS).setItemTags(ItemTags.WOODEN_STAIRS, ItemTags.STAIRS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_SLAB, (complexMaterial, settings) -> {
|
||||
return new BaseSlabBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.WOODEN_SLABS, BlockTags.SLABS).setItemTags(ItemTags.WOODEN_SLABS, ItemTags.SLABS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_FENCE, (complexMaterial, settings) -> {
|
||||
return new BaseFenceBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.FENCES, BlockTags.WOODEN_FENCES).setItemTags(ItemTags.FENCES, ItemTags.WOODEN_FENCES));
|
||||
addBlockEntry(new BlockEntry(BLOCK_GATE, (complexMaterial, settings) -> {
|
||||
return new BaseGateBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.FENCE_GATES));
|
||||
addBlockEntry(new BlockEntry(BLOCK_BUTTON, (complexMaterial, settings) -> {
|
||||
return new BaseWoodenButtonBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.BUTTONS, BlockTags.WOODEN_BUTTONS).setItemTags(ItemTags.BUTTONS, ItemTags.WOODEN_BUTTONS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_PRESSURE_PLATE, (complexMaterial, settings) -> {
|
||||
return new WoodenPressurePlateBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.PRESSURE_PLATES, BlockTags.WOODEN_PRESSURE_PLATES).setItemTags(ItemTags.WOODEN_PRESSURE_PLATES));
|
||||
addBlockEntry(new BlockEntry(BLOCK_TRAPDOOR, (complexMaterial, settings) -> {
|
||||
return new BaseTrapdoorBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.TRAPDOORS, BlockTags.WOODEN_TRAPDOORS).setItemTags(ItemTags.TRAPDOORS, ItemTags.WOODEN_TRAPDOORS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_DOOR, (complexMaterial, settings) -> {
|
||||
return new BaseDoorBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.DOORS, BlockTags.WOODEN_DOORS).setItemTags(ItemTags.DOORS, ItemTags.WOODEN_DOORS));
|
||||
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_LADDER, (complexMaterial, settings) -> {
|
||||
return new BaseLadderBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.CLIMBABLE));
|
||||
addBlockEntry(new BlockEntry(BLOCK_SIGN, (complexMaterial, settings) -> {
|
||||
return new BaseSignBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.SIGNS).setItemTags(ItemTags.SIGNS));
|
||||
|
||||
|
||||
}
|
||||
|
||||
final protected void initStorage(FabricBlockSettings blockSettings, FabricItemSettings itemSettings){
|
||||
addBlockEntry(new BlockEntry(BLOCK_CHEST, (complexMaterial, settings) -> {
|
||||
return new BaseChestBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(TagAPI.BLOCK_CHEST).setItemTags(TagAPI.ITEM_CHEST));
|
||||
addBlockEntry(new BlockEntry(BLOCK_BARREL, (complexMaterial, settings) -> {
|
||||
return new BaseBarrelBlock(getBlock(BLOCK_PLANKS));
|
||||
}));
|
||||
}
|
||||
|
||||
final protected void initDecorations(FabricBlockSettings blockSettings, FabricItemSettings itemSettings){
|
||||
addBlockEntry(new BlockEntry(BLOCK_CRAFTING_TABLE, (complexMaterial, settings) -> {
|
||||
return new BaseCraftingTableBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(TagAPI.BLOCK_WORKBENCHES).setItemTags(TagAPI.ITEM_WORKBENCHES));
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_BOOKSHELF, (complexMaterial, settings) -> {
|
||||
return new BaseBookshelfBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(TagAPI.BLOCK_BOOKSHELVES));
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_COMPOSTER, (complexMaterial, settings) -> {
|
||||
return new BaseComposterBlock(getBlock(BLOCK_PLANKS));
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initFlammable(FlammableBlockRegistry registry) {
|
||||
getBlocks().forEach(block -> {
|
||||
registry.add(block, 5, 20);
|
||||
});
|
||||
|
||||
registry.add(getBlock(BLOCK_LOG), 5, 5);
|
||||
registry.add(getBlock(BLOCK_BARK), 5, 5);
|
||||
registry.add(getBlock(BLOCK_STRIPPED_LOG), 5, 5);
|
||||
registry.add(getBlock(BLOCK_STRIPPED_BARK), 5, 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initDefaultRecipes() {
|
||||
Block planks = getBlock(BLOCK_PLANKS);
|
||||
addRecipeEntry(new RecipeEntry("planks", (material, config, id) -> {
|
||||
Block log_stripped = getBlock(BLOCK_STRIPPED_LOG);
|
||||
Block bark_stripped = getBlock(BLOCK_STRIPPED_BARK);
|
||||
Block log = getBlock(BLOCK_LOG);
|
||||
Block bark = getBlock(BLOCK_BARK);
|
||||
GridRecipe.make(id, planks)
|
||||
.checkConfig(config)
|
||||
.setOutputCount(4)
|
||||
.setList("#")
|
||||
.addMaterial('#', log, bark, log_stripped, bark_stripped)
|
||||
.setGroup(receipGroupPrefix +"_planks")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("stairs", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_STAIRS))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(4)
|
||||
.setShape("# ", "## ", "###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_planks_stairs")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("slab", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_SLAB))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(6)
|
||||
.setShape("###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_planks_slabs")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("fence", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_FENCE))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("#I#", "#I#")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix +"_planks_fences")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("gate", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_GATE))
|
||||
.checkConfig(config)
|
||||
.setShape("I#I", "I#I")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix +"_planks_gates")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("button", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BUTTON))
|
||||
.checkConfig(config)
|
||||
.setList("#")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_planks_buttons")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("pressure_plate", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_PRESSURE_PLATE))
|
||||
.checkConfig(config)
|
||||
.setShape("##")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_planks_plates")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("trapdoor", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_TRAPDOOR))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(2)
|
||||
.setShape("###", "###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_trapdoors")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("door", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_DOOR))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("##", "##", "##")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_doors")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("crafting_table", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_CRAFTING_TABLE))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_tables")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("ladder", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_LADDER))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("I I", "I#I", "I I")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix +"_ladders")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("sign", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_SIGN))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("###", "###", " I ")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix +"_signs")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("chest", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_CHEST))
|
||||
.checkConfig(config)
|
||||
.setShape("###", "# #", "###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix +"_chests")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("barrel", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BARREL))
|
||||
.checkConfig(config)
|
||||
.setShape("#S#", "# #", "#S#")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('S', getBlock(BLOCK_SLAB))
|
||||
.setGroup(receipGroupPrefix +"_barrels")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("bookshelf", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BOOKSHELF))
|
||||
.checkConfig(config)
|
||||
.setShape("###", "PPP", "###")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('P', Items.BOOK)
|
||||
.setGroup(receipGroupPrefix +"_bookshelves")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("bark", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BARK))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_LOG))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("log", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_LOG))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_BARK))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("stripped_bark", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_STRIPPED_BARK))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_STRIPPED_LOG))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("stripped_log", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_STRIPPED_LOG))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_STRIPPED_BARK))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("composter", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_COMPOSTER))
|
||||
.checkConfig(config)
|
||||
.setShape("# #", "# #", "###")
|
||||
.addMaterial('#', getBlock(BLOCK_SLAB))
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("shulker", (material, config, id) -> {
|
||||
GridRecipe.make(id, Blocks.SHULKER_BOX)
|
||||
.checkConfig(config)
|
||||
.setShape("S", "#", "S")
|
||||
.addMaterial('S', Items.SHULKER_SHELL)
|
||||
.addMaterial('#', getBlock(BLOCK_CHEST))
|
||||
.build();
|
||||
}));
|
||||
}
|
||||
public static final ResourceLocation MATERIAL_ID = BCLib.makeID("wooden_material");
|
||||
|
||||
public static final String BLOCK_CRAFTING_TABLE = "crafting_table";
|
||||
public static final String BLOCK_STRIPPED_BARK = "stripped_bark";
|
||||
public static final String BLOCK_STRIPPED_LOG = "stripped_log";
|
||||
public static final String BLOCK_PRESSURE_PLATE = "plate";
|
||||
public static final String BLOCK_BOOKSHELF = "bookshelf";
|
||||
public static final String BLOCK_COMPOSTER = "composter";
|
||||
public static final String BLOCK_TRAPDOOR = "trapdoor";
|
||||
public static final String BLOCK_BARREL = "barrel";
|
||||
public static final String BLOCK_BUTTON = "button";
|
||||
public static final String BLOCK_LADDER = "ladder";
|
||||
public static final String BLOCK_PLANKS = "planks";
|
||||
public static final String BLOCK_STAIRS = "stairs";
|
||||
public static final String BLOCK_CHEST = "chest";
|
||||
public static final String BLOCK_FENCE = "fence";
|
||||
public static final String BLOCK_BARK = "bark";
|
||||
public static final String BLOCK_DOOR = "door";
|
||||
public static final String BLOCK_GATE = "gate";
|
||||
public static final String BLOCK_SIGN = "sign";
|
||||
public static final String BLOCK_SLAB = "slab";
|
||||
public static final String BLOCK_LOG = "log";
|
||||
|
||||
public static final String TAG_LOGS = "logs";
|
||||
|
||||
public final MaterialColor planksColor;
|
||||
public final MaterialColor woodColor;
|
||||
|
||||
public WoodenComplexMaterial(String modID, String baseName, String receipGroupPrefix, MaterialColor woodColor, MaterialColor planksColor) {
|
||||
super(modID, baseName, receipGroupPrefix);
|
||||
this.planksColor = planksColor;
|
||||
this.woodColor = woodColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FabricBlockSettings getBlockSettings() {
|
||||
return FabricBlockSettings.copyOf(Blocks.OAK_PLANKS)
|
||||
.materialColor(planksColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getMaterialID() {
|
||||
return MATERIAL_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTags() {
|
||||
addBlockTag(TagAPI.makeBlockTag(getModID(), getBaseName() + "_logs"));
|
||||
addItemTag(TagAPI.makeItemTag(getModID(), getBaseName() + "_logs"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initDefault(FabricBlockSettings blockSettings, FabricItemSettings itemSettings) {
|
||||
initBase(blockSettings, itemSettings);
|
||||
initStorage(blockSettings, itemSettings);
|
||||
initDecorations(blockSettings, itemSettings);
|
||||
}
|
||||
|
||||
final protected void initBase(FabricBlockSettings blockSettings, FabricItemSettings itemSettings) {
|
||||
Tag.Named<Block> tagBlockLog = getBlockTag(TAG_LOGS);
|
||||
Tag.Named<Item> tagItemLog = getItemTag(TAG_LOGS);
|
||||
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_STRIPPED_LOG, (complexMaterial, settings) -> {
|
||||
return new BaseRotatedPillarBlock(settings);
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_STRIPPED_BARK, (complexMaterial, settings) -> {
|
||||
return new BaseBarkBlock(settings);
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_LOG, (complexMaterial, settings) -> {
|
||||
return new BaseStripableLogBlock(woodColor, getBlock(BLOCK_STRIPPED_LOG));
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
addBlockEntry(
|
||||
new BlockEntry(BLOCK_BARK, (complexMaterial, settings) -> {
|
||||
return new StripableBarkBlock(woodColor, getBlock(BLOCK_STRIPPED_BARK));
|
||||
})
|
||||
.setBlockTags(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN, tagBlockLog)
|
||||
.setItemTags(ItemTags.LOGS, ItemTags.LOGS_THAT_BURN, tagItemLog)
|
||||
);
|
||||
addBlockEntry(new BlockEntry(BLOCK_PLANKS, (complexMaterial, settings) -> {
|
||||
return new BaseBlock(settings);
|
||||
}).setBlockTags(BlockTags.PLANKS)
|
||||
.setItemTags(ItemTags.PLANKS));
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_STAIRS, (complexMaterial, settings) -> {
|
||||
return new BaseStairsBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.WOODEN_STAIRS, BlockTags.STAIRS)
|
||||
.setItemTags(ItemTags.WOODEN_STAIRS, ItemTags.STAIRS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_SLAB, (complexMaterial, settings) -> {
|
||||
return new BaseSlabBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.WOODEN_SLABS, BlockTags.SLABS)
|
||||
.setItemTags(ItemTags.WOODEN_SLABS, ItemTags.SLABS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_FENCE, (complexMaterial, settings) -> {
|
||||
return new BaseFenceBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.FENCES, BlockTags.WOODEN_FENCES)
|
||||
.setItemTags(ItemTags.FENCES, ItemTags.WOODEN_FENCES));
|
||||
addBlockEntry(new BlockEntry(BLOCK_GATE, (complexMaterial, settings) -> {
|
||||
return new BaseGateBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.FENCE_GATES));
|
||||
addBlockEntry(new BlockEntry(BLOCK_BUTTON, (complexMaterial, settings) -> {
|
||||
return new BaseWoodenButtonBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.BUTTONS, BlockTags.WOODEN_BUTTONS)
|
||||
.setItemTags(ItemTags.BUTTONS, ItemTags.WOODEN_BUTTONS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_PRESSURE_PLATE, (complexMaterial, settings) -> {
|
||||
return new WoodenPressurePlateBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.PRESSURE_PLATES, BlockTags.WOODEN_PRESSURE_PLATES)
|
||||
.setItemTags(ItemTags.WOODEN_PRESSURE_PLATES));
|
||||
addBlockEntry(new BlockEntry(BLOCK_TRAPDOOR, (complexMaterial, settings) -> {
|
||||
return new BaseTrapdoorBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.TRAPDOORS, BlockTags.WOODEN_TRAPDOORS)
|
||||
.setItemTags(ItemTags.TRAPDOORS, ItemTags.WOODEN_TRAPDOORS));
|
||||
addBlockEntry(new BlockEntry(BLOCK_DOOR, (complexMaterial, settings) -> {
|
||||
return new BaseDoorBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.DOORS, BlockTags.WOODEN_DOORS)
|
||||
.setItemTags(ItemTags.DOORS, ItemTags.WOODEN_DOORS));
|
||||
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_LADDER, (complexMaterial, settings) -> {
|
||||
return new BaseLadderBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.CLIMBABLE));
|
||||
addBlockEntry(new BlockEntry(BLOCK_SIGN, (complexMaterial, settings) -> {
|
||||
return new BaseSignBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(BlockTags.SIGNS)
|
||||
.setItemTags(ItemTags.SIGNS));
|
||||
|
||||
|
||||
}
|
||||
|
||||
final protected void initStorage(FabricBlockSettings blockSettings, FabricItemSettings itemSettings) {
|
||||
addBlockEntry(new BlockEntry(BLOCK_CHEST, (complexMaterial, settings) -> {
|
||||
return new BaseChestBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(TagAPI.BLOCK_CHEST, TagAPI.BLOCK_WOODEN_CHEST)
|
||||
.setItemTags(TagAPI.ITEM_CHEST, TagAPI.ITEM_WOODEN_CHEST));
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_BARREL, (complexMaterial, settings) -> {
|
||||
return new BaseBarrelBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(TagAPI.BLOCK_BARREL, TagAPI.BLOCK_WOODEN_BARREL)
|
||||
.setItemTags(TagAPI.ITEM_BARREL, TagAPI.ITEM_WOODEN_BARREL));
|
||||
}
|
||||
|
||||
final protected void initDecorations(FabricBlockSettings blockSettings, FabricItemSettings itemSettings) {
|
||||
addBlockEntry(new BlockEntry(BLOCK_CRAFTING_TABLE, (complexMaterial, settings) -> {
|
||||
return new BaseCraftingTableBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(TagAPI.BLOCK_WORKBENCHES)
|
||||
.setItemTags(TagAPI.ITEM_WORKBENCHES));
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_BOOKSHELF, (complexMaterial, settings) -> {
|
||||
return new BaseBookshelfBlock(getBlock(BLOCK_PLANKS));
|
||||
}).setBlockTags(TagAPI.BLOCK_BOOKSHELVES));
|
||||
|
||||
addBlockEntry(new BlockEntry(BLOCK_COMPOSTER, (complexMaterial, settings) -> {
|
||||
return new BaseComposterBlock(getBlock(BLOCK_PLANKS));
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initFlammable(FlammableBlockRegistry registry) {
|
||||
getBlocks().forEach(block -> {
|
||||
registry.add(block, 5, 20);
|
||||
});
|
||||
|
||||
registry.add(getBlock(BLOCK_LOG), 5, 5);
|
||||
registry.add(getBlock(BLOCK_BARK), 5, 5);
|
||||
registry.add(getBlock(BLOCK_STRIPPED_LOG), 5, 5);
|
||||
registry.add(getBlock(BLOCK_STRIPPED_BARK), 5, 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initDefaultRecipes() {
|
||||
Block planks = getBlock(BLOCK_PLANKS);
|
||||
addRecipeEntry(new RecipeEntry("planks", (material, config, id) -> {
|
||||
Block log_stripped = getBlock(BLOCK_STRIPPED_LOG);
|
||||
Block bark_stripped = getBlock(BLOCK_STRIPPED_BARK);
|
||||
Block log = getBlock(BLOCK_LOG);
|
||||
Block bark = getBlock(BLOCK_BARK);
|
||||
GridRecipe.make(id, planks)
|
||||
.checkConfig(config)
|
||||
.setOutputCount(4)
|
||||
.setList("#")
|
||||
.addMaterial('#', log, bark, log_stripped, bark_stripped)
|
||||
.setGroup(receipGroupPrefix + "_planks")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("stairs", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_STAIRS))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(4)
|
||||
.setShape("# ", "## ", "###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_planks_stairs")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("slab", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_SLAB))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(6)
|
||||
.setShape("###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_planks_slabs")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("fence", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_FENCE))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("#I#", "#I#")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix + "_planks_fences")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("gate", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_GATE))
|
||||
.checkConfig(config)
|
||||
.setShape("I#I", "I#I")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix + "_planks_gates")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("button", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BUTTON))
|
||||
.checkConfig(config)
|
||||
.setList("#")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_planks_buttons")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("pressure_plate", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_PRESSURE_PLATE))
|
||||
.checkConfig(config)
|
||||
.setShape("##")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_planks_plates")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("trapdoor", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_TRAPDOOR))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(2)
|
||||
.setShape("###", "###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_trapdoors")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("door", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_DOOR))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("##", "##", "##")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_doors")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("crafting_table", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_CRAFTING_TABLE))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_tables")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("ladder", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_LADDER))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("I I", "I#I", "I I")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix + "_ladders")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("sign", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_SIGN))
|
||||
.checkConfig(config)
|
||||
.setOutputCount(3)
|
||||
.setShape("###", "###", " I ")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('I', Items.STICK)
|
||||
.setGroup(receipGroupPrefix + "_signs")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("chest", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_CHEST))
|
||||
.checkConfig(config)
|
||||
.setShape("###", "# #", "###")
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_chests")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("barrel", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BARREL))
|
||||
.checkConfig(config)
|
||||
.setShape("#S#", "# #", "#S#")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('S', getBlock(BLOCK_SLAB))
|
||||
.setGroup(receipGroupPrefix + "_barrels")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("bookshelf", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BOOKSHELF))
|
||||
.checkConfig(config)
|
||||
.setShape("###", "PPP", "###")
|
||||
.addMaterial('#', planks)
|
||||
.addMaterial('P', Items.BOOK)
|
||||
.setGroup(receipGroupPrefix + "_bookshelves")
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("bark", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_BARK))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_LOG))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("log", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_LOG))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_BARK))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("stripped_bark", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_STRIPPED_BARK))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_STRIPPED_LOG))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("stripped_log", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_STRIPPED_LOG))
|
||||
.checkConfig(config)
|
||||
.setShape("##", "##")
|
||||
.addMaterial('#', getBlock(BLOCK_STRIPPED_BARK))
|
||||
.setOutputCount(3)
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("composter", (material, config, id) -> {
|
||||
GridRecipe.make(id, getBlock(BLOCK_COMPOSTER))
|
||||
.checkConfig(config)
|
||||
.setShape("# #", "# #", "###")
|
||||
.addMaterial('#', getBlock(BLOCK_SLAB))
|
||||
.build();
|
||||
}));
|
||||
addRecipeEntry(new RecipeEntry("shulker", (material, config, id) -> {
|
||||
GridRecipe.make(id, Blocks.SHULKER_BOX)
|
||||
.checkConfig(config)
|
||||
.setShape("S", "#", "S")
|
||||
.addMaterial('S', Items.SHULKER_SHELL)
|
||||
.addMaterial('#', getBlock(BLOCK_CHEST))
|
||||
.build();
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ package ru.bclib.complexmaterials.entry;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import ru.bclib.complexmaterials.ComplexMaterial;
|
||||
import ru.bclib.config.PathConfig;
|
||||
import ru.bclib.util.TriConsumer;
|
||||
import ru.bclib.interfaces.TriConsumer;
|
||||
|
||||
public class RecipeEntry extends ComplexMaterialEntry {
|
||||
final TriConsumer<ComplexMaterial, PathConfig, ResourceLocation> initFunction;
|
||||
|
|
|
@ -12,7 +12,7 @@ public class Configs {
|
|||
public static final ServerConfig SERVER_CONFIG = new ServerConfig();
|
||||
|
||||
|
||||
public static final PathConfig GENERATOR_CONFIG = new PathConfig(BCLib.MOD_ID, "generator");
|
||||
public static final PathConfig GENERATOR_CONFIG = new PathConfig(BCLib.MOD_ID, "generator", false);
|
||||
public static final PathConfig MAIN_CONFIG = new PathConfig(BCLib.MOD_ID, "main", true, true);
|
||||
public static final String MAIN_PATCH_CATEGORY = "patches";
|
||||
|
||||
|
@ -23,5 +23,6 @@ public class Configs {
|
|||
public static void save() {
|
||||
MAIN_CONFIG.saveChanges();
|
||||
RECIPE_CONFIG.saveChanges();
|
||||
GENERATOR_CONFIG.saveChanges();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,11 @@ public class ServerConfig extends NamedPathConfig {
|
|||
public static final DependendConfigToken<Boolean> OFFER_FILES = DependendConfigToken.Boolean(true, "offerFiles", AutoSync.SYNC_CATEGORY, (config) -> config.get(ENABLED));
|
||||
public static final DependendConfigToken<Boolean> OFFER_MODS = DependendConfigToken.Boolean(true, "offerMods", AutoSync.SYNC_CATEGORY, (config) -> config.get(ENABLED));
|
||||
public static final DependendConfigToken<Boolean> OFFER_ALL_MODS = DependendConfigToken.Boolean(false, "offerAllMods", AutoSync.SYNC_CATEGORY, (config) -> config.get(OFFER_MODS));
|
||||
public static final DependendConfigToken<Boolean> SEND_ALL_MOD_INFO = DependendConfigToken.Boolean(true, "sendAllModInfo", AutoSync.SYNC_CATEGORY, (config) -> config.get(ENABLED));
|
||||
public static final DependendConfigToken<Boolean> SEND_ALL_MOD_INFO = DependendConfigToken.Boolean(false, "sendAllModInfo", AutoSync.SYNC_CATEGORY, (config) -> config.get(ENABLED));
|
||||
|
||||
|
||||
public static final ConfigToken<List<String>> ADDITIONAL_MODS = ConfigToken.StringArray(new ArrayList<>(0), "additionalMods", AutoSync.SYNC_CATEGORY);
|
||||
public static final ConfigToken<List<String>> EXCLUDED_MODS = ConfigToken.StringArray(new ArrayList<>(0), "excludeMods", AutoSync.SYNC_CATEGORY);
|
||||
|
||||
|
||||
public ServerConfig() {
|
||||
|
@ -45,8 +46,5 @@ public class ServerConfig extends NamedPathConfig {
|
|||
public boolean isOfferingInfosForMods() {
|
||||
return get(SEND_ALL_MOD_INFO) /*&& isAllowingAutoSync()*/;
|
||||
}
|
||||
|
||||
public String[] additionalModsForSync() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package ru.bclib.gui.gridlayout;
|
|||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import ru.bclib.util.TriConsumer;
|
||||
import ru.bclib.interfaces.TriConsumer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
|
|
@ -5,8 +5,8 @@ import net.fabricmc.api.EnvType;
|
|||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import ru.bclib.gui.gridlayout.GridLayout.GridValueType;
|
||||
import ru.bclib.interfaces.TriConsumer;
|
||||
import ru.bclib.util.Pair;
|
||||
import ru.bclib.util.TriConsumer;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -88,6 +88,7 @@ public class GridLayout extends GridColumn {
|
|||
public static final int COLOR_RED = 0xFFDB1F48;
|
||||
public static final int COLOR_CYAN = 0xFF01949A;
|
||||
public static final int COLOR_GREEN = 0xFF00FF00;
|
||||
public static final int COLOR_DARK_GREEN = 0xFF007F00;
|
||||
public static final int COLOR_YELLOW = 0xFFFAD02C;
|
||||
public static final int COLOR_BLUE = 0xFF0000FF;
|
||||
public static final int COLOR_GRAY = 0xFF7F7F7F;
|
||||
|
|
|
@ -9,8 +9,6 @@ import com.mojang.blaze3d.vertex.VertexFormat;
|
|||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.components.AbstractSelectionList;
|
||||
import net.minecraft.client.gui.components.OptionsList;
|
||||
import net.minecraft.client.gui.components.Widget;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ru.bclib.gui.screens;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
|
|
60
src/main/java/ru/bclib/gui/screens/LevelFixErrorScreen.java
Normal file
60
src/main/java/ru/bclib/gui/screens/LevelFixErrorScreen.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
package ru.bclib.gui.screens;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.CommonComponents;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import ru.bclib.gui.gridlayout.GridColumn;
|
||||
import ru.bclib.gui.gridlayout.GridLayout;
|
||||
import ru.bclib.gui.gridlayout.GridRow;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class LevelFixErrorScreen extends BCLibScreen {
|
||||
private final String[] errors;
|
||||
final Listener onContinue;
|
||||
|
||||
public LevelFixErrorScreen(Screen parent, String[] errors, Listener onContinue) {
|
||||
super(parent, new TranslatableComponent("title.bclib.datafixer.error"), 10, true);
|
||||
this.errors = errors;
|
||||
this.onContinue = onContinue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initLayout() {
|
||||
grid.addSpacerRow();
|
||||
grid.addRow().addMessage(new TranslatableComponent("message.bclib.datafixer.error"), font, GridLayout.Alignment.CENTER);
|
||||
grid.addSpacerRow(8);
|
||||
|
||||
GridRow row = grid.addRow();
|
||||
row.addSpacer(10);
|
||||
GridColumn col = row.addColumn(300, GridLayout.GridValueType.CONSTANT);
|
||||
for (String error : errors){
|
||||
TextComponent dash = new TextComponent("-");
|
||||
row = col.addRow();
|
||||
row.addString(dash, this);
|
||||
|
||||
row.addSpacer(4);
|
||||
row.addString(new TextComponent(error), this);
|
||||
}
|
||||
|
||||
grid.addSpacerRow(8);
|
||||
row = grid.addRow();
|
||||
row.addFiller();
|
||||
row.addButton(new TranslatableComponent("title.bclib.datafixer.error.continue"), 0.5f, 20, font, (n)-> {
|
||||
onClose();
|
||||
onContinue.doContinue(true);
|
||||
});
|
||||
row.addSpacer();
|
||||
row.addButton(CommonComponents.GUI_CANCEL, 20, font, (n)-> {
|
||||
this.minecraft.setScreen(null);
|
||||
});
|
||||
row.addFiller();
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface Listener {
|
||||
void doContinue(boolean markFixed);
|
||||
}
|
||||
}
|
|
@ -73,13 +73,14 @@ public class ModListScreen extends BCLibScreen {
|
|||
|
||||
|
||||
public static void addModDesc(GridColumn grid, java.util.List<ModUtil.ModInfo> mods, HelloClient.IServerModMap serverInfo, GridScreen parent) {
|
||||
final int STATE_OK = 0;
|
||||
final int STATE_MISSING = 1;
|
||||
final int STATE_SERVER_MISSING = 2;
|
||||
final int STATE_VERSION = 3;
|
||||
final int STATE_SERVER_MISSING_CLIENT_MOD = 4;
|
||||
final int STATE_VERSION_NOT_OFFERED = 5;
|
||||
final int STATE_MISSING_NOT_OFFERED = 6;
|
||||
final int STATE_OK = 6;
|
||||
final int STATE_SERVER_MISSING_CLIENT_MOD = 5;
|
||||
final int STATE_MISSING_NOT_OFFERED = 4;
|
||||
final int STATE_VERSION_NOT_OFFERED = 3;
|
||||
final int STATE_VERSION = 2;
|
||||
final int STATE_SERVER_MISSING = 1;
|
||||
final int STATE_MISSING = 0;
|
||||
|
||||
|
||||
List<Triple<String, Integer, String>> items = new LinkedList<>();
|
||||
if (serverInfo!=null) {
|
||||
|
@ -141,7 +142,7 @@ public class ModListScreen extends BCLibScreen {
|
|||
});
|
||||
|
||||
items.stream()
|
||||
.sorted(Comparator.comparing(a -> a.first.toLowerCase(Locale.ROOT)))
|
||||
.sorted(Comparator.comparing(a -> a.second + a.first.toLowerCase(Locale.ROOT)))
|
||||
.forEach(t -> {
|
||||
final String name = t.first;
|
||||
final int state = t.second;
|
||||
|
@ -160,12 +161,14 @@ public class ModListScreen extends BCLibScreen {
|
|||
color = GridLayout.COLOR_YELLOW;
|
||||
}
|
||||
} else if (state==STATE_SERVER_MISSING || state == STATE_SERVER_MISSING_CLIENT_MOD) {
|
||||
typeText = "[NOT ON SERVER]";
|
||||
if (state == STATE_SERVER_MISSING_CLIENT_MOD) {
|
||||
color = GridLayout.COLOR_YELLOW;
|
||||
color = GridLayout.COLOR_CYAN;
|
||||
typeText = "[OK]";
|
||||
} else {
|
||||
typeText = "[NOT ON SERVER]";
|
||||
}
|
||||
} else {
|
||||
color = GridLayout.COLOR_CYAN;
|
||||
color = GridLayout.COLOR_DARK_GREEN;
|
||||
typeText = "[OK]";
|
||||
}
|
||||
TextComponent dash = new TextComponent("-");
|
||||
|
@ -208,7 +211,6 @@ public class ModListScreen extends BCLibScreen {
|
|||
row.addFiller();
|
||||
row.addButton(buttonTitle, 20, font, (n)-> {
|
||||
onClose();
|
||||
System.out.println("Closing");
|
||||
});
|
||||
row.addFiller();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import net.minecraft.network.chat.Component;
|
|||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import ru.bclib.gui.gridlayout.GridLayout.Alignment;
|
||||
import ru.bclib.gui.gridlayout.GridRow;
|
||||
import ru.bclib.gui.gridlayout.GridScreen;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class WarnBCLibVersionMismatch extends BCLibScreen {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package ru.bclib.interfaces;
|
||||
|
||||
|
||||
import ru.bclib.recipes.AnvilRecipe;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AnvilScreenHandlerExtended {
|
||||
void be_updateCurrentRecipe(AnvilRecipe recipe);
|
||||
|
||||
AnvilRecipe be_getCurrentRecipe();
|
||||
|
||||
List<AnvilRecipe> be_getRecipes();
|
||||
|
||||
default void be_nextRecipe() {
|
||||
List<AnvilRecipe> recipes = be_getRecipes();
|
||||
if (recipes.size() < 2) return;
|
||||
AnvilRecipe current = be_getCurrentRecipe();
|
||||
int i = recipes.indexOf(current) + 1;
|
||||
if (i >= recipes.size()) {
|
||||
i = 0;
|
||||
}
|
||||
be_updateCurrentRecipe(recipes.get(i));
|
||||
}
|
||||
|
||||
default void be_previousRecipe() {
|
||||
List<AnvilRecipe> recipes = be_getRecipes();
|
||||
if (recipes.size() < 2) return;
|
||||
AnvilRecipe current = be_getCurrentRecipe();
|
||||
int i = recipes.indexOf(current) - 1;
|
||||
if (i <= 0) {
|
||||
i = recipes.size() - 1;
|
||||
}
|
||||
be_updateCurrentRecipe(recipes.get(i));
|
||||
}
|
||||
}
|
8
src/main/java/ru/bclib/interfaces/BiomeSetter.java
Normal file
8
src/main/java/ru/bclib/interfaces/BiomeSetter.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package ru.bclib.interfaces;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
public interface BiomeSetter {
|
||||
public void bclib_setBiome(Biome biome, BlockPos pos);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package ru.bclib.util;
|
||||
package ru.bclib.interfaces;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TriConsumer<A, B, C> {
|
|
@ -0,0 +1,4 @@
|
|||
package ru.bclib.interfaces;
|
||||
|
||||
public interface UnknownReceipBookCategory {
|
||||
}
|
21
src/main/java/ru/bclib/items/tool/BaseShearsItem.java
Normal file
21
src/main/java/ru/bclib/items/tool/BaseShearsItem.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package ru.bclib.items.tool;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.ShearsItem;
|
||||
import ru.bclib.api.TagAPI;
|
||||
|
||||
public class BaseShearsItem extends ShearsItem {
|
||||
public BaseShearsItem(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
public static boolean isShear(ItemStack itemStack, Item item){
|
||||
if (item == Items.SHEARS){
|
||||
return itemStack.is(item) | itemStack.is(TagAPI.ITEM_COMMON_SHEARS) || itemStack.is(TagAPI.ITEM_SHEARS);
|
||||
} else {
|
||||
return itemStack.is(item);
|
||||
}
|
||||
}
|
||||
}
|
95
src/main/java/ru/bclib/mixin/client/AnvilScreenMixin.java
Normal file
95
src/main/java/ru/bclib/mixin/client/AnvilScreenMixin.java
Normal file
|
@ -0,0 +1,95 @@
|
|||
package ru.bclib.mixin.client;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.screens.inventory.AnvilScreen;
|
||||
import net.minecraft.client.gui.screens.inventory.ItemCombinerScreen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.AnvilMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import ru.bclib.interfaces.AnvilScreenHandlerExtended;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(AnvilScreen.class)
|
||||
public class AnvilScreenMixin extends ItemCombinerScreen<AnvilMenu> {
|
||||
|
||||
@Shadow
|
||||
private EditBox name;
|
||||
|
||||
private final List<AbstractWidget> be_buttons = Lists.newArrayList();
|
||||
|
||||
public AnvilScreenMixin(AnvilMenu handler, Inventory playerInventory, Component title, ResourceLocation texture) {
|
||||
super(handler, playerInventory, title, texture);
|
||||
}
|
||||
|
||||
@Inject(method = "subInit", at = @At("TAIL"))
|
||||
protected void be_subInit(CallbackInfo info) {
|
||||
int x = (width - imageWidth) / 2;
|
||||
int y = (height - imageHeight) / 2;
|
||||
be_buttons.clear();
|
||||
be_buttons.add(new Button(x + 8, y + 45, 15, 20, new TextComponent("<"), b -> be_previousRecipe()));
|
||||
be_buttons.add(new Button(x + 154, y + 45, 15, 20, new TextComponent(">"), b -> be_nextRecipe()));
|
||||
}
|
||||
|
||||
@Inject(method = "renderFg", at = @At("TAIL"))
|
||||
protected void be_renderForeground(PoseStack matrices, int mouseX, int mouseY, float delta, CallbackInfo info) {
|
||||
be_buttons.forEach(button -> {
|
||||
button.render(matrices, mouseX, mouseY, delta);
|
||||
});
|
||||
}
|
||||
|
||||
@Inject(method = "slotChanged", at = @At("HEAD"), cancellable = true)
|
||||
public void be_onSlotUpdate(AbstractContainerMenu handler, int slotId, ItemStack stack, CallbackInfo info) {
|
||||
AnvilScreenHandlerExtended anvilHandler = (AnvilScreenHandlerExtended) handler;
|
||||
if (anvilHandler.be_getCurrentRecipe() != null) {
|
||||
if (anvilHandler.be_getRecipes().size() > 1) {
|
||||
be_buttons.forEach(button -> button.visible = true);
|
||||
}
|
||||
else {
|
||||
be_buttons.forEach(button -> button.visible = false);
|
||||
}
|
||||
name.setValue("");
|
||||
info.cancel();
|
||||
}
|
||||
else {
|
||||
be_buttons.forEach(button -> button.visible = false);
|
||||
}
|
||||
}
|
||||
|
||||
private void be_nextRecipe() {
|
||||
((AnvilScreenHandlerExtended) menu).be_nextRecipe();
|
||||
}
|
||||
|
||||
private void be_previousRecipe() {
|
||||
((AnvilScreenHandlerExtended) menu).be_previousRecipe();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (minecraft != null) {
|
||||
for (AbstractWidget elem : be_buttons) {
|
||||
if (elem.visible && elem.mouseClicked(mouseX, mouseY, button)) {
|
||||
if (minecraft.gameMode != null) {
|
||||
int i = be_buttons.indexOf(elem);
|
||||
minecraft.gameMode.handleInventoryButtonClick(menu.containerId, i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ public class BackgroundRendererMixin {
|
|||
private static final MutableBlockPos BCLIB_LAST_POS = new MutableBlockPos(0, -100, 0);
|
||||
private static final MutableBlockPos BCLIB_MUT_POS = new MutableBlockPos();
|
||||
private static final float[] BCLIB_FOG_DENSITY = new float[8];
|
||||
//private static boolean isEnd;
|
||||
|
||||
@Shadow
|
||||
private static float fogRed;
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
package ru.bclib.mixin.client;public class ClientLevelMixin {
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package ru.bclib.mixin.client;
|
||||
|
||||
import net.minecraft.client.ClientRecipeBook;
|
||||
import net.minecraft.client.RecipeBookCategories;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
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 ru.bclib.interfaces.UnknownReceipBookCategory;
|
||||
|
||||
@Mixin(ClientRecipeBook.class)
|
||||
public abstract class ClientRecipeBookMixin {
|
||||
@Inject(method = "getCategory", at = @At("HEAD"), cancellable = true)
|
||||
private static void be_getGroupForRecipe(Recipe<?> recipe, CallbackInfoReturnable<RecipeBookCategories> info) {
|
||||
if (recipe instanceof UnknownReceipBookCategory) {
|
||||
info.setReturnValue(RecipeBookCategories.UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package ru.bclib.mixin.client;
|
||||
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
|
||||
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.CallbackInfo;
|
||||
|
||||
@Mixin(ClientboundLoginPacket.class)
|
||||
public abstract class ClientboundLoginPacketMixin {
|
||||
@Inject(method = "handle", cancellable = true, at=@At("HEAD"))
|
||||
public void bclib_handle(ClientGamePacketListener clientGamePacketListener, CallbackInfo ci){
|
||||
//cLevel.setBCLibDidSendHello();
|
||||
// DataExchangeAPI.sendOnEnter();
|
||||
// ci.cancel();
|
||||
}
|
||||
}
|
|
@ -100,8 +100,7 @@ public abstract class MinecraftMixin {
|
|||
DataExchangeAPI.prepareServerside();
|
||||
|
||||
if (DataFixerAPI.fixData(this.levelSource, levelID, true, (appliedFixes) -> {
|
||||
bclib_doLoadLevel_BACKUP(levelID, RegistryAccess.builtin(), Minecraft::loadDataPacks, Minecraft::loadWorldData, false);
|
||||
//this.doLoadLevel(levelID, RegistryAccess.builtin(), Minecraft::loadDataPacks, Minecraft::loadWorldData, false, Minecraft.ExperimentalDialogType.BACKUP);
|
||||
this.doLoadLevel(levelID, RegistryAccess.builtin(), Minecraft::loadDataPacks, Minecraft::loadWorldData, false, appliedFixes?ExperimentalDialogType.NONE:ExperimentalDialogType.BACKUP);
|
||||
})) {
|
||||
ci.cancel();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import net.minecraft.world.inventory.DataSlot;
|
|||
import net.minecraft.world.inventory.ItemCombinerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
|
@ -17,10 +19,22 @@ import org.spongepowered.asm.mixin.Shadow;
|
|||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import ru.bclib.blocks.BaseAnvilBlock;
|
||||
import ru.bclib.blocks.LeveledAnvilBlock;
|
||||
import ru.bclib.interfaces.AnvilScreenHandlerExtended;
|
||||
import ru.bclib.recipes.AnvilRecipe;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(AnvilMenu.class)
|
||||
public abstract class AnvilMenuMixin extends ItemCombinerMenu {
|
||||
public abstract class AnvilMenuMixin extends ItemCombinerMenu implements AnvilScreenHandlerExtended {
|
||||
private List<AnvilRecipe> be_recipes = Collections.emptyList();
|
||||
private AnvilRecipe be_currentRecipe;
|
||||
private DataSlot anvilLevel;
|
||||
|
||||
@Shadow
|
||||
private int repairItemCountCost;
|
||||
|
||||
|
@ -31,9 +45,64 @@ public abstract class AnvilMenuMixin extends ItemCombinerMenu {
|
|||
public AnvilMenuMixin(@Nullable MenuType<?> menuType, int i, Inventory inventory, ContainerLevelAccess containerLevelAccess) {
|
||||
super(menuType, i, inventory, containerLevelAccess);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/inventory/ContainerLevelAccess;)V", at = @At("TAIL"))
|
||||
public void be_initAnvilLevel(int syncId, Inventory inventory, ContainerLevelAccess context, CallbackInfo info) {
|
||||
this.anvilLevel = addDataSlot(DataSlot.standalone());
|
||||
if (context != ContainerLevelAccess.NULL) {
|
||||
int level = context.evaluate((world, blockPos) -> {
|
||||
Block anvilBlock = world.getBlockState(blockPos).getBlock();
|
||||
if (anvilBlock instanceof LeveledAnvilBlock) {
|
||||
return ((LeveledAnvilBlock) anvilBlock).getCraftingLevel();
|
||||
}
|
||||
return 1;
|
||||
}, 1);
|
||||
anvilLevel.set(level);
|
||||
}
|
||||
else {
|
||||
anvilLevel.set(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public abstract void createResult();
|
||||
|
||||
@Inject(method = "mayPickup", at = @At("HEAD"), cancellable = true)
|
||||
protected void be_canTakeOutput(Player player, boolean present, CallbackInfoReturnable<Boolean> info) {
|
||||
if (be_currentRecipe != null) {
|
||||
info.setReturnValue(be_currentRecipe.checkHammerDurability(inputSlots, player));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onTake", at = @At("HEAD"), cancellable = true)
|
||||
protected void bclib_onTakeAnvilOutput(Player player, ItemStack stack, CallbackInfo info) {
|
||||
if (be_currentRecipe != null) {
|
||||
inputSlots.getItem(0).shrink(be_currentRecipe.getInputCount());
|
||||
stack = be_currentRecipe.craft(inputSlots, player);
|
||||
slotsChanged(inputSlots);
|
||||
access.execute((world, blockPos) -> {
|
||||
final BlockState anvilState = world.getBlockState(blockPos);
|
||||
final Block anvilBlock = anvilState.getBlock();
|
||||
if (anvilBlock instanceof BaseAnvilBlock) {
|
||||
final BaseAnvilBlock anvil = (BaseAnvilBlock) anvilBlock;
|
||||
if (!player.getAbilities().instabuild && anvilState.is(BlockTags.ANVIL) && player.getRandom().nextDouble() < 0.1) {
|
||||
BlockState damagedState = anvil.damageAnvilUse(anvilState, player.getRandom());
|
||||
if (damagedState == null) {
|
||||
world.removeBlock(blockPos, false);
|
||||
world.levelEvent(1029, blockPos, 0);
|
||||
} else {
|
||||
world.setBlock(blockPos, damagedState, 2);
|
||||
world.levelEvent(1030, blockPos, 0);
|
||||
}
|
||||
} else {
|
||||
world.levelEvent(1030, blockPos, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
this.access.execute((level, blockPos) -> {
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (blockState.getBlock() instanceof BaseAnvilBlock) {
|
||||
|
@ -77,4 +146,68 @@ public abstract class AnvilMenuMixin extends ItemCombinerMenu {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Inject(method = "createResult", at = @At("HEAD"), cancellable = true)
|
||||
public void be_updateOutput(CallbackInfo info) {
|
||||
RecipeManager recipeManager = this.player.level.getRecipeManager();
|
||||
be_recipes = recipeManager.getRecipesFor(AnvilRecipe.TYPE, inputSlots, player.level);
|
||||
if (be_recipes.size() > 0) {
|
||||
int anvilLevel = this.anvilLevel.get();
|
||||
be_recipes = be_recipes.stream()
|
||||
.filter(recipe -> anvilLevel >= recipe.getAnvilLevel())
|
||||
.collect(Collectors.toList());
|
||||
if (be_recipes.size() > 0) {
|
||||
if (be_currentRecipe == null || !be_recipes.contains(be_currentRecipe)) {
|
||||
be_currentRecipe = be_recipes.get(0);
|
||||
}
|
||||
be_updateResult();
|
||||
info.cancel();
|
||||
}
|
||||
else {
|
||||
be_currentRecipe = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "setItemName", at = @At("HEAD"), cancellable = true)
|
||||
public void be_setNewItemName(String string, CallbackInfo info) {
|
||||
if (be_currentRecipe != null) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clickMenuButton(Player player, int id) {
|
||||
if (id == 0) {
|
||||
be_previousRecipe();
|
||||
return true;
|
||||
}
|
||||
else if (id == 1) {
|
||||
be_nextRecipe();
|
||||
return true;
|
||||
}
|
||||
return super.clickMenuButton(player, id);
|
||||
}
|
||||
|
||||
private void be_updateResult() {
|
||||
if (be_currentRecipe == null) return;
|
||||
resultSlots.setItem(0, be_currentRecipe.assemble(inputSlots));
|
||||
broadcastChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void be_updateCurrentRecipe(AnvilRecipe recipe) {
|
||||
this.be_currentRecipe = recipe;
|
||||
be_updateResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnvilRecipe be_getCurrentRecipe() {
|
||||
return be_currentRecipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnvilRecipe> be_getRecipes() {
|
||||
return be_recipes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
package ru.bclib.mixin.common;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.BitStorage;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import ru.bclib.BCLib;
|
||||
import ru.bclib.interfaces.BiomeSetter;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@Mixin(ChunkBiomeContainer.class)
|
||||
public class ChunkBiomeContainerMixin implements BiomeSetter {
|
||||
private static boolean bclib_hasHydrogen = FabricLoader.getInstance().isModLoaded("hydrogen");
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private Biome[] biomes;
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private static int WIDTH_BITS;
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private static int HORIZONTAL_MASK;
|
||||
|
||||
@Override
|
||||
public void bclib_setBiome(Biome biome, BlockPos pos) {
|
||||
int biomeX = pos.getX() >> 2;
|
||||
int biomeY = pos.getY() >> 2;
|
||||
int biomeZ = pos.getZ() >> 2;
|
||||
int index = be_getArrayIndex(biomeX, biomeY, biomeZ);
|
||||
|
||||
if (bclib_hasHydrogen && be_shouldWriteToHydrogen()) {
|
||||
try {
|
||||
ChunkBiomeContainer self = (ChunkBiomeContainer) (Object) this;
|
||||
BitStorage storage = be_getHydrogenStorage(self);
|
||||
Biome[] palette = be_getHydrogenPalette(self);
|
||||
int paletteIndex = be_getHydrogenPaletteIndex(biome, palette);
|
||||
if (paletteIndex == -1) {
|
||||
Biome[] newPalette = new Biome[palette.length + 1];
|
||||
System.arraycopy(palette, 0, newPalette, 0, palette.length);
|
||||
paletteIndex = palette.length;
|
||||
palette = newPalette;
|
||||
palette[paletteIndex] = biome;
|
||||
be_setHydrogenPalette(self, palette);
|
||||
}
|
||||
try {
|
||||
storage.set(index, paletteIndex);
|
||||
}
|
||||
catch (Exception e) {
|
||||
int size = storage.getSize();
|
||||
int bits = Mth.ceillog2(palette.length);
|
||||
BitStorage newStorage = new BitStorage(bits, size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
newStorage.set(i, storage.get(i));
|
||||
}
|
||||
storage = newStorage;
|
||||
storage.set(index, paletteIndex);
|
||||
be_setHydrogenStorage(self, storage);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
BCLib.LOGGER.warning(e.getLocalizedMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
biomes[index] = biome;
|
||||
}
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private int quartMinY;
|
||||
@Shadow
|
||||
@Final
|
||||
private int quartHeight;
|
||||
|
||||
private boolean be_shouldWriteToHydrogen() {
|
||||
try {
|
||||
Field field = ChunkBiomeContainer.class.getDeclaredField("intArray");
|
||||
return field != null;
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int be_getArrayIndex(int biomeX, int biomeY, int biomeZ) {
|
||||
int i = biomeX & HORIZONTAL_MASK;
|
||||
int j = Mth.clamp(biomeY - this.quartMinY, 0, this.quartHeight);
|
||||
int k = biomeZ & HORIZONTAL_MASK;
|
||||
return j << WIDTH_BITS + WIDTH_BITS | k << WIDTH_BITS | i;
|
||||
}
|
||||
|
||||
private Field be_getField(String name) throws Exception {
|
||||
Field field = ChunkBiomeContainer.class.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
|
||||
private BitStorage be_getHydrogenStorage(ChunkBiomeContainer container) throws Exception {
|
||||
return (BitStorage) be_getField("intArray").get(container);
|
||||
}
|
||||
|
||||
private Biome[] be_getHydrogenPalette(ChunkBiomeContainer container) throws Exception {
|
||||
return (Biome[]) be_getField("palette").get(container);
|
||||
}
|
||||
|
||||
private int be_getHydrogenPaletteIndex(Biome biome, Biome[] palette) {
|
||||
int index = -1;
|
||||
for (int i = 0; i < palette.length; i++) {
|
||||
if (palette[i] == biome) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private void be_setHydrogenPalette(ChunkBiomeContainer container, Biome[] palette) throws Exception {
|
||||
be_getField("palette").set(container, palette);
|
||||
}
|
||||
|
||||
private void be_setHydrogenStorage(ChunkBiomeContainer container, BitStorage storage) throws Exception {
|
||||
be_getField("intArray").set(container, storage);
|
||||
}
|
||||
}
|
31
src/main/java/ru/bclib/mixin/common/CraftingMenuMixin.java
Normal file
31
src/main/java/ru/bclib/mixin/common/CraftingMenuMixin.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
package ru.bclib.mixin.common;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.ContainerLevelAccess;
|
||||
import net.minecraft.world.inventory.CraftingMenu;
|
||||
import net.minecraft.world.level.block.CraftingTableBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import ru.bclib.api.TagAPI;
|
||||
|
||||
@Mixin(CraftingMenu.class)
|
||||
public abstract class CraftingMenuMixin {
|
||||
@Final
|
||||
@Shadow
|
||||
private ContainerLevelAccess access;
|
||||
|
||||
@Inject(method = "stillValid", at = @At("HEAD"), cancellable = true)
|
||||
private void bclib_stillValid(Player player, CallbackInfoReturnable<Boolean> info) {
|
||||
if (access.evaluate((world, pos) -> {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
return state.getBlock() instanceof CraftingTableBlock || state.is(TagAPI.BLOCK_WORKBENCHES);
|
||||
}, true)) {
|
||||
info.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,24 +12,29 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import ru.bclib.world.generator.BCLibEndBiomeSource;
|
||||
import ru.bclib.world.generator.BCLibNetherBiomeSource;
|
||||
import ru.bclib.world.generator.GeneratorOptions;
|
||||
|
||||
@Mixin(value = DimensionType.class, priority = 100)
|
||||
public class DimensionTypeMixin {
|
||||
@Inject(method = "defaultNetherGenerator", at = @At("HEAD"), cancellable = true)
|
||||
private static void be_replaceNetherBiomeSource(Registry<Biome> biomeRegistry, Registry<NoiseGeneratorSettings> chunkGeneratorSettingsRegistry, long seed, CallbackInfoReturnable<ChunkGenerator> info) {
|
||||
info.setReturnValue(new NoiseBasedChunkGenerator(
|
||||
new BCLibNetherBiomeSource(biomeRegistry, seed),
|
||||
seed,
|
||||
() -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER)
|
||||
));
|
||||
if (GeneratorOptions.customNetherBiomeSource()) {
|
||||
info.setReturnValue(new NoiseBasedChunkGenerator(
|
||||
new BCLibNetherBiomeSource(biomeRegistry, seed),
|
||||
seed,
|
||||
() -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "defaultEndGenerator", at = @At("HEAD"), cancellable = true)
|
||||
private static void be_replaceEndBiomeSource(Registry<Biome> biomeRegistry, Registry<NoiseGeneratorSettings> chunkGeneratorSettingsRegistry, long seed, CallbackInfoReturnable<ChunkGenerator> info) {
|
||||
info.setReturnValue(new NoiseBasedChunkGenerator(
|
||||
new BCLibEndBiomeSource(biomeRegistry, seed),
|
||||
seed,
|
||||
() -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END)
|
||||
));
|
||||
if (GeneratorOptions.customEndBiomeSource()) {
|
||||
info.setReturnValue(new NoiseBasedChunkGenerator(
|
||||
new BCLibEndBiomeSource(biomeRegistry, seed),
|
||||
seed,
|
||||
() -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package ru.bclib.mixin.common;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.piston.PistonBaseBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
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 ru.bclib.api.TagAPI;
|
||||
|
||||
@Mixin(PistonBaseBlock.class)
|
||||
public class PistonBaseBlockMixin {
|
||||
@Inject(method="isPushable", at=@At("HEAD"), cancellable = true)
|
||||
private static void bclib_isPushable(BlockState blockState, Level level, BlockPos blockPos, Direction direction, boolean bl, Direction direction2, CallbackInfoReturnable<Boolean> cir){
|
||||
if (blockState.is(TagAPI.BLOCK_IMMOBILE)){
|
||||
cir.setReturnValue(false);
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
33
src/main/java/ru/bclib/mixin/common/PortalShapeMixin.java
Normal file
33
src/main/java/ru/bclib/mixin/common/PortalShapeMixin.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
package ru.bclib.mixin.common;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour.StatePredicate;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.portal.PortalShape;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.api.TagAPI;
|
||||
|
||||
@Mixin(PortalShape.class)
|
||||
public class PortalShapeMixin {
|
||||
@Redirect(method="getDistanceUntilEdgeAboveFrame", at=@At(value="INVOKE", target="Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;test(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z"))
|
||||
private boolean be_getDistanceUntilEdgeAboveFrame(StatePredicate statePredicate, BlockState blockState, BlockGetter blockGetter, BlockPos blockPos){
|
||||
return be_FRAME(statePredicate, blockState, blockGetter, blockPos);
|
||||
}
|
||||
|
||||
@Redirect(method="hasTopFrame", at=@At(value="INVOKE", target="Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;test(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z"))
|
||||
private boolean be_hasTopFrame(StatePredicate statePredicate, BlockState blockState, BlockGetter blockGetter, BlockPos blockPos){
|
||||
return be_FRAME(statePredicate, blockState, blockGetter, blockPos);
|
||||
}
|
||||
|
||||
@Redirect(method="getDistanceUntilTop", at=@At(value="INVOKE", target="Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;test(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z"))
|
||||
private boolean be_getDistanceUntilTop(StatePredicate statePredicate, BlockState blockState, BlockGetter blockGetter, BlockPos blockPos){
|
||||
return be_FRAME(statePredicate, blockState, blockGetter, blockPos);
|
||||
}
|
||||
|
||||
private static boolean be_FRAME(StatePredicate FRAME, BlockState state, BlockGetter getter, BlockPos pos){
|
||||
return state.is(TagAPI.BLOCK_NETHER_PORTAL_FRAME) || FRAME.test(state, getter, pos);
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ public abstract class ServerLevelMixin extends Level {
|
|||
@Inject(method = "<init>*", at = @At("TAIL"))
|
||||
private void bclib_onServerWorldInit(MinecraftServer server, Executor workerExecutor, LevelStorageSource.LevelStorageAccess session, ServerLevelData properties, ResourceKey<Level> registryKey, DimensionType dimensionType, ChunkProgressListener worldGenerationProgressListener, ChunkGenerator chunkGenerator, boolean debugWorld, long l, List<CustomSpawner> list, boolean bl, CallbackInfo info) {
|
||||
BiomeAPI.initRegistry(server);
|
||||
BiomeAPI.applyModifications(ServerLevel.class.cast(this));
|
||||
|
||||
if (bclib_lastWorld != null && bclib_lastWorld.equals(session.getLevelId())) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.mixin.common.shears;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.BeehiveBlock;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
@Mixin(BeehiveBlock.class)
|
||||
public class BeehiveBlockMixin {
|
||||
@Redirect(method="use", at=@At(value="INVOKE", target="Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
|
||||
public boolean bn_useProxy(ItemStack itemStack, Item item){
|
||||
return BaseShearsItem.isShear(itemStack, item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.mixin.common.shears;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.DiggingEnchantment;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
@Mixin(DiggingEnchantment.class)
|
||||
public class DiggingEnchantmentMixin {
|
||||
@Redirect(method="canEnchant", at=@At(value="INVOKE", target="Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
|
||||
public boolean bn_mobInteractProxy(ItemStack itemStack, Item item){
|
||||
return BaseShearsItem.isShear(itemStack, item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.mixin.common.shears;
|
||||
|
||||
import net.minecraft.world.entity.animal.MushroomCow;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
@Mixin(MushroomCow.class)
|
||||
public class MushroomCowMixin {
|
||||
@Redirect(method="mobInteract", at=@At(value="INVOKE", target="Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
|
||||
public boolean bn_mobInteractProxy(ItemStack itemStack, Item item){
|
||||
return BaseShearsItem.isShear(itemStack, item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.mixin.common.shears;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.PumpkinBlock;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
@Mixin(PumpkinBlock.class)
|
||||
public abstract class PumpkinBlockMixin {
|
||||
@Redirect(method="use", at=@At(value="INVOKE", target="Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
|
||||
public boolean bn_useProxy(ItemStack itemStack, Item item){
|
||||
return BaseShearsItem.isShear(itemStack, item);
|
||||
}
|
||||
}
|
17
src/main/java/ru/bclib/mixin/common/shears/SheepMixin.java
Normal file
17
src/main/java/ru/bclib/mixin/common/shears/SheepMixin.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.mixin.common.shears;
|
||||
|
||||
import net.minecraft.world.entity.animal.Sheep;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
@Mixin(Sheep.class)
|
||||
public class SheepMixin {
|
||||
@Redirect(method="mobInteract", at=@At(value="INVOKE", target="Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
|
||||
public boolean bn_mobInteractProxy(ItemStack itemStack, Item item){
|
||||
return BaseShearsItem.isShear(itemStack, item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.mixin.common.shears;
|
||||
|
||||
import net.minecraft.world.entity.animal.SnowGolem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
@Mixin(SnowGolem.class)
|
||||
public class SnowGolemMixin {
|
||||
@Redirect(method="mobInteract", at=@At(value="INVOKE", target="Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
|
||||
public boolean bn_mobInteractProxy(ItemStack itemStack, Item item){
|
||||
return BaseShearsItem.isShear(itemStack, item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.mixin.common.shears;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.TripWireBlock;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
@Mixin(TripWireBlock.class)
|
||||
public class TripWireBlockMixin {
|
||||
@Redirect(method="playerWillDestroy", at=@At(value="INVOKE", target="Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
|
||||
public boolean bn_useProxy(ItemStack itemStack, Item item){
|
||||
return BaseShearsItem.isShear(itemStack, item);
|
||||
}
|
||||
}
|
334
src/main/java/ru/bclib/recipes/AnvilRecipe.java
Normal file
334
src/main/java/ru/bclib/recipes/AnvilRecipe.java
Normal file
|
@ -0,0 +1,334 @@
|
|||
package ru.bclib.recipes;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.TagParser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TieredItem;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.Level;
|
||||
import ru.bclib.BCLib;
|
||||
import ru.bclib.api.TagAPI;
|
||||
import ru.bclib.config.PathConfig;
|
||||
import ru.bclib.interfaces.UnknownReceipBookCategory;
|
||||
import ru.bclib.util.ItemUtil;
|
||||
import ru.bclib.util.RecipeHelper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory {
|
||||
public final static String GROUP = "smithing";
|
||||
public final static RecipeType<AnvilRecipe> TYPE = BCLRecipeManager.registerType(BCLib.MOD_ID, GROUP);
|
||||
public final static Serializer SERIALIZER = BCLRecipeManager.registerSerializer(
|
||||
BCLib.MOD_ID,
|
||||
GROUP,
|
||||
new Serializer()
|
||||
);
|
||||
public final static ResourceLocation ID = BCLib.makeID(GROUP);
|
||||
|
||||
private final ResourceLocation id;
|
||||
private final Ingredient input;
|
||||
private final ItemStack output;
|
||||
private final int damage;
|
||||
private final int toolLevel;
|
||||
private final int anvilLevel;
|
||||
private final int inputCount;
|
||||
|
||||
public AnvilRecipe(ResourceLocation identifier, Ingredient input, ItemStack output, int inputCount, int toolLevel, int anvilLevel, int damage) {
|
||||
this.id = identifier;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.toolLevel = toolLevel;
|
||||
this.anvilLevel = anvilLevel;
|
||||
this.inputCount = inputCount;
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
public static Builder create(String id) {
|
||||
return create(BCLib.makeID(id));
|
||||
}
|
||||
|
||||
public static Builder create(ResourceLocation id) {
|
||||
Builder.INSTANCE.id = id;
|
||||
Builder.INSTANCE.input = null;
|
||||
Builder.INSTANCE.output = null;
|
||||
Builder.INSTANCE.inputCount = 1;
|
||||
Builder.INSTANCE.toolLevel = 1;
|
||||
Builder.INSTANCE.anvilLevel = 1;
|
||||
Builder.INSTANCE.damage = 1;
|
||||
Builder.INSTANCE.alright = true;
|
||||
Builder.INSTANCE.exist = true;
|
||||
|
||||
return Builder.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getResultItem() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Container craftingInventory, Level world) {
|
||||
return this.matches(craftingInventory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack assemble(Container craftingInventory) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
public ItemStack craft(Container craftingInventory, Player player) {
|
||||
if (!player.isCreative()) {
|
||||
if (!checkHammerDurability(craftingInventory, player)) return ItemStack.EMPTY;
|
||||
ItemStack hammer = craftingInventory.getItem(1);
|
||||
hammer.hurtAndBreak(this.damage, player, entity -> entity.broadcastBreakEvent((InteractionHand) null));
|
||||
}
|
||||
return this.assemble(craftingInventory);
|
||||
}
|
||||
|
||||
public boolean checkHammerDurability(Container craftingInventory, Player player) {
|
||||
if (player.isCreative()) return true;
|
||||
ItemStack hammer = craftingInventory.getItem(1);
|
||||
int damage = hammer.getDamageValue() + this.damage;
|
||||
return damage < hammer.getMaxDamage();
|
||||
}
|
||||
|
||||
public boolean matches(Container craftingInventory) {
|
||||
ItemStack hammer = craftingInventory.getItem(1);
|
||||
if (hammer.isEmpty() || !TagAPI.ITEM_HAMMERS.contains(hammer.getItem())) {
|
||||
return false;
|
||||
}
|
||||
ItemStack material = craftingInventory.getItem(0);
|
||||
int materialCount = material.getCount();
|
||||
int level = ((TieredItem) hammer.getItem()).getTier().getLevel();
|
||||
return this.input.test(craftingInventory.getItem(0)) && materialCount >= this.inputCount && level >= this.toolLevel;
|
||||
}
|
||||
|
||||
public int getDamage() {
|
||||
return this.damage;
|
||||
}
|
||||
|
||||
public int getInputCount() {
|
||||
return this.inputCount;
|
||||
}
|
||||
|
||||
public int getAnvilLevel() {
|
||||
return this.anvilLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NonNullList<Ingredient> getIngredients() {
|
||||
NonNullList<Ingredient> defaultedList = NonNullList.create();
|
||||
defaultedList.add(Ingredient.of(TagAPI.ITEM_HAMMERS.getValues()
|
||||
.stream()
|
||||
.filter(hammer -> ((TieredItem) hammer).getTier()
|
||||
.getLevel() >= toolLevel)
|
||||
.map(ItemStack::new)));
|
||||
defaultedList.add(input);
|
||||
|
||||
return defaultedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public boolean canCraftInDimensions(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecial() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
AnvilRecipe that = (AnvilRecipe) o;
|
||||
return damage == that.damage && toolLevel == that.toolLevel && id.equals(that.id) && input.equals(that.input) && output
|
||||
.equals(that.output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, input, output, damage, toolLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AnvilRecipe [" + id + "]";
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
|
||||
private ResourceLocation id;
|
||||
private Ingredient input;
|
||||
private ItemStack output;
|
||||
private int inputCount = 1;
|
||||
private int toolLevel = 1;
|
||||
private int anvilLevel = 1;
|
||||
private int damage = 1;
|
||||
private boolean alright;
|
||||
private boolean exist;
|
||||
|
||||
private Builder() { }
|
||||
|
||||
public Builder setInput(ItemLike... inputItems) {
|
||||
this.alright &= RecipeHelper.exists(inputItems);
|
||||
this.setInput(Ingredient.of(inputItems));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Tag<Item> inputTag) {
|
||||
this.setInput(Ingredient.of(inputTag));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Ingredient ingredient) {
|
||||
this.input = ingredient;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInputCount(int count) {
|
||||
this.inputCount = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemLike output) {
|
||||
return this.setOutput(output, 1);
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemLike output, int amount) {
|
||||
this.alright &= RecipeHelper.exists(output);
|
||||
this.output = new ItemStack(output, amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setToolLevel(int level) {
|
||||
this.toolLevel = level;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAnvilLevel(int level) {
|
||||
this.anvilLevel = level;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDamage(int damage) {
|
||||
this.damage = damage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder checkConfig(PathConfig config) {
|
||||
exist |= config.getBoolean("anvil", id.getPath(), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (exist) {
|
||||
if (input == null) {
|
||||
BCLib.LOGGER.warning("Input for Anvil recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (output == null) {
|
||||
BCLib.LOGGER.warning("Output for Anvil recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (BCLRecipeManager.getRecipe(TYPE, id) != null) {
|
||||
BCLib.LOGGER.warning("Can't add Anvil recipe! Id {} already exists!", id);
|
||||
return;
|
||||
}
|
||||
if (!alright) {
|
||||
BCLib.LOGGER.debug("Can't add Anvil recipe {}! Ingeredient or output not exists.", id);
|
||||
return;
|
||||
}
|
||||
BCLRecipeManager.addRecipe(
|
||||
TYPE,
|
||||
new AnvilRecipe(id, input, output, inputCount, toolLevel, anvilLevel, damage)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<AnvilRecipe> {
|
||||
@Override
|
||||
public AnvilRecipe fromJson(ResourceLocation id, JsonObject json) {
|
||||
Ingredient input = Ingredient.fromJson(json.get("input"));
|
||||
JsonObject result = GsonHelper.getAsJsonObject(json, "result");
|
||||
ItemStack output = ItemUtil.fromJsonRecipe(result);
|
||||
if (output == null) {
|
||||
throw new IllegalStateException("Output item does not exists!");
|
||||
}
|
||||
if (result.has("nbt")) {
|
||||
try {
|
||||
String nbtData = GsonHelper.getAsString(result, "nbt");
|
||||
CompoundTag nbt = TagParser.parseTag(nbtData);
|
||||
output.setTag(nbt);
|
||||
}
|
||||
catch (CommandSyntaxException ex) {
|
||||
BCLib.LOGGER.warning("Error parse nbt data for output.", ex);
|
||||
}
|
||||
}
|
||||
int inputCount = GsonHelper.getAsInt(json, "inputCount", 1);
|
||||
int toolLevel = GsonHelper.getAsInt(json, "toolLevel", 1);
|
||||
int anvilLevel = GsonHelper.getAsInt(json, "anvilLevel", 1);
|
||||
int damage = GsonHelper.getAsInt(json, "damage", 1);
|
||||
|
||||
return new AnvilRecipe(id, input, output, inputCount, toolLevel, anvilLevel, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnvilRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf packetBuffer) {
|
||||
Ingredient input = Ingredient.fromNetwork(packetBuffer);
|
||||
ItemStack output = packetBuffer.readItem();
|
||||
int inputCount = packetBuffer.readVarInt();
|
||||
int toolLevel = packetBuffer.readVarInt();
|
||||
int anvilLevel = packetBuffer.readVarInt();
|
||||
int damage = packetBuffer.readVarInt();
|
||||
|
||||
return new AnvilRecipe(id, input, output, inputCount, toolLevel, anvilLevel, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNetwork(FriendlyByteBuf packetBuffer, AnvilRecipe recipe) {
|
||||
recipe.input.toNetwork(packetBuffer);
|
||||
packetBuffer.writeItem(recipe.output);
|
||||
packetBuffer.writeVarInt(recipe.inputCount);
|
||||
packetBuffer.writeVarInt(recipe.toolLevel);
|
||||
packetBuffer.writeVarInt(recipe.anvilLevel);
|
||||
packetBuffer.writeVarInt(recipe.damage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,37 +3,55 @@ package ru.bclib.registry;
|
|||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import ru.bclib.BCLib;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import ru.bclib.config.PathConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class BaseRegistry<T> {
|
||||
private static final List<BaseRegistry<?>> REGISTRIES = Lists.newArrayList();
|
||||
private static final Map<String, List<Item>> MOD_BLOCKS = Maps.newHashMap();
|
||||
private static final Map<String, List<Item>> MOD_BLOCK_ITEMS = Maps.newHashMap();
|
||||
private static final Map<String, List<Block>> MOD_BLOCKS = Maps.newHashMap();
|
||||
private static final Map<String, List<Item>> MOD_ITEMS = Maps.newHashMap();
|
||||
|
||||
protected final CreativeModeTab creativeTab;
|
||||
protected final PathConfig config;
|
||||
|
||||
protected BaseRegistry(CreativeModeTab creativeTab, PathConfig config) {
|
||||
this.creativeTab = creativeTab;
|
||||
this.config = config;
|
||||
REGISTRIES.add(this);
|
||||
}
|
||||
|
||||
public abstract T register(ResourceLocation objId, T obj);
|
||||
|
||||
public abstract void registerItem(ResourceLocation id, Item item);
|
||||
|
||||
public FabricItemSettings makeItemSettings() {
|
||||
FabricItemSettings properties = new FabricItemSettings();
|
||||
return (FabricItemSettings) properties.tab(creativeTab);
|
||||
}
|
||||
|
||||
private void registerInternal() {}
|
||||
|
||||
public static Map<String, List<Item>> getRegisteredBlocks() {
|
||||
return MOD_BLOCKS;
|
||||
return MOD_BLOCK_ITEMS;
|
||||
}
|
||||
|
||||
public static Map<String, List<Item>> getRegisteredItems() {
|
||||
return MOD_ITEMS;
|
||||
}
|
||||
|
||||
public static List<Item> getModBlocks(String modId) {
|
||||
if (MOD_BLOCKS.containsKey(modId)) {
|
||||
return MOD_BLOCKS.get(modId);
|
||||
public static List<Item> getModBlockItems(String modId) {
|
||||
if (MOD_BLOCK_ITEMS.containsKey(modId)) {
|
||||
return MOD_BLOCK_ITEMS.get(modId);
|
||||
}
|
||||
List<Item> modBlocks = Lists.newArrayList();
|
||||
MOD_BLOCKS.put(modId, modBlocks);
|
||||
MOD_BLOCK_ITEMS.put(modId, modBlocks);
|
||||
return modBlocks;
|
||||
}
|
||||
|
||||
|
@ -46,36 +64,16 @@ public abstract class BaseRegistry<T> {
|
|||
return modBlocks;
|
||||
}
|
||||
|
||||
public static List<Block> getModBlocks(String modId) {
|
||||
if (MOD_BLOCKS.containsKey(modId)) {
|
||||
return MOD_BLOCKS.get(modId);
|
||||
}
|
||||
List<Block> modBlocks = Lists.newArrayList();
|
||||
MOD_BLOCKS.put(modId, modBlocks);
|
||||
return modBlocks;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
REGISTRIES.forEach(BaseRegistry::registerInternal);
|
||||
}
|
||||
|
||||
protected BaseRegistry(CreativeModeTab creativeTab) {
|
||||
this.creativeTab = creativeTab;
|
||||
REGISTRIES.add(this);
|
||||
}
|
||||
|
||||
public T register(String name, T obj) {
|
||||
return register(createModId(name), obj);
|
||||
}
|
||||
|
||||
public abstract T register(ResourceLocation objId, T obj);
|
||||
|
||||
public ResourceLocation createModId(String name) {
|
||||
return BCLib.makeID(name);
|
||||
}
|
||||
|
||||
public void registerItem(ResourceLocation id, Item item, List<Item> registry) {
|
||||
if (item != Items.AIR) {
|
||||
Registry.register(Registry.ITEM, id, item);
|
||||
registry.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public FabricItemSettings makeItemSettings() {
|
||||
FabricItemSettings properties = new FabricItemSettings();
|
||||
return (FabricItemSettings) properties.tab(creativeTab);
|
||||
}
|
||||
|
||||
private void registerInternal() {}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,25 @@ import net.minecraft.resources.ResourceLocation;
|
|||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import ru.bclib.api.TagAPI;
|
||||
import ru.bclib.blocks.BaseLeavesBlock;
|
||||
import ru.bclib.blocks.FeatureSaplingBlock;
|
||||
import ru.bclib.config.PathConfig;
|
||||
import ru.bclib.interfaces.CustomItemProvider;
|
||||
|
||||
public abstract class BlockRegistry extends BaseRegistry<Block> {
|
||||
protected BlockRegistry(CreativeModeTab creativeTab) {
|
||||
super(creativeTab);
|
||||
public class BlockRegistry extends BaseRegistry<Block> {
|
||||
public BlockRegistry(CreativeModeTab creativeTab, PathConfig config) {
|
||||
super(creativeTab, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block register(ResourceLocation id, Block block) {
|
||||
if (!config.getBooleanRoot(id.getNamespace(), true)) {
|
||||
return block;
|
||||
}
|
||||
|
||||
BlockItem item = null;
|
||||
if (block instanceof CustomItemProvider) {
|
||||
item = ((CustomItemProvider) block).getCustomItem(id, makeItemSettings());
|
||||
|
@ -24,20 +33,46 @@ public abstract class BlockRegistry extends BaseRegistry<Block> {
|
|||
item = new BlockItem(block, makeItemSettings());
|
||||
}
|
||||
registerBlockItem(id, item);
|
||||
if (block.defaultBlockState().getMaterial().isFlammable() && FlammableBlockRegistry.getDefaultInstance()
|
||||
.get(block)
|
||||
.getBurnChance() == 0) {
|
||||
if (block.defaultBlockState().getMaterial().isFlammable() && FlammableBlockRegistry.getDefaultInstance().get(block).getBurnChance() == 0) {
|
||||
FlammableBlockRegistry.getDefaultInstance().add(block, 5, 5);
|
||||
}
|
||||
return Registry.register(Registry.BLOCK, id, block);
|
||||
|
||||
block = Registry.register(Registry.BLOCK, id, block);
|
||||
getModBlocks(id.getNamespace()).add(block);
|
||||
|
||||
if (block instanceof BaseLeavesBlock){
|
||||
TagAPI.addTags(block, TagAPI.BLOCK_LEAVES);
|
||||
if (item != null){
|
||||
TagAPI.addTags(item, TagAPI.ITEM_LEAVES);
|
||||
}
|
||||
} else if (block instanceof FeatureSaplingBlock){
|
||||
TagAPI.addTags(block, TagAPI.BLOCK_SAPLINGS);
|
||||
if (item != null){
|
||||
TagAPI.addTags(item, TagAPI.ITEM_SAPLINGS);
|
||||
}
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
public Block registerBlockOnly(ResourceLocation id, Block block) {
|
||||
if (!config.getBooleanRoot(id.getNamespace(), true)) {
|
||||
return block;
|
||||
}
|
||||
getModBlocks(id.getNamespace()).add(block);
|
||||
return Registry.register(Registry.BLOCK, id, block);
|
||||
}
|
||||
|
||||
private Item registerBlockItem(ResourceLocation id, Item item) {
|
||||
registerItem(id, item, BaseRegistry.getModBlocks(id.getNamespace()));
|
||||
registerItem(id, item);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerItem(ResourceLocation id, Item item) {
|
||||
if (item != null && item != Items.AIR) {
|
||||
Registry.register(Registry.ITEM, id, item);
|
||||
getModBlockItems(id.getNamespace()).add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package ru.bclib.registry;
|
|||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.core.BlockSource;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
|
||||
import net.minecraft.core.dispenser.ShearsDispenseItemBehavior;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.tags.Tag;
|
||||
|
@ -15,12 +17,13 @@ import net.minecraft.world.food.FoodProperties;
|
|||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.ShovelItem;
|
||||
import net.minecraft.world.item.SpawnEggItem;
|
||||
import net.minecraft.world.item.SwordItem;
|
||||
import net.minecraft.world.item.TieredItem;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import ru.bclib.api.TagAPI;
|
||||
import ru.bclib.config.PathConfig;
|
||||
import ru.bclib.items.BaseDiscItem;
|
||||
import ru.bclib.items.BaseDrinkItem;
|
||||
import ru.bclib.items.BaseSpawnEggItem;
|
||||
|
@ -28,30 +31,44 @@ import ru.bclib.items.ModelProviderItem;
|
|||
import ru.bclib.items.tool.BaseAxeItem;
|
||||
import ru.bclib.items.tool.BaseHoeItem;
|
||||
import ru.bclib.items.tool.BasePickaxeItem;
|
||||
import ru.bclib.items.tool.BaseShearsItem;
|
||||
|
||||
public abstract class ItemRegistry extends BaseRegistry<Item> {
|
||||
|
||||
protected ItemRegistry(CreativeModeTab creativeTab) {
|
||||
super(creativeTab);
|
||||
public class ItemRegistry extends BaseRegistry<Item> {
|
||||
public ItemRegistry(CreativeModeTab creativeTab, PathConfig config) {
|
||||
super(creativeTab, config);
|
||||
}
|
||||
|
||||
public Item registerDisc(String name, int power, SoundEvent sound) {
|
||||
return register(name, new BaseDiscItem(power, sound, makeItemSettings().stacksTo(1)));
|
||||
public Item registerDisc(ResourceLocation itemId, int power, SoundEvent sound) {
|
||||
BaseDiscItem item = new BaseDiscItem(power, sound, makeItemSettings().stacksTo(1));
|
||||
|
||||
if (!config.getBoolean("musicDiscs", itemId.getPath(), true)) {
|
||||
return item;
|
||||
}
|
||||
|
||||
return register(itemId, new BaseDiscItem(power, sound, makeItemSettings().stacksTo(1)));
|
||||
}
|
||||
|
||||
public Item registerItem(String name) {
|
||||
return register(name, new ModelProviderItem(makeItemSettings()));
|
||||
public Item register(ResourceLocation itemId) {
|
||||
return register(itemId, new ModelProviderItem(makeItemSettings()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item register(ResourceLocation itemId, Item item) {
|
||||
registerItem(itemId, item, BaseRegistry.getModItems(itemId.getNamespace()));
|
||||
if (!config.getBoolean("items", itemId.getPath(), true)) {
|
||||
return item;
|
||||
}
|
||||
|
||||
registerItem(itemId, item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public TieredItem registerTool(String name, TieredItem item) {
|
||||
ResourceLocation id = createModId(name);
|
||||
registerItem(id, item, BaseRegistry.getModItems(id.getNamespace()));
|
||||
public Item registerTool(ResourceLocation itemId, Item item) {
|
||||
if (!config.getBoolean("tools", itemId.getPath(), true)) {
|
||||
return item;
|
||||
}
|
||||
|
||||
registerItem(itemId, item);
|
||||
|
||||
if (item instanceof ShovelItem) {
|
||||
TagAPI.addTag((Tag.Named<Item>) FabricToolTags.SHOVELS, item);
|
||||
|
@ -68,12 +85,21 @@ public abstract class ItemRegistry extends BaseRegistry<Item> {
|
|||
else if (item instanceof BaseHoeItem) {
|
||||
TagAPI.addTag((Tag.Named<Item>) FabricToolTags.HOES, item);
|
||||
}
|
||||
else if (item instanceof BaseShearsItem) {
|
||||
TagAPI.addTags(item, (Tag.Named<Item>) FabricToolTags.SHEARS, TagAPI.ITEM_SHEARS, TagAPI.ITEM_COMMON_SHEARS);
|
||||
DispenserBlock.registerBehavior(item.asItem(), new ShearsDispenseItemBehavior());
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public Item registerEgg(String name, EntityType<? extends Mob> type, int background, int dots) {
|
||||
public Item registerEgg(ResourceLocation itemId, EntityType<? extends Mob> type, int background, int dots) {
|
||||
SpawnEggItem item = new BaseSpawnEggItem(type, background, dots, makeItemSettings());
|
||||
|
||||
if (!config.getBoolean("spawnEggs", itemId.getPath(), true)) {
|
||||
return item;
|
||||
}
|
||||
|
||||
DefaultDispenseItemBehavior behavior = new DefaultDispenseItemBehavior() {
|
||||
public ItemStack execute(BlockSource pointer, ItemStack stack) {
|
||||
Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
|
||||
|
@ -92,31 +118,42 @@ public abstract class ItemRegistry extends BaseRegistry<Item> {
|
|||
}
|
||||
};
|
||||
DispenserBlock.registerBehavior(item, behavior);
|
||||
return register(name, item);
|
||||
return register(itemId, item);
|
||||
}
|
||||
|
||||
public Item registerFood(String name, int hunger, float saturation, MobEffectInstance... effects) {
|
||||
public Item registerFood(ResourceLocation itemId, int hunger, float saturation, MobEffectInstance... effects) {
|
||||
FoodProperties.Builder builder = new FoodProperties.Builder().nutrition(hunger).saturationMod(saturation);
|
||||
for (MobEffectInstance effect : effects) {
|
||||
builder.effect(effect, 1F);
|
||||
}
|
||||
return registerFood(name, builder.build());
|
||||
return registerFood(itemId, builder.build());
|
||||
}
|
||||
|
||||
public Item registerFood(String name, FoodProperties foodComponent) {
|
||||
return register(name, new ModelProviderItem(makeItemSettings().food(foodComponent)));
|
||||
public Item registerFood(ResourceLocation itemId, FoodProperties foodComponent) {
|
||||
return register(itemId, new ModelProviderItem(makeItemSettings().food(foodComponent)));
|
||||
}
|
||||
|
||||
public Item registerDrink(String name) {
|
||||
return register(name, new BaseDrinkItem(makeItemSettings().stacksTo(1)));
|
||||
public Item registerDrink(ResourceLocation itemId, FoodProperties foodComponent) {
|
||||
return register(itemId, new BaseDrinkItem(makeItemSettings().stacksTo(1).food(foodComponent)));
|
||||
}
|
||||
|
||||
public Item registerDrink(String name, FoodProperties foodComponent) {
|
||||
return register(name, new BaseDrinkItem(makeItemSettings().stacksTo(1).food(foodComponent)));
|
||||
}
|
||||
|
||||
public Item registerDrink(String name, int hunger, float saturation) {
|
||||
public Item registerDrink(ResourceLocation itemId, int hunger, float saturation) {
|
||||
FoodProperties.Builder builder = new FoodProperties.Builder().nutrition(hunger).saturationMod(saturation);
|
||||
return registerDrink(name, builder.build());
|
||||
return registerDrink(itemId, builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerItem(ResourceLocation id, Item item) {
|
||||
if (item != null && item != Items.AIR) {
|
||||
Registry.register(Registry.ITEM, id, item);
|
||||
getModItems(id.getNamespace()).add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public Item register(ResourceLocation itemId, Item item, String category) {
|
||||
if (config.getBoolean(category, itemId.getPath(), true)) {
|
||||
registerItem(itemId, item);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
74
src/main/java/ru/bclib/util/ItemUtil.java
Normal file
74
src/main/java/ru/bclib/util/ItemUtil.java
Normal file
|
@ -0,0 +1,74 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import ru.bclib.BCLib;
|
||||
|
||||
public class ItemUtil {
|
||||
|
||||
public static String toStackString(@NotNull ItemStack stack) {
|
||||
try {
|
||||
if (stack == null) {
|
||||
throw new IllegalStateException("Stack can't be null!");
|
||||
}
|
||||
Item item = stack.getItem();
|
||||
return Registry.ITEM.getKey(item) + ":" + stack.getCount();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
BCLib.LOGGER.error("ItemStack serialization error!", ex);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ItemStack fromStackString(String stackString) {
|
||||
if (stackString == null || stackString.equals("")) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String[] parts = stackString.split(":");
|
||||
if (parts.length < 2) return null;
|
||||
if (parts.length == 2) {
|
||||
ResourceLocation itemId = new ResourceLocation(stackString);
|
||||
Item item = Registry.ITEM.getOptional(itemId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Output item " + itemId + " does not exists!");
|
||||
});
|
||||
return new ItemStack(item);
|
||||
}
|
||||
ResourceLocation itemId = new ResourceLocation(parts[0], parts[1]);
|
||||
Item item = Registry.ITEM.getOptional(itemId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Output item " + itemId + " does not exists!");
|
||||
});
|
||||
return new ItemStack(item, Integer.valueOf(parts[2]));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
BCLib.LOGGER.error("ItemStack deserialization error!", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ItemStack fromJsonRecipe(JsonObject recipe) {
|
||||
try {
|
||||
if (!recipe.has("item")) {
|
||||
throw new IllegalStateException("Invalid JsonObject. Entry 'item' does not exists!");
|
||||
}
|
||||
ResourceLocation itemId = new ResourceLocation(GsonHelper.getAsString(recipe, "item"));
|
||||
Item item = Registry.ITEM.getOptional(itemId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Output item " + itemId + " does not exists!");
|
||||
});
|
||||
int count = GsonHelper.getAsInt(recipe, "count", 1);
|
||||
return new ItemStack(item, count);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
BCLib.LOGGER.error("ItemStack deserialization error!", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,22 +1,35 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.fabricmc.loader.api.SemanticVersion;
|
||||
import net.fabricmc.loader.api.Version;
|
||||
import net.fabricmc.loader.api.VersionParsingException;
|
||||
import net.fabricmc.loader.api.metadata.ContactInformation;
|
||||
import net.fabricmc.loader.api.metadata.CustomValue;
|
||||
import net.fabricmc.loader.api.metadata.ModDependency;
|
||||
import net.fabricmc.loader.api.metadata.ModEnvironment;
|
||||
import net.fabricmc.loader.api.metadata.ModMetadata;
|
||||
import net.fabricmc.loader.impl.metadata.ModMetadataParser;
|
||||
import net.fabricmc.loader.impl.metadata.ParseMetadataException;
|
||||
import net.fabricmc.loader.api.metadata.Person;
|
||||
import net.fabricmc.loader.util.version.SemanticVersionImpl;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import ru.bclib.BCLib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
|
@ -59,17 +72,19 @@ public class ModUtil {
|
|||
Path modMetaFile = fs.getPath("fabric.mod.json");
|
||||
if (modMetaFile != null) {
|
||||
try (InputStream is = Files.newInputStream(modMetaFile)) {
|
||||
ModMetadata mc = ModMetadataParser.parseMetadata(is, uri.toString(), new LinkedList<String>());
|
||||
mods.put(mc.getId(), new ModInfo(mc, file));
|
||||
//ModMetadata mc = ModMetadataParser.parseMetadata(is, uri.toString(), new LinkedList<String>());
|
||||
ModMetadata mc = readJSON(is, uri.toString());
|
||||
if (mc!=null){
|
||||
mods.put(mc.getId(), new ModInfo(mc, file));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (ParseMetadataException e) {
|
||||
} catch (Exception e) {
|
||||
BCLib.LOGGER.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
catch (Exception e) {
|
||||
BCLib.LOGGER.error(e.getMessage());
|
||||
}
|
||||
}));
|
||||
|
@ -77,6 +92,176 @@ public class ModUtil {
|
|||
return mods;
|
||||
}
|
||||
|
||||
private static ModMetadata readJSON(InputStream is, String sourceFile) throws IOException {
|
||||
try (com.google.gson.stream.JsonReader reader = new JsonReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
JsonObject data = new JsonParser().parse(reader).getAsJsonObject();
|
||||
Version ver;
|
||||
try {
|
||||
ver = new SemanticVersionImpl(data.get("version").getAsString(), false);
|
||||
}
|
||||
catch (VersionParsingException e) {
|
||||
BCLib.LOGGER.error("Unable to parse Version in " + sourceFile);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.get("id") == null){
|
||||
BCLib.LOGGER.error("Unable to read ID in " + sourceFile);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.get("name") == null){
|
||||
BCLib.LOGGER.error("Unable to read name in " + sourceFile);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ModMetadata() {
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
return ver;
|
||||
}
|
||||
@Override
|
||||
public String getType() {
|
||||
return "fabric";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return data.get("id").getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getProvides() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModEnvironment getEnvironment() {
|
||||
JsonElement env = data.get("environment");
|
||||
if (env==null) {
|
||||
BCLib.LOGGER.error("No environment specified in " + sourceFile);
|
||||
return ModEnvironment.UNIVERSAL;
|
||||
}
|
||||
final String environment = env.getAsString().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (environment.isEmpty() || environment.equals("*") || environment.equals("common")) {
|
||||
JsonElement entrypoints = data.get("entrypoints");
|
||||
boolean hasClient = true;
|
||||
|
||||
//check if there is an actual client entrypoint
|
||||
if (entrypoints!=null && entrypoints.isJsonObject()){
|
||||
JsonElement client = entrypoints.getAsJsonObject().get("client");
|
||||
if (client!=null && client.isJsonArray()){
|
||||
hasClient = client.getAsJsonArray().size() > 0;
|
||||
} else if (client==null || !client.isJsonPrimitive()){
|
||||
hasClient = false;
|
||||
} else if (!client.getAsJsonPrimitive().isString()){
|
||||
hasClient = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasClient == false) return ModEnvironment.SERVER;
|
||||
return ModEnvironment.UNIVERSAL;
|
||||
} else if (environment.equals("client")) {
|
||||
return ModEnvironment.CLIENT;
|
||||
} else if (environment.equals("server")) {
|
||||
return ModEnvironment.SERVER;
|
||||
} else {
|
||||
BCLib.LOGGER.error("Unable to read environment in " + sourceFile);
|
||||
return ModEnvironment.UNIVERSAL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModDependency> getDepends() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModDependency> getRecommends() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModDependency> getSuggests() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModDependency> getConflicts() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModDependency> getBreaks() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public Collection<ModDependency> getDependencies() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return data.get("name").getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Person> getAuthors() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Person> getContributors() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactInformation getContact() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getLicense() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getIconPath(int size) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCustomValue(String key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomValue getCustomValue(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, CustomValue> getCustomValues() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCustomElement(String key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public JsonElement getCustomElement(String key) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ModInfo} or {@code null} if the mod was not found.
|
||||
* <p>
|
||||
|
|
25
src/main/java/ru/bclib/util/RecipeHelper.java
Normal file
25
src/main/java/ru/bclib/util/RecipeHelper.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
public class RecipeHelper {
|
||||
public static boolean exists(ItemLike item) {
|
||||
if (item instanceof Block) {
|
||||
return Registry.BLOCK.getKey((Block) item) != Registry.BLOCK.getDefaultKey();
|
||||
}
|
||||
else {
|
||||
return Registry.ITEM.getKey(item.asItem()) != Registry.ITEM.getDefaultKey();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean exists(ItemLike... items) {
|
||||
for (ItemLike item : items) {
|
||||
if (!exists(item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ public class TranslationHelper {
|
|||
|
||||
Gson gson = new Gson();
|
||||
InputStream inputStream = TranslationHelper.class.getResourceAsStream("/assets/" + modID + "/lang/" + languageCode + ".json");
|
||||
JsonObject translation = gson.fromJson(new InputStreamReader(inputStream), JsonObject.class);
|
||||
JsonObject translation = inputStream == null ? new JsonObject() : gson.fromJson(new InputStreamReader(inputStream), JsonObject.class);
|
||||
|
||||
Registry.BLOCK.forEach(block -> {
|
||||
if (Registry.BLOCK.getKey(block).getNamespace().equals(modID)) {
|
||||
|
|
|
@ -70,6 +70,7 @@ public class BCLBiomeDef {
|
|||
private int waterFogColor = 329011;
|
||||
private int waterColor = 4159204;
|
||||
private int fogColor = 10518688;
|
||||
private int skyColor = 0;
|
||||
private float fogDensity = 1F;
|
||||
private float depth = 0.1F;
|
||||
|
||||
|
@ -247,11 +248,24 @@ public class BCLBiomeDef {
|
|||
return ColorUtil.color(r, g, b);
|
||||
}
|
||||
|
||||
public BCLBiomeDef setFogColor(int r, int g, int b) {
|
||||
this.fogColor = getColor(r, g, b);
|
||||
public BCLBiomeDef setSkyColor(int rgb) {
|
||||
this.skyColor = rgb;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BCLBiomeDef setSkyColor(int r, int g, int b) {
|
||||
return setSkyColor(getColor(r, g, b));
|
||||
}
|
||||
|
||||
public BCLBiomeDef setFogColor(int rgb) {
|
||||
this.fogColor = rgb;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BCLBiomeDef setFogColor(int r, int g, int b) {
|
||||
return setFogColor(getColor(r, g, b));
|
||||
}
|
||||
|
||||
public BCLBiomeDef setFogDensity(float density) {
|
||||
this.fogDensity = density;
|
||||
return this;
|
||||
|
@ -333,7 +347,7 @@ public class BCLBiomeDef {
|
|||
|
||||
addCustomToBuild(generationSettings);
|
||||
|
||||
effects.skyColor(0)
|
||||
effects.skyColor(skyColor)
|
||||
.waterColor(waterColor)
|
||||
.waterFogColor(waterFogColor)
|
||||
.fogColor(fogColor)
|
||||
|
@ -380,9 +394,9 @@ public class BCLBiomeDef {
|
|||
ConfiguredFeature<?, ?> feature;
|
||||
}
|
||||
|
||||
private static final class CarverInfo {
|
||||
private static final class CarverInfo <C extends CarverConfiguration> {
|
||||
Carving carverStep;
|
||||
ConfiguredWorldCarver<CarverConfiguration> carver;
|
||||
ConfiguredWorldCarver<C> carver;
|
||||
}
|
||||
|
||||
public ResourceLocation getID() {
|
||||
|
@ -401,7 +415,7 @@ public class BCLBiomeDef {
|
|||
return edgeSize;
|
||||
}
|
||||
|
||||
public BCLBiomeDef addCarver(Carving carverStep, ConfiguredWorldCarver<CarverConfiguration> carver) {
|
||||
public <C extends CarverConfiguration> BCLBiomeDef addCarver(Carving carverStep, ConfiguredWorldCarver<C> carver) {
|
||||
CarverInfo info = new CarverInfo();
|
||||
info.carverStep = carverStep;
|
||||
info.carver = carver;
|
||||
|
|
|
@ -29,6 +29,7 @@ public class BCLibNetherBiomeSource extends BiomeSource {
|
|||
private BiomeMap biomeMap;
|
||||
private final long seed;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public static final List<Consumer<BCLibNetherBiomeSource>> onInit = new LinkedList<>();
|
||||
|
||||
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, long seed) {
|
||||
|
|
|
@ -12,11 +12,15 @@ public class GeneratorOptions {
|
|||
private static int biomeSizeEndVoid;
|
||||
private static Function<Point, Boolean> endLandFunction;
|
||||
private static boolean farEndBiomes = true;
|
||||
private static boolean customNetherBiomeSource = true;
|
||||
private static boolean customEndBiomeSource = true;
|
||||
|
||||
public static void init() {
|
||||
biomeSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap", "biomeSize", 256);
|
||||
biomeSizeEndLand = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeLand", 256);
|
||||
biomeSizeEndVoid = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeVoid", 256);
|
||||
customNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customNetherBiomeSource", true);
|
||||
customEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customEndBiomeSource", true);
|
||||
}
|
||||
|
||||
public static int getBiomeSizeNether() {
|
||||
|
@ -46,4 +50,12 @@ public class GeneratorOptions {
|
|||
public static void setFarEndBiomes(boolean farEndBiomes) {
|
||||
GeneratorOptions.farEndBiomes = farEndBiomes;
|
||||
}
|
||||
|
||||
public static boolean customNetherBiomeSource() {
|
||||
return customNetherBiomeSource;
|
||||
}
|
||||
|
||||
public static boolean customEndBiomeSource() {
|
||||
return customEndBiomeSource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,43 +5,46 @@
|
|||
"bclib.datafixer.backupWarning.backup": "Backup erstellen bevor die Reperaturen angewendet werden",
|
||||
"bclib.datafixer.backupWarning.nofixes": "Weiter ohne Reperaturen",
|
||||
"bclib.datafixer.backupWarning.fix": "Reperaturen Anwenden",
|
||||
"title.bclib.bclibmissmatch": "Version Mismatch",
|
||||
"message.bclib.bclibmissmatch": "The Version of BCLib on the server and this client do not match. This will cause problems when playing.\n\nDo you want to automatically download the BCLib-Version from the server? \n\nBCLib will move the old version into a subdirectory of your Mods-Folder and before installing the new one.",
|
||||
"title.bclib.syncfiles": "Mismatching Data",
|
||||
"message.bclib.syncfiles": "Some Content on the Server does not match the versions on the client.\nDo you want to replace the selected content with the data from the server?",
|
||||
"message.bclib.syncfiles.mods": "Synchronize Mods",
|
||||
"message.bclib.syncfiles.configs": "Synchronize Configs",
|
||||
"message.bclib.syncfiles.folders": "Synchronize Folders and Files",
|
||||
"message.bclib.syncfiles.delete": "Delete unneeded",
|
||||
"title.bclib.confirmrestart": "Restart Required",
|
||||
"message.bclib.confirmrestart": "The requested content was synchronized. You need to restart Minecraft now.",
|
||||
"title.bclib.bclibmissmatch": "Versionsunterschied",
|
||||
"message.bclib.bclibmissmatch": "Die Version von BCLib auf dem Server und dem Client sind unterschiedlich. Dies kann Probleme verursachen.\n\nSoll die passende Version von BCLib vom Server auf diese Maschine kopiert werden? \n\nDazu wird die aktuell installierte Version von BCLib im Mods-Verzeichnis in einen Unterordner verschoben und die Version vom Server installiert.",
|
||||
"title.bclib.syncfiles": "Inkonsistente Daten",
|
||||
"message.bclib.syncfiles": "Einige Daten (Konfigurationen, Mods, ...) sind unterschiedlich.\nSollen die unten ausgewählten Inhalte vom Server auf diese Maschine kopieren?",
|
||||
"message.bclib.syncfiles.mods": "Mods synchronisieren",
|
||||
"message.bclib.syncfiles.configs": "Einstellungen synchronisieren",
|
||||
"message.bclib.syncfiles.folders": "Dateien und Ordner synchronisieren",
|
||||
"message.bclib.syncfiles.delete": "Unnötige löschen",
|
||||
"title.bclib.confirmrestart": "Neustart erforderlich",
|
||||
"message.bclib.confirmrestart": "Die angeforderten Inhalte wurden erfolgreich übertragen. Minecraft muss nun neu gestartet werden.",
|
||||
"title.link.bclib.discord": "Discord",
|
||||
"title.bclib.modmenu.main": "BCLib Settings",
|
||||
"title.bclib.progress": "Progress",
|
||||
"title.bclib.filesync.progress": "File Transfer",
|
||||
"message.bclib.filesync.progress": "Syncing File-Content with Server",
|
||||
"title.bclib.modmenu.main": "BCLib Einstellungen",
|
||||
"title.bclib.progress": "Fortschritt",
|
||||
"title.bclib.filesync.progress": "Datenübertragung",
|
||||
"message.bclib.filesync.progress": "Snychronisiere Dateien und Verzeichnise vom Server",
|
||||
"message.bclib.filesync.progress.stage.empty": "",
|
||||
|
||||
"title.config.bclib.client.auto_sync.enabled": "Enable Auto-Sync",
|
||||
"title.config.bclib.client.auto_sync.acceptConfigs": "Accept incoming Confog Files",
|
||||
"title.config.bclib.client.auto_sync.acceptFiles": "Accept incoming Files",
|
||||
"title.config.bclib.client.auto_sync.acceptMods": "Accept incoming Mods",
|
||||
"title.config.bclib.client.auto_sync.displayModInfo": "Display warning when Serverside Mods differ from Client",
|
||||
"title.config.bclib.client.auto_sync.debugHashes": "Print Auto-Sync Debug-Hashes to Log",
|
||||
"title.config.bclib.client.auto_sync.enabled": "Auto-Sync Aktivieren",
|
||||
"title.config.bclib.client.auto_sync.acceptConfigs": "Konfiguration von Server annehmen",
|
||||
"title.config.bclib.client.auto_sync.acceptFiles": "Dateien von Server annehmen",
|
||||
"title.config.bclib.client.auto_sync.acceptMods": "Mods von Server annehmen",
|
||||
"title.config.bclib.client.auto_sync.displayModInfo": "Warnung anzeigen wen Mods auf Server/Client unterschiedlich",
|
||||
"title.config.bclib.client.auto_sync.debugHashes": "Erweiterete Logausgabe für Auto-Sync",
|
||||
|
||||
"title.bclib.syncfiles.modInfo": "Mod Info",
|
||||
"title.bclib.syncfiles.modlist": "Mod Information",
|
||||
"message.bclib.syncfiles.modlist": "The following shows the state of your installed installed Mods.\n\nAll Mods that do not exist locally, or have a different version will on the Server will be synchronized.",
|
||||
"title.bclib.modmissmatch": "Mod Version Conflict",
|
||||
"message.bclib.modmissmatch": "Some Mods on this client do not match the version of Mods on the Server.\n\nMismatching Mods can result in odd game behavior or crashes. Please make sue that you use the same mods as the server.",
|
||||
"message.bclib.syncfiles.modlist": "Im Folgenden wird der Status deiner installierten Mods angezeigt.\n\nAlle Mods, die lokal nicht vorhanden sind oder eine andere Version auf dem Server haben, werden synchronisiert.",
|
||||
"title.bclib.modmissmatch": "Mod-Konflikt",
|
||||
"message.bclib.modmissmatch": "Einige Mods auf diesem Rechner stimmen nicht mit der Version auf dem Server überein.\n\nNicht übereinstimmende Mods können zu merkwürdigem Spielverhalten oder Abstürzen führen. Bitte stellen Sie sicher, dass Sie die gleichen Mods wie auf dem Server verwenden.",
|
||||
|
||||
"message.bclib.datafixer.progress.waitbackup": "Waiting for Backup to finish. This may take a while!",
|
||||
"message.bclib.datafixer.progress.reading": "Reading Data",
|
||||
"message.bclib.datafixer.progress.players": "Fixing Players",
|
||||
"message.bclib.datafixer.progress.level": "Applying Patches to level.dat",
|
||||
"message.bclib.datafixer.progress.worlddata": "Patching Custom World-Data",
|
||||
"message.bclib.datafixer.progress.regions": "Repairing all Regions",
|
||||
"message.bclib.datafixer.progress.saving": "Saving Patch State",
|
||||
"title.bclib.datafixer.progress": "Fixing World",
|
||||
"message.bclib.datafixer.progress": "Applying all Patches to your World."
|
||||
"message.bclib.datafixer.progress.waitbackup": "Ich warte auf das Ende der Sicherung. Dies kann eine Weile dauern!",
|
||||
"message.bclib.datafixer.progress.reading": "Lese Daten",
|
||||
"message.bclib.datafixer.progress.players": "Repariere Spieler",
|
||||
"message.bclib.datafixer.progress.level": "Patches auf level.dat anwenden",
|
||||
"message.bclib.datafixer.progress.worlddata": "Benutzerdefinierte Weltdaten patchen",
|
||||
"message.bclib.datafixer.progress.regions": "Alle Regionen reparieren",
|
||||
"message.bclib.datafixer.progress.saving": "Patch-Status speichern",
|
||||
"title.bclib.datafixer.progress": "Welt in Ordnung bringen",
|
||||
"message.bclib.datafixer.progress": "Anwenden aller Änderungen",
|
||||
"title.bclib.datafixer.error": "Fehler beim Reparieren der Welt",
|
||||
"message.bclib.datafixer.error": "Es gab Fehler beim Reparieren der Welt. Das bedeutet, dass dieser Level wahrscheinlich in einem inkonsistenten Zustand ist und Sie ihn nicht spielen sollten. Bitte stellen Sie Ihr Backup wieder her und beheben Sie die unten aufgeführten Fehler, bevor Sie es erneut versuchen.",
|
||||
"title.bclib.datafixer.error.continue": "Continue and Mark as Fixed"
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
"message.bclib.filesync.progress.stage.empty": "",
|
||||
|
||||
"title.config.bclib.client.auto_sync.enabled": "Enable Auto-Sync",
|
||||
"title.config.bclib.client.auto_sync.acceptConfigs": "Accept incoming Confog Files",
|
||||
"title.config.bclib.client.auto_sync.acceptConfigs": "Accept incoming Config Files",
|
||||
"title.config.bclib.client.auto_sync.acceptFiles": "Accept incoming Files",
|
||||
"title.config.bclib.client.auto_sync.acceptMods": "Accept incoming Mods",
|
||||
"title.config.bclib.client.auto_sync.displayModInfo": "Display warning when Serverside Mods differ from Client",
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
"title.bclib.syncfiles.modInfo": "Mod Info",
|
||||
"title.bclib.syncfiles.modlist": "Mod Information",
|
||||
"message.bclib.syncfiles.modlist": "The following shows the state of your installed installed Mods.\n\nAll Mods that do not exist locally, or have a different version will on the Server will be synchronized.",
|
||||
"message.bclib.syncfiles.modlist": "The following shows the state of your installed installed Mods.\n\nAll Mods that do not exist locally, or have a different version on the Server will be synchronized.",
|
||||
"title.bclib.modmissmatch": "Mod Version Conflict",
|
||||
"message.bclib.modmissmatch": "Some Mods on this client do not match the version of Mods on the Server.\n\nMismatching Mods can result in odd game behavior or crashes. Please make sue that you use the same mods as the server.",
|
||||
|
||||
|
@ -43,5 +43,8 @@
|
|||
"message.bclib.datafixer.progress.regions": "Repairing all Regions",
|
||||
"message.bclib.datafixer.progress.saving": "Saving Patch State",
|
||||
"title.bclib.datafixer.progress": "Fixing World",
|
||||
"message.bclib.datafixer.progress": "Applying all Patches to your World."
|
||||
"message.bclib.datafixer.progress": "Applying all Patches to your World.",
|
||||
"title.bclib.datafixer.error": "Errors while fixing World",
|
||||
"message.bclib.datafixer.error": "There were errors while repairing the world. This means that this level is probably in an inconsistent state and you should not play it. Please restore your backup and fix the errors below before trying again.",
|
||||
"title.bclib.datafixer.error.continue": "Fortfahren und als behoben markieren"
|
||||
}
|
|
@ -7,8 +7,10 @@
|
|||
"SimpleReloadableResourceManagerMixin",
|
||||
"EnchantingTableBlockMixin",
|
||||
"BackgroundRendererMixin",
|
||||
"ClientRecipeBookMixin",
|
||||
"ModelManagerMixin",
|
||||
"TextureAtlasMixin",
|
||||
"AnvilScreenMixin",
|
||||
"ModelBakeryMixin",
|
||||
"MinecraftMixin",
|
||||
"GameMixin",
|
||||
|
|
|
@ -5,23 +5,33 @@
|
|||
"compatibilityLevel": "JAVA_16",
|
||||
"mixins": [
|
||||
"SimpleReloadableResourceManagerMixin",
|
||||
"shears.DiggingEnchantmentMixin",
|
||||
"shears.TripWireBlockMixin",
|
||||
"ChunkBiomeContainerMixin",
|
||||
"shears.BeehiveBlockMixin",
|
||||
"shears.PumpkinBlockMixin",
|
||||
"shears.MushroomCowMixin",
|
||||
"shears.SnowGolemMixin",
|
||||
"ComposterBlockAccessor",
|
||||
"InternalBiomeDataMixin",
|
||||
"PotionBrewingAccessor",
|
||||
"RecipeManagerAccessor",
|
||||
"EnchantmentMenuMixin",
|
||||
"MinecraftServerMixin",
|
||||
"PistonBaseBlockMixin",
|
||||
"WorldGenRegionMixin",
|
||||
"DimensionTypeMixin",
|
||||
"RecipeManagerMixin",
|
||||
"CraftingMenuMixin",
|
||||
"BoneMealItemMixin",
|
||||
"shears.SheepMixin",
|
||||
"PortalShapeMixin",
|
||||
"ServerLevelMixin",
|
||||
"AnvilBlockMixin",
|
||||
"AnvilMenuMixin",
|
||||
"TagLoaderMixin",
|
||||
"ChunkGeneratorMixin",
|
||||
"MainMixin",
|
||||
"TheEndBiomeDataMixin",
|
||||
"NetherBiomeDataMixin"
|
||||
"BiomeMixin",
|
||||
"MainMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.11.6",
|
||||
"fabric": ">=0.36.0",
|
||||
"fabric": ">=0.41.0",
|
||||
"minecraft": ">=1.17.1"
|
||||
},
|
||||
"custom":{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue