Merge branch 'master' into experimental
|
@ -8,7 +8,7 @@
|
|||
loader_version=0.11.3
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 0.9.4-pre
|
||||
mod_version = 0.9.7-pre
|
||||
maven_group = ru.betterend
|
||||
archives_base_name = better-end
|
||||
|
||||
|
|
0
gradlew
vendored
Normal file → Executable file
|
@ -39,6 +39,8 @@ import ru.betterend.world.surface.SurfaceBuilders;
|
|||
public class BetterEnd implements ModInitializer {
|
||||
public static final String MOD_ID = "betterend";
|
||||
public static final Logger LOGGER = Logger.get();
|
||||
private static boolean hasHydrogen;
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
EndPortals.loadPortals();
|
||||
|
@ -70,6 +72,7 @@ public class BetterEnd implements ModInitializer {
|
|||
if (hasGuideBook()) {
|
||||
GuideBookItem.register();
|
||||
}
|
||||
hasHydrogen = FabricLoader.getInstance().isModLoaded("hydrogen");
|
||||
|
||||
FabricLoader.getInstance().getEntrypoints("betterend", BetterEndPlugin.class).forEach(BetterEndPlugin::register);
|
||||
Configs.saveConfigs();
|
||||
|
@ -88,6 +91,10 @@ public class BetterEnd implements ModInitializer {
|
|||
return FabricLoader.getInstance().isModLoaded("patchouli");
|
||||
}
|
||||
|
||||
public static boolean hasHydrogen() {
|
||||
return hasHydrogen;
|
||||
}
|
||||
|
||||
public static ResourceLocation makeID(String path) {
|
||||
return new ResourceLocation(MOD_ID, path);
|
||||
}
|
||||
|
|
25
src/main/java/ru/betterend/blocks/LucerniaSaplingBlock.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import ru.betterend.blocks.basis.FeatureSaplingBlock;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
|
||||
public class LucerniaSaplingBlock extends FeatureSaplingBlock {
|
||||
public LucerniaSaplingBlock() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Feature<?> getFeature() {
|
||||
return EndFeatures.LUCERNIA.getFeature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
|
||||
return world.getBlockState(pos.below()).is(EndBlocks.RUTISCUS);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ public class TenaneaFlowersBlock extends VineBlock implements IColorProvider {
|
|||
@Override
|
||||
public BlockColor getProvider() {
|
||||
return (state, world, pos, tintIndex) -> {
|
||||
if (pos == null) pos = BlockPos.ZERO;
|
||||
long i = (MHelper.getRandom(pos.getX(), pos.getZ()) & 63) + pos.getY();
|
||||
double delta = i * 0.1;
|
||||
int index = MHelper.floor(delta);
|
||||
|
|
|
@ -15,11 +15,11 @@ public class TenaneaSaplingBlock extends FeatureSaplingBlock {
|
|||
|
||||
@Override
|
||||
protected Feature<?> getFeature() {
|
||||
return EndFeatures.LUCERNIA.getFeature();
|
||||
return EndFeatures.TENANEA.getFeature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
|
||||
return world.getBlockState(pos.below()).is(EndBlocks.RUTISCUS);
|
||||
return world.getBlockState(pos.below()).is(EndBlocks.PINK_MOSS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ru.betterend.blocks.basis;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
|
@ -9,29 +11,32 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.core.Registry;
|
||||
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.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.BonemealableBlock;
|
||||
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.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 ru.betterend.client.render.ERenderLayer;
|
||||
import ru.betterend.interfaces.IRenderTypeable;
|
||||
import ru.betterend.patterns.BlockPatterned;
|
||||
import ru.betterend.patterns.Patterns;
|
||||
import ru.betterend.registry.EndTags;
|
||||
|
||||
public abstract class FeatureSaplingBlock extends BlockBaseNotFull implements BonemealableBlock, IRenderTypeable {
|
||||
public abstract class FeatureSaplingBlock extends SaplingBlock implements IRenderTypeable, BlockPatterned {
|
||||
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
|
||||
|
||||
public FeatureSaplingBlock() {
|
||||
super(FabricBlockSettings.of(Material.PLANT)
|
||||
super(null, FabricBlockSettings.of(Material.PLANT)
|
||||
.breakByHand(true)
|
||||
.collidable(false)
|
||||
.instabreak()
|
||||
|
@ -40,7 +45,7 @@ public abstract class FeatureSaplingBlock extends BlockBaseNotFull implements Bo
|
|||
}
|
||||
|
||||
public FeatureSaplingBlock(int light) {
|
||||
super(FabricBlockSettings.of(Material.PLANT)
|
||||
super(null, FabricBlockSettings.of(Material.PLANT)
|
||||
.breakByHand(true)
|
||||
.collidable(false)
|
||||
.luminance(light)
|
||||
|
@ -51,6 +56,11 @@ public abstract class FeatureSaplingBlock extends BlockBaseNotFull implements Bo
|
|||
|
||||
protected abstract Feature<?> getFeature();
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
|
||||
return SHAPE;
|
||||
|
@ -69,21 +79,21 @@ public abstract class FeatureSaplingBlock extends BlockBaseNotFull implements Bo
|
|||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) {
|
||||
return random.nextInt(16) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performBonemeal(ServerLevel world, Random random, BlockPos pos, BlockState state) {
|
||||
public void advanceTree(ServerLevel world, BlockPos pos, BlockState blockState, Random random) {
|
||||
getFeature().place(world, world.getChunkSource().getGenerator(), random, pos, null);
|
||||
}
|
||||
|
||||
@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);
|
||||
|
|
|
@ -49,7 +49,7 @@ public class MetalMaterial {
|
|||
public final Block block;
|
||||
public final Block tile;
|
||||
public final Block bars;
|
||||
public final Block plate;
|
||||
public final Block pressurePlate;
|
||||
public final Block door;
|
||||
public final Block trapdoor;
|
||||
public final Block anvil;
|
||||
|
@ -78,6 +78,7 @@ public class MetalMaterial {
|
|||
public final Item hoe;
|
||||
public final Item hammer;
|
||||
|
||||
public final Item forgedPlate;
|
||||
public final Item helmet;
|
||||
public final Item chestplate;
|
||||
public final Item leggings;
|
||||
|
@ -113,7 +114,7 @@ public class MetalMaterial {
|
|||
anvil = EndBlocks.registerBlock(name + "_anvil", new EndAnvilBlock(block.defaultMaterialColor(), level));
|
||||
bars = EndBlocks.registerBlock(name + "_bars", new EndMetalPaneBlock(block));
|
||||
chain = EndBlocks.registerBlock(name + "_chain", new EndChainBlock(block.defaultMaterialColor()));
|
||||
plate = EndBlocks.registerBlock(name + "_plate", new EndWoodenPlateBlock(block));
|
||||
pressurePlate = EndBlocks.registerBlock(name + "_plate", new EndWoodenPlateBlock(block));
|
||||
|
||||
chandelier = EndBlocks.registerBlock(name + "_chandelier", new ChandelierBlock(block));
|
||||
bulb_lantern = EndBlocks.registerBlock(name + "_bulb_lantern", new BulbVineLanternBlock(lanternProperties));
|
||||
|
@ -136,6 +137,7 @@ public class MetalMaterial {
|
|||
hoe = EndItems.registerTool(name + "_hoe", new EndHoeItem(material, -3, 0.0F, itemSettings));
|
||||
hammer = EndItems.registerTool(name + "_hammer", new EndHammerItem(material, 5.0F, -3.2F, 0.3D, itemSettings));
|
||||
|
||||
forgedPlate = EndItems.registerItem(name + "_forged_plate");
|
||||
helmet = EndItems.registerItem(name + "_helmet", new EndArmorItem(armor, EquipmentSlot.HEAD, itemSettings));
|
||||
chestplate = EndItems.registerItem(name + "_chestplate", new EndArmorItem(armor, EquipmentSlot.CHEST, itemSettings));
|
||||
leggings = EndItems.registerItem(name + "_leggings", new EndArmorItem(armor, EquipmentSlot.LEGS, itemSettings));
|
||||
|
@ -148,13 +150,14 @@ public class MetalMaterial {
|
|||
|
||||
// Basic recipes
|
||||
GridRecipe.make(name + "_ingot_from_nuggets", ingot).setShape("###", "###", "###").addMaterial('#', nugget).setGroup("end_metal_ingots_nug").build();
|
||||
GridRecipe.make(name + "_nuggets_from_ingot", nugget).setOutputCount(9).setList("#").addMaterial('#', ingot).setGroup("end_metal_nuggets_ing").build();
|
||||
GridRecipe.make(name + "_block", block).setShape("###", "###", "###").addMaterial('#', ingot).setGroup("end_metal_blocks").build();
|
||||
GridRecipe.make(name + "_ingot_from_block", ingot).setOutputCount(9).setList("#").addMaterial('#', block).setGroup("end_metal_ingots").build();
|
||||
|
||||
// Block recipes
|
||||
GridRecipe.make(name + "_tile", tile).setOutputCount(4).setShape("##", "##").addMaterial('#', block).setGroup("end_metal_tiles").build();
|
||||
GridRecipe.make(name + "_bars", bars).setOutputCount(16).setShape("###", "###").addMaterial('#', ingot).setGroup("end_metal_bars").build();
|
||||
GridRecipe.make(name + "_plate", plate).setShape("##").addMaterial('#', ingot).setGroup("end_metal_plates").build();
|
||||
GridRecipe.make(name + "_pressure_plate", pressurePlate).setShape("##").addMaterial('#', ingot).setGroup("end_metal_plates").build();
|
||||
GridRecipe.make(name + "_door", door).setOutputCount(3).setShape("##", "##", "##").addMaterial('#', ingot).setGroup("end_metal_doors").build();
|
||||
GridRecipe.make(name + "_trapdoor", trapdoor).setShape("##", "##").addMaterial('#', ingot).setGroup("end_metal_trapdoors").build();
|
||||
GridRecipe.make(name + "_stairs", stairs).setOutputCount(4).setShape("# ", "## ", "###").addMaterial('#', block, tile).setGroup("end_metal_stairs").build();
|
||||
|
@ -182,6 +185,7 @@ public class MetalMaterial {
|
|||
AnvilRecipe.Builder.create(name + "_axe_head").setInput(ingot).setInputCount(3).setOutput(axeHead).setAnvilLevel(level).setToolLevel(level).setDamage(level).build();
|
||||
AnvilRecipe.Builder.create(name + "_hoe_head").setInput(ingot).setInputCount(2).setOutput(hoeHead).setAnvilLevel(level).setToolLevel(level).setDamage(level).build();
|
||||
AnvilRecipe.Builder.create(name + "_sword_blade").setInput(ingot).setOutput(swordBlade).setAnvilLevel(level).setToolLevel(level).setDamage(level).build();
|
||||
AnvilRecipe.Builder.create(name + "_forged_plate").setInput(ingot).setOutput(forgedPlate).setAnvilLevel(level).setToolLevel(level).setDamage(level).build();
|
||||
|
||||
// Tools from parts
|
||||
SmithingTableRecipe.create(name + "_hammer").setResult(hammer).setBase(block).setAddition(Items.STICK).build();
|
||||
|
@ -193,10 +197,10 @@ public class MetalMaterial {
|
|||
SmithingTableRecipe.create(name + "_shovel").setResult(shovel).setBase(shovelHead).setAddition(Items.STICK).build();
|
||||
|
||||
// Armor crafting
|
||||
GridRecipe.make(name + "_helmet", helmet).setShape("###", "# #").addMaterial('#', ingot).setGroup("end_metal_helmets").build();
|
||||
GridRecipe.make(name + "_chestplate", chestplate).setShape("# #", "###", "###").addMaterial('#', ingot).setGroup("end_metal_chestplates").build();
|
||||
GridRecipe.make(name + "_leggings", leggings).setShape("###", "# #", "# #").addMaterial('#', ingot).setGroup("end_metal_leggings").build();
|
||||
GridRecipe.make(name + "_boots", boots).setShape("# #", "# #").addMaterial('#', ingot).setGroup("end_metal_boots").build();
|
||||
GridRecipe.make(name + "_helmet", helmet).setShape("###", "# #").addMaterial('#', forgedPlate).setGroup("end_metal_helmets").build();
|
||||
GridRecipe.make(name + "_chestplate", chestplate).setShape("# #", "###", "###").addMaterial('#', forgedPlate).setGroup("end_metal_chestplates").build();
|
||||
GridRecipe.make(name + "_leggings", leggings).setShape("###", "# #", "# #").addMaterial('#', forgedPlate).setGroup("end_metal_leggings").build();
|
||||
GridRecipe.make(name + "_boots", boots).setShape("# #", "# #").addMaterial('#', forgedPlate).setGroup("end_metal_boots").build();
|
||||
|
||||
TagHelper.addTag(BlockTags.ANVIL, anvil);
|
||||
TagHelper.addTag(BlockTags.BEACON_BASE_BLOCKS, block);
|
||||
|
|
|
@ -7,6 +7,8 @@ import net.minecraft.core.Registry;
|
|||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.client.render.ERenderLayer;
|
||||
import ru.betterend.interfaces.IRenderTypeable;
|
||||
import ru.betterend.interfaces.MultiModelItem;
|
||||
import ru.betterend.item.CrystaliteArmor;
|
||||
import ru.betterend.registry.EndBlockEntityRenders;
|
||||
import ru.betterend.registry.EndEntitiesRenders;
|
||||
import ru.betterend.registry.EndModelProviders;
|
||||
|
@ -23,6 +25,8 @@ public class BetterEndClient implements ClientModInitializer {
|
|||
EndParticles.register();
|
||||
EndEntitiesRenders.register();
|
||||
EndModelProviders.register();
|
||||
MultiModelItem.register();
|
||||
CrystaliteArmor.registerTooltips();
|
||||
ClientOptions.init();
|
||||
|
||||
if (BetterEnd.isDevEnvironment()) {
|
||||
|
|
|
@ -16,7 +16,7 @@ public class EndPotions {
|
|||
public final static Potion LONG_END_VEIL = registerPotion("long_end_veil", EndStatusEffects.END_VEIL, 9600);
|
||||
|
||||
public static Potion registerPotion(String name, MobEffect effect, int duration) {
|
||||
return registerPotion(name, new Potion(name, new MobEffectInstance[]{ new MobEffectInstance(effect, duration) }));
|
||||
return registerPotion(name, new Potion(name, new MobEffectInstance(effect, duration)));
|
||||
}
|
||||
|
||||
public static Potion registerPotion(String name, Potion potion) {
|
||||
|
|
|
@ -2,10 +2,15 @@ package ru.betterend.effects;
|
|||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.effects.status.EndVeilEffect;
|
||||
|
||||
public class EndStatusEffects {
|
||||
public final static MobEffectInstance CRYSTALITE_HEALTH_REGEN = new MobEffectInstance(MobEffects.REGENERATION, 40, 0, true, false, true);
|
||||
public final static MobEffectInstance CRYSTALITE_DIG_SPEED = new MobEffectInstance(MobEffects.DIG_SPEED, 40, 0, true, false, true);
|
||||
public final static MobEffectInstance CRYSTALITE_MOVE_SPEED = new MobEffectInstance(MobEffects.MOVEMENT_SPEED, 40, 0, true, false, true);
|
||||
|
||||
public final static MobEffect END_VEIL = registerEffect("end_veil", new EndVeilEffect());
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.entity.AgableMob;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
|
@ -25,6 +24,7 @@ import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
|||
import net.minecraft.world.entity.ai.util.RandomPos;
|
||||
import net.minecraft.world.entity.animal.Animal;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
|
@ -57,8 +57,8 @@ public class DragonflyEntity extends Animal implements FlyingAnimal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Entity getLeashHolder() {
|
||||
return null;
|
||||
public boolean canBeLeashed(Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,7 +17,6 @@ import net.minecraft.sounds.SoundEvents;
|
|||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.AgableMob;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
|
@ -36,6 +35,7 @@ import net.minecraft.world.entity.ai.util.RandomPos;
|
|||
import net.minecraft.world.entity.animal.Animal;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
@ -82,8 +82,8 @@ public class SilkMothEntity extends Animal implements FlyingAnimal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Entity getLeashHolder() {
|
||||
return null;
|
||||
public boolean canBeLeashed(Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,9 +17,38 @@ public class NourishIntegration extends ModIntegration {
|
|||
Tag.Named<Item> protein = getItemTag("protein");
|
||||
Tag.Named<Item> sweets = getItemTag("sweets");
|
||||
|
||||
TagHelper.addTag(fats, EndItems.END_FISH_RAW, EndItems.END_FISH_COOKED);
|
||||
TagHelper.addTag(fruit, EndItems.SHADOW_BERRY_RAW, EndItems.SHADOW_BERRY_COOKED, EndItems.BLOSSOM_BERRY, EndItems.SHADOW_BERRY_JELLY, EndItems.SWEET_BERRY_JELLY);
|
||||
TagHelper.addTag(protein, EndItems.END_FISH_RAW, EndItems.END_FISH_COOKED);
|
||||
TagHelper.addTag(sweets, EndItems.SHADOW_BERRY_JELLY, EndItems.SWEET_BERRY_JELLY);
|
||||
TagHelper.addTag(
|
||||
fats,
|
||||
EndItems.END_FISH_RAW,
|
||||
EndItems.END_FISH_COOKED
|
||||
);
|
||||
TagHelper.addTag(
|
||||
fruit,
|
||||
EndItems.SHADOW_BERRY_RAW,
|
||||
EndItems.SHADOW_BERRY_COOKED,
|
||||
EndItems.BLOSSOM_BERRY,
|
||||
EndItems.SHADOW_BERRY_JELLY,
|
||||
EndItems.SWEET_BERRY_JELLY,
|
||||
EndItems.BLOSSOM_BERRY_JELLY,
|
||||
EndItems.AMBER_ROOT_RAW,
|
||||
EndItems.CHORUS_MUSHROOM_RAW,
|
||||
EndItems.CHORUS_MUSHROOM_COOKED,
|
||||
EndItems.BOLUX_MUSHROOM_COOKED
|
||||
);
|
||||
TagHelper.addTag(
|
||||
protein,
|
||||
EndItems.END_FISH_RAW,
|
||||
EndItems.END_FISH_COOKED,
|
||||
EndItems.CHORUS_MUSHROOM_COOKED,
|
||||
EndItems.BOLUX_MUSHROOM_COOKED,
|
||||
EndItems.CAVE_PUMPKIN_PIE
|
||||
);
|
||||
TagHelper.addTag(
|
||||
sweets,
|
||||
EndItems.SHADOW_BERRY_JELLY,
|
||||
EndItems.SWEET_BERRY_JELLY,
|
||||
EndItems.BLOSSOM_BERRY_JELLY,
|
||||
EndItems.CAVE_PUMPKIN_PIE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
public interface BreakableItem {
|
||||
void registerBrokenItem();
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public interface MobEffectApplier {
|
||||
void applyEffect(LivingEntity owner);
|
||||
}
|
18
src/main/java/ru/betterend/interfaces/MultiModelItem.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
public interface MultiModelItem {
|
||||
@Environment(EnvType.CLIENT)
|
||||
void registerModelPredicate();
|
||||
|
||||
static void register() {
|
||||
EndItems.getModItems().forEach(item -> {
|
||||
if (item instanceof MultiModelItem) {
|
||||
((MultiModelItem) item).registerModelPredicate();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -2,18 +2,14 @@ package ru.betterend.item;
|
|||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.item.*;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.interfaces.BreakableItem;
|
||||
import ru.betterend.patterns.ModelProvider;
|
||||
import ru.betterend.patterns.Patterns;
|
||||
import ru.betterend.interfaces.MultiModelItem;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
75
src/main/java/ru/betterend/item/CrystaliteArmor.java
Normal file
|
@ -0,0 +1,75 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import ru.betterend.effects.EndStatusEffects;
|
||||
import ru.betterend.item.material.EndArmorMaterial;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
public class CrystaliteArmor extends EndArmorItem {
|
||||
|
||||
protected final static TranslatableComponent CHEST_DESC;
|
||||
protected final static TranslatableComponent BOOTS_DESC;
|
||||
|
||||
public CrystaliteArmor(EquipmentSlot equipmentSlot, Properties settings) {
|
||||
super(EndArmorMaterial.CRYSTALITE, equipmentSlot, settings);
|
||||
}
|
||||
|
||||
public static boolean hasFullSet(LivingEntity owner) {
|
||||
for (ItemStack armorStack : owner.getArmorSlots()) {
|
||||
if (!(armorStack.getItem() instanceof CrystaliteArmor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void applySetEffect(LivingEntity owner) {
|
||||
owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_HEALTH_REGEN));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void registerTooltips() {
|
||||
ItemTooltipCallback.EVENT.register((stack, context, lines) -> {
|
||||
if (stack.getItem() instanceof CrystaliteArmor) {
|
||||
boolean hasSet = false;
|
||||
Player owner = Minecraft.getInstance().player;
|
||||
if (owner != null) {
|
||||
hasSet = hasFullSet(owner);
|
||||
}
|
||||
|
||||
TranslatableComponent setDesc = new TranslatableComponent("tooltip.armor.crystalite_set");
|
||||
setDesc.setStyle(Style.EMPTY.applyFormats(hasSet ? ChatFormatting.BLUE : ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC));
|
||||
lines.add(TextComponent.EMPTY);
|
||||
lines.add(setDesc);
|
||||
|
||||
if (stack.getItem() == EndItems.CRYSTALITE_CHESTPLATE) {
|
||||
lines.add(1, TextComponent.EMPTY);
|
||||
lines.add(2, CHEST_DESC);
|
||||
} else if (stack.getItem() == EndItems.CRYSTALITE_BOOTS) {
|
||||
lines.add(1, TextComponent.EMPTY);
|
||||
lines.add(2, BOOTS_DESC);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static {
|
||||
Style descStyle = Style.EMPTY.applyFormats(ChatFormatting.DARK_AQUA, ChatFormatting.ITALIC);
|
||||
CHEST_DESC = new TranslatableComponent("tooltip.armor.crystalite_chest");
|
||||
CHEST_DESC.setStyle(descStyle);
|
||||
BOOTS_DESC = new TranslatableComponent("tooltip.armor.crystalite_boots");
|
||||
BOOTS_DESC.setStyle(descStyle);
|
||||
}
|
||||
}
|
21
src/main/java/ru/betterend/item/CrystaliteBoots.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.Rarity;
|
||||
import ru.betterend.effects.EndStatusEffects;
|
||||
import ru.betterend.interfaces.MobEffectApplier;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
public class CrystaliteBoots extends CrystaliteArmor implements MobEffectApplier {
|
||||
|
||||
public CrystaliteBoots() {
|
||||
super(EquipmentSlot.FEET, EndItems.makeItemSettings().rarity(Rarity.RARE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEffect(LivingEntity owner) {
|
||||
owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_MOVE_SPEED));
|
||||
}
|
||||
}
|
21
src/main/java/ru/betterend/item/CrystaliteChestplate.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.Rarity;
|
||||
import ru.betterend.effects.EndStatusEffects;
|
||||
import ru.betterend.interfaces.MobEffectApplier;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
public class CrystaliteChestplate extends CrystaliteArmor implements MobEffectApplier {
|
||||
|
||||
public CrystaliteChestplate() {
|
||||
super(EquipmentSlot.CHEST, EndItems.makeItemSettings().rarity(Rarity.RARE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEffect(LivingEntity owner) {
|
||||
owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_DIG_SPEED));
|
||||
}
|
||||
}
|
18
src/main/java/ru/betterend/item/CrystaliteHelmet.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.item.Rarity;
|
||||
import ru.betterend.registry.EndAttributes;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CrystaliteHelmet extends CrystaliteArmor {
|
||||
|
||||
public CrystaliteHelmet() {
|
||||
super(EquipmentSlot.HEAD, EndItems.makeItemSettings().rarity(Rarity.RARE));
|
||||
UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[EquipmentSlot.HEAD.getIndex()];
|
||||
addAttributeModifier(EndAttributes.BLINDNESS_RESISTANCE, new AttributeModifier(uuid, "Helmet blindness resistance", 1.0, AttributeModifier.Operation.ADDITION));
|
||||
}
|
||||
}
|
18
src/main/java/ru/betterend/item/CrystaliteLeggings.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.item.Rarity;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CrystaliteLeggings extends CrystaliteArmor {
|
||||
|
||||
public CrystaliteLeggings() {
|
||||
super(EquipmentSlot.LEGS, EndItems.makeItemSettings().rarity(Rarity.RARE));
|
||||
UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[EquipmentSlot.LEGS.getIndex()];
|
||||
addAttributeModifier(Attributes.MAX_HEALTH, new AttributeModifier(uuid, "Armor health boost", 4.0, AttributeModifier.Operation.ADDITION));
|
||||
}
|
||||
}
|
|
@ -1,25 +1,19 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.ArmorMaterial;
|
||||
import net.minecraft.world.item.Item;
|
||||
import ru.betterend.mixin.common.ArmorItemAccessor;
|
||||
import ru.betterend.patterns.ModelProvider;
|
||||
import ru.betterend.patterns.Patterned;
|
||||
import ru.betterend.patterns.Patterns;
|
||||
|
||||
public class EndArmorItem extends ArmorItem implements ModelProvider {
|
||||
import java.util.UUID;
|
||||
|
||||
public class EndArmorItem extends ArmorItem implements Patterned {
|
||||
|
||||
protected static final UUID[] ARMOR_MODIFIER_UUID_PER_SLOT = new UUID[] {
|
||||
UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B"),
|
||||
|
@ -54,7 +48,7 @@ public class EndArmorItem extends ArmorItem implements ModelProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getModelString(String name) {
|
||||
public String getModelPattern(String name) {
|
||||
return Patterns.createItemGenerated(name);
|
||||
}
|
||||
}
|
||||
|
|
10
src/main/java/ru/betterend/item/EndAttribute.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||
|
||||
public class EndAttribute extends Attribute {
|
||||
|
||||
public EndAttribute(String description, double value) {
|
||||
super(description, value);
|
||||
}
|
||||
}
|
|
@ -1,18 +1,19 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.world.item.BucketItem;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.item.FishBucketItem;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import ru.betterend.patterns.ModelProvider;
|
||||
import ru.betterend.patterns.Patterned;
|
||||
import ru.betterend.patterns.Patterns;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
public class EndBucketItem extends BucketItem implements ModelProvider {
|
||||
public EndBucketItem() {
|
||||
super(Fluids.WATER, EndItems.makeItemSettings().stacksTo(1));
|
||||
public class EndBucketItem extends FishBucketItem implements Patterned {
|
||||
public EndBucketItem(EntityType<?> type) {
|
||||
super(type, Fluids.WATER, EndItems.makeItemSettings().stacksTo(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModelString(String name) {
|
||||
public String getModelPattern(String name) {
|
||||
return Patterns.createJson(Patterns.ITEM_GENERATED, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package ru.betterend.mixin.client;
|
||||
|
||||
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;
|
||||
|
||||
import net.minecraft.client.model.ArmorStandArmorModel;
|
||||
import net.minecraft.client.renderer.entity.ArmorStandRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
import net.minecraft.world.entity.decoration.ArmorStand;
|
||||
import ru.betterend.client.render.ArmoredElytraLayer;
|
||||
|
||||
@Mixin(ArmorStandRenderer.class)
|
||||
public abstract class ArmorStandRendererMixin extends LivingEntityRenderer<ArmorStand, ArmorStandArmorModel> {
|
||||
|
||||
public ArmorStandRendererMixin(EntityRenderDispatcher entityRenderDispatcher, ArmorStandArmorModel entityModel, float f) {
|
||||
super(entityRenderDispatcher, entityModel, f);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>*", at = @At("TAIL"))
|
||||
public void be_addCustomLayer(EntityRenderDispatcher entityRenderDispatcher, CallbackInfo info) {
|
||||
addLayer(new ArmoredElytraLayer<>(this));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package ru.betterend.mixin.client;
|
||||
|
||||
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;
|
||||
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.HumanoidMobRenderer;
|
||||
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import ru.betterend.client.render.ArmoredElytraLayer;
|
||||
|
||||
@Mixin(HumanoidMobRenderer.class)
|
||||
public abstract class HumanoidMobRendererMixin<T extends Mob, M extends HumanoidModel<T>> extends MobRenderer<T, M> {
|
||||
|
||||
public HumanoidMobRendererMixin(EntityRenderDispatcher entityRenderDispatcher, M entityModel, float f) {
|
||||
super(entityRenderDispatcher, entityModel, f);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>*", at = @At("TAIL"))
|
||||
public void be_addCustomLayer(EntityRenderDispatcher entityRenderDispatcher, M humanoidModel, float f, float g, float h, float i, CallbackInfo info) {
|
||||
addLayer(new ArmoredElytraLayer<>(this));
|
||||
}
|
||||
}
|
|
@ -21,6 +21,6 @@ public abstract class PlayerRendererMixin extends LivingEntityRenderer<AbstractC
|
|||
|
||||
@Inject(method = "<init>(Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;Z)V", at = @At("TAIL"))
|
||||
public void be_addCustomLayer(EntityRenderDispatcher entityRenderDispatcher, boolean bl, CallbackInfo info) {
|
||||
addLayer(new ArmoredElytraLayer<>(PlayerRenderer.class.cast(this)));
|
||||
addLayer(new ArmoredElytraLayer<>(this));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
|
||||
@Mixin(ArmorItem.class)
|
||||
public interface ArmorItemAccessor {
|
||||
@Accessor("ARMOR_MODIFIER_UUID_PER_SLOT")
|
||||
UUID[] be_getModifiers();
|
||||
|
||||
@Accessor("defaultModifiers")
|
||||
Multimap<Attribute, AttributeModifier> be_getDefaultModifiers();
|
||||
|
||||
@Accessor("defaultModifiers")
|
||||
void be_setDefaultModifiers(Multimap<Attribute, AttributeModifier> attributeModifiers);
|
||||
}
|
|
@ -1,13 +1,17 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
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 ru.betterend.BetterEnd;
|
||||
import ru.betterend.interfaces.IBiomeArray;
|
||||
|
||||
@Mixin(ChunkBiomeContainer.class)
|
||||
|
@ -34,6 +38,42 @@ public class ChunkBiomeContainerMixin implements IBiomeArray {
|
|||
int biomeY = pos.getY() >> 2;
|
||||
int biomeZ = pos.getZ() >> 2;
|
||||
int index = be_getArrayIndex(biomeX, biomeY, biomeZ);
|
||||
|
||||
if (BetterEnd.hasHydrogen()) {
|
||||
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) {
|
||||
BetterEnd.LOGGER.warning(e.getLocalizedMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
biomes[index] = biome;
|
||||
}
|
||||
|
||||
|
@ -43,4 +83,37 @@ public class ChunkBiomeContainerMixin implements IBiomeArray {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
100
src/main/java/ru/betterend/mixin/common/EndDragonFightMixin.java
Normal file
|
@ -0,0 +1,100 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
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.CallbackInfo;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.pattern.BlockPattern;
|
||||
import net.minecraft.world.level.dimension.end.DragonRespawnAnimation;
|
||||
import net.minecraft.world.level.dimension.end.EndDragonFight;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import ru.betterend.util.BlocksHelper;
|
||||
import ru.betterend.world.generator.GeneratorOptions;
|
||||
|
||||
@Mixin(EndDragonFight.class)
|
||||
public class EndDragonFightMixin {
|
||||
@Shadow
|
||||
private DragonRespawnAnimation respawnStage;
|
||||
@Shadow
|
||||
private boolean dragonKilled;
|
||||
@Shadow
|
||||
private BlockPos portalLocation;
|
||||
@Final
|
||||
@Shadow
|
||||
private static Logger LOGGER;
|
||||
@Final
|
||||
@Shadow
|
||||
private ServerLevel level;
|
||||
|
||||
@Shadow
|
||||
private BlockPattern.BlockPatternMatch findExitPortal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Shadow
|
||||
private void spawnExitPortal(boolean bl) {}
|
||||
|
||||
@Shadow
|
||||
private void respawnDragon(List<EndCrystal> list) {}
|
||||
|
||||
@Inject(method = "tryRespawn", at = @At("HEAD"), cancellable = true)
|
||||
private void be_tryRespawnDragon(CallbackInfo info) {
|
||||
if (GeneratorOptions.replacePortal() && GeneratorOptions.hasDragonFights() && this.dragonKilled && this.respawnStage == null) {
|
||||
BlockPos blockPos = portalLocation;
|
||||
if (blockPos == null) {
|
||||
LOGGER.debug("Tried to respawn, but need to find the portal first.");
|
||||
BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal();
|
||||
if (blockPatternMatch == null) {
|
||||
LOGGER.debug("Couldn't find a portal, so we made one.");
|
||||
spawnExitPortal(true);
|
||||
}
|
||||
else {
|
||||
LOGGER.debug("Found the exit portal & temporarily using it.");
|
||||
}
|
||||
|
||||
blockPos = portalLocation;
|
||||
}
|
||||
|
||||
List<EndCrystal> crystals = Lists.newArrayList();
|
||||
BlockPos center = GeneratorOptions.getPortalPos().above(5);
|
||||
for (Direction dir : BlocksHelper.HORIZONTAL) {
|
||||
BlockPos central = center.relative(dir, 4);
|
||||
List<EndCrystal> crystalList = level.getEntitiesOfClass(EndCrystal.class, new AABB(central.below(10).south().west(), central.above(10).north().east()));
|
||||
|
||||
int count = crystalList.size();
|
||||
for (int n = 0; n < count; n++) {
|
||||
EndCrystal crystal = crystalList.get(n);
|
||||
if (!level.getBlockState(crystal.blockPosition().below()).is(Blocks.BEDROCK)) {
|
||||
crystalList.remove(n);
|
||||
count--;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
if (crystalList.isEmpty()) {
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
crystals.addAll(crystalList);
|
||||
}
|
||||
|
||||
LOGGER.debug("Found all crystals, respawning dragon.");
|
||||
respawnDragon(crystals);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.feature.EndPodiumFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
@ -40,7 +41,7 @@ public class EndPodiumFeatureMixin {
|
|||
blockPos = be_updatePos(blockPos, world);
|
||||
StructureTemplate structure = StructureHelper.readStructure(BetterEnd.makeID(active ? "portal/end_portal_active" : "portal/end_portal_inactive"));
|
||||
BlockPos size = structure.getSize();
|
||||
blockPos = blockPos.offset(-(size.getX() >> 1), -3, -(size.getZ() >> 1));
|
||||
blockPos = blockPos.offset(-(size.getX() >> 1), -1, -(size.getZ() >> 1));
|
||||
structure.placeInWorldChunk(world, blockPos, new StructurePlaceSettings(), random);
|
||||
info.setReturnValue(true);
|
||||
info.cancel();
|
||||
|
@ -56,7 +57,7 @@ public class EndPodiumFeatureMixin {
|
|||
if (GeneratorOptions.useNewGenerator()) {
|
||||
BlockPos pos = GeneratorOptions.getPortalPos();
|
||||
if (pos.equals(BlockPos.ZERO)) {
|
||||
int y = world.getChunk(blockPos).getHeight(Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ());
|
||||
int y = world.getChunk(0, 0, ChunkStatus.FULL).getHeight(Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ());
|
||||
if (y < 1) {
|
||||
y = 65;
|
||||
}
|
||||
|
|
43
src/main/java/ru/betterend/mixin/common/EndSpikeMixin.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
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 net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.levelgen.feature.SpikeFeature.EndSpike;
|
||||
import ru.betterend.util.WorldDataUtil;
|
||||
import ru.betterend.world.generator.GeneratorOptions;
|
||||
|
||||
@Mixin(EndSpike.class)
|
||||
public class EndSpikeMixin {
|
||||
@Final
|
||||
@Shadow
|
||||
private int height;
|
||||
|
||||
@Inject(method = "getHeight", at = @At("HEAD"), cancellable = true)
|
||||
private void be_getSpikeHeight(CallbackInfoReturnable<Integer> info) {
|
||||
if (!GeneratorOptions.isDirectSpikeHeight()) {
|
||||
int x = getCenterX();
|
||||
int z = getCenterZ();
|
||||
String pillarID = String.format("%d_%d", x, z);
|
||||
CompoundTag pillar = WorldDataUtil.getCompoundTag("pillars");
|
||||
int minY = pillar.contains(pillarID) ? pillar.getInt(pillarID) : 65;
|
||||
int maxY = minY + height - 54;
|
||||
info.setReturnValue(maxY);
|
||||
}
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public int getCenterX() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public int getCenterZ() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,22 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.*;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeMap;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.item.ElytraItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
@ -10,26 +25,12 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.MoverType;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.item.ElytraItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import ru.betterend.interfaces.MobEffectApplier;
|
||||
import ru.betterend.item.ArmoredElytra;
|
||||
import ru.betterend.item.CrystaliteArmor;
|
||||
import ru.betterend.registry.EndAttributes;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public abstract class LivingEntityMixin extends Entity {
|
||||
|
@ -56,8 +57,38 @@ public abstract class LivingEntityMixin extends Entity {
|
|||
@Shadow
|
||||
public abstract boolean isFallFlying();
|
||||
|
||||
@Shadow
|
||||
public abstract AttributeMap getAttributes();
|
||||
|
||||
private Entity lastAttacker;
|
||||
|
||||
@Inject(method = "createLivingAttributes", at = @At("RETURN"), cancellable = true)
|
||||
private static void be_addLivingAttributes(CallbackInfoReturnable<AttributeSupplier.Builder> info) {
|
||||
EndAttributes.addLivingEntityAttributes(info.getReturnValue());
|
||||
}
|
||||
|
||||
@Inject(method = "tickEffects", at = @At("HEAD"))
|
||||
protected void be_applyEffects(CallbackInfo info) {
|
||||
if (!level.isClientSide()) {
|
||||
LivingEntity owner = LivingEntity.class.cast(this);
|
||||
if (CrystaliteArmor.hasFullSet(owner)) {
|
||||
CrystaliteArmor.applySetEffect(owner);
|
||||
}
|
||||
getArmorSlots().forEach(itemStack -> {
|
||||
if (itemStack.getItem() instanceof MobEffectApplier) {
|
||||
((MobEffectApplier) itemStack.getItem()).applyEffect(owner);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "canBeAffected", at = @At("HEAD"), cancellable = true)
|
||||
public void be_canBeAffected(MobEffectInstance mobEffectInstance, CallbackInfoReturnable<Boolean> info) {
|
||||
if (mobEffectInstance.getEffect() == MobEffects.BLINDNESS && getAttributes().getValue(EndAttributes.BLINDNESS_RESISTANCE) > 0.0) {
|
||||
info.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "hurt", at = @At("HEAD"))
|
||||
public void be_hurt(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
|
||||
this.lastAttacker = source.getEntity();
|
||||
|
@ -80,9 +111,8 @@ public abstract class LivingEntityMixin extends Entity {
|
|||
if (isFlying && !onGround && !isPassenger() && !hasEffect(MobEffects.LEVITATION)) {
|
||||
if (ElytraItem.isFlyEnabled(itemStack)) {
|
||||
if ((fallFlyTicks + 1) % 20 == 0) {
|
||||
itemStack.hurtAndBreak(1, LivingEntity.class.cast(this), (livingEntity) -> {
|
||||
livingEntity.broadcastBreakEvent(EquipmentSlot.CHEST);
|
||||
});
|
||||
itemStack.hurtAndBreak(1, LivingEntity.class.cast(this),
|
||||
livingEntity -> livingEntity.broadcastBreakEvent(EquipmentSlot.CHEST));
|
||||
}
|
||||
isFlying = true;
|
||||
} else {
|
||||
|
|
|
@ -4,10 +4,12 @@ import java.io.File;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
|
@ -17,35 +19,47 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.level.CustomSpawner;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.ServerLevelData;
|
||||
import net.minecraft.world.level.storage.WritableLevelData;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.registry.EndBiomes;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.util.DataFixerUtil;
|
||||
import ru.betterend.util.WorldDataUtil;
|
||||
import ru.betterend.world.generator.GeneratorOptions;
|
||||
|
||||
@Mixin(ServerLevel.class)
|
||||
public class ServerLevelMixin {
|
||||
private static final int DEV_VERSION = be_getVersionInt("63.63.63");
|
||||
private static final int FIX_VERSION = DEV_VERSION;
|
||||
private static String lastWorld = null;
|
||||
public abstract class ServerLevelMixin extends Level {
|
||||
private static final int BE_DEV_VERSION = be_getVersionInt("63.63.63");
|
||||
private static final int BE_FIX_VERSION = BE_DEV_VERSION;
|
||||
private static String be_lastWorld = null;
|
||||
|
||||
protected ServerLevelMixin(WritableLevelData writableLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l) {
|
||||
super(writableLevelData, resourceKey, dimensionType, supplier, bl, bl2, l);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>*", at = @At("TAIL"))
|
||||
private void be_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) {
|
||||
if (lastWorld != null && lastWorld.equals(session.getLevelId())) {
|
||||
if (be_lastWorld != null && be_lastWorld.equals(session.getLevelId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastWorld = session.getLevelId();
|
||||
be_lastWorld = session.getLevelId();
|
||||
|
||||
ServerLevel world = ServerLevel.class.cast(this);
|
||||
EndBiomes.onWorldLoad(world.getSeed());
|
||||
File dir = session.getDimensionPath(world.dimension());
|
||||
if (!new File(dir, "level.dat").exists()) {
|
||||
dir = dir.getParentFile();
|
||||
|
@ -53,7 +67,7 @@ public class ServerLevelMixin {
|
|||
File data = new File(dir, "data/betterend_data.nbt");
|
||||
|
||||
ModMetadata meta = FabricLoader.getInstance().getModContainer(BetterEnd.MOD_ID).get().getMetadata();
|
||||
int version = BetterEnd.isDevEnvironment() ? DEV_VERSION : be_getVersionInt(meta.getVersion().toString());
|
||||
int version = BetterEnd.isDevEnvironment() ? BE_DEV_VERSION : be_getVersionInt(meta.getVersion().toString());
|
||||
|
||||
WorldDataUtil.load(data);
|
||||
CompoundTag root = WorldDataUtil.getRootTag();
|
||||
|
@ -61,7 +75,7 @@ public class ServerLevelMixin {
|
|||
GeneratorOptions.setPortalPos(NbtUtils.readBlockPos(root.getCompound("portal")));
|
||||
|
||||
if (dataVersion < version) {
|
||||
if (version < FIX_VERSION) {
|
||||
if (version < BE_FIX_VERSION) {
|
||||
DataFixerUtil.fixData(data.getParentFile());
|
||||
}
|
||||
root.putString("version", be_getVersionString(version));
|
||||
|
@ -79,6 +93,23 @@ public class ServerLevelMixin {
|
|||
}
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
method = "tickChunk",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z"
|
||||
)
|
||||
)
|
||||
private BlockState be_modifyTickState(BlockPos pos, BlockState state) {
|
||||
if (state.is(Blocks.ICE)) {
|
||||
ResourceLocation biome = EndBiomes.getBiomeID(getBiome(pos));
|
||||
if (biome.getNamespace().equals(BetterEnd.MOD_ID)) {
|
||||
state = EndBlocks.EMERALD_ICE.defaultBlockState();
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
private static int be_getVersionInt(String version) {
|
||||
if (version.isEmpty()) {
|
||||
return 0;
|
||||
|
|
|
@ -63,6 +63,7 @@ public class SpikeFeatureMixin {
|
|||
minY = world.getChunk(x >> 4, z >> 4).getHeight(Types.WORLD_SURFACE, x & 15, z);
|
||||
}
|
||||
|
||||
GeneratorOptions.setDirectSpikeHeight();
|
||||
int maxY = minY + spike.getHeight() - 64;
|
||||
|
||||
if (GeneratorOptions.replacePillars() && be_radiusInRange(radius)) {
|
||||
|
|
|
@ -63,5 +63,12 @@ public class AnvilRecipes {
|
|||
.setToolLevel(4)
|
||||
.setDamage(6)
|
||||
.build();
|
||||
AnvilRecipe.Builder.create("aeternium_forged_plate")
|
||||
.setInput(EndItems.AETERNIUM_INGOT)
|
||||
.setOutput(EndItems.AETERNIUM_FORGED_PLATE)
|
||||
.setAnvilLevel(anvilLevel)
|
||||
.setToolLevel(4)
|
||||
.setDamage(6)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,19 +101,27 @@ public class CraftingRecipes {
|
|||
GridRecipe.make("petal_white_dye", Items.WHITE_DYE).setList("#").addMaterial('#', EndItems.HYDRALUX_PETAL).build();
|
||||
|
||||
GridRecipe.make("sweet_berry_jelly", EndItems.SWEET_BERRY_JELLY)
|
||||
.setList("JWSB")
|
||||
.addMaterial('J', EndItems.GELATINE)
|
||||
.addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))
|
||||
.addMaterial('S', Items.SUGAR).addMaterial('B', Items.SWEET_BERRIES)
|
||||
.build();
|
||||
.setList("JWSB")
|
||||
.addMaterial('J', EndItems.GELATINE)
|
||||
.addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))
|
||||
.addMaterial('S', Items.SUGAR).addMaterial('B', Items.SWEET_BERRIES)
|
||||
.build();
|
||||
|
||||
GridRecipe.make("shadow_berry_jelly", EndItems.SHADOW_BERRY_JELLY)
|
||||
.setList("JWSB")
|
||||
.addMaterial('J', EndItems.GELATINE)
|
||||
.addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))
|
||||
.addMaterial('S', Items.SUGAR)
|
||||
.addMaterial('B', EndItems.SHADOW_BERRY_COOKED)
|
||||
.build();
|
||||
.setList("JWSB")
|
||||
.addMaterial('J', EndItems.GELATINE)
|
||||
.addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))
|
||||
.addMaterial('S', Items.SUGAR)
|
||||
.addMaterial('B', EndItems.SHADOW_BERRY_COOKED)
|
||||
.build();
|
||||
|
||||
GridRecipe.make("shadow_berry_jelly", EndItems.BLOSSOM_BERRY_JELLY)
|
||||
.setList("JWSB")
|
||||
.addMaterial('J', EndItems.GELATINE)
|
||||
.addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))
|
||||
.addMaterial('S', Items.SUGAR)
|
||||
.addMaterial('B', EndItems.BLOSSOM_BERRY)
|
||||
.build();
|
||||
|
||||
GridRecipe.make("sulphur_gunpowder", Items.GUNPOWDER).setList("SCB").addMaterial('S', EndItems.CRYSTALLINE_SULPHUR).addMaterial('C', Items.COAL, Items.CHARCOAL).addMaterial('B', Items.BONE_MEAL).build();
|
||||
|
||||
|
@ -188,11 +196,12 @@ public class CraftingRecipes {
|
|||
registerHammer("diamond", Items.DIAMOND, EndItems.DIAMOND_HAMMER);
|
||||
|
||||
GridRecipe.make("charcoal_block", EndBlocks.CHARCOAL_BLOCK).setShape("###", "###", "###").addMaterial('#', Items.CHARCOAL).build();
|
||||
GridRecipe.make("charcoal_from_block", Items.CHARCOAL).setOutputCount(9).setList("#").addMaterial('#', EndBlocks.CHARCOAL_BLOCK).build();
|
||||
GridRecipe.make("end_stone_furnace", EndBlocks.END_STONE_FURNACE).setShape("###", "# #", "###").addMaterial('#', Blocks.END_STONE).build();
|
||||
GridRecipe.make("filalux_lantern", EndBlocks.FILALUX_LANTERN).setShape("###", "###", "###").addMaterial('#', EndBlocks.FILALUX).build();
|
||||
|
||||
GridRecipe.make("silk_moth_hive", EndBlocks.SILK_MOTH_HIVE).setShape("#L#", "LML", "#L#").addMaterial('#', EndBlocks.TENANEA.planks).addMaterial('L', EndBlocks.TENANEA_LEAVES).addMaterial('M', EndItems.SILK_MOTH_MATRIX).build();
|
||||
GridRecipe.make("cave_pumpkin_pie", EndItems.CAVE_PUMPKIN_PIE).setShape(" B ", "BPB", " B ").addMaterial('P', EndBlocks.CAVE_PUMPKIN).addMaterial('B', EndItems.BLOSSOM_BERRY, EndItems.SHADOW_BERRY_RAW).build();
|
||||
GridRecipe.make("cave_pumpkin_pie", EndItems.CAVE_PUMPKIN_PIE).setShape("SBS", "BPB", "SBS").addMaterial('P', EndBlocks.CAVE_PUMPKIN).addMaterial('B', EndItems.BLOSSOM_BERRY, EndItems.SHADOW_BERRY_RAW).addMaterial('S', Items.SUGAR).build();
|
||||
GridRecipe.make("cave_pumpkin_seeds", EndBlocks.CAVE_PUMPKIN_SEED).setOutputCount(4).setList("#").addMaterial('#', EndBlocks.CAVE_PUMPKIN).build();
|
||||
|
||||
GridRecipe.make("neon_cactus_block", EndBlocks.NEON_CACTUS_BLOCK).setShape("##", "##").addMaterial('#', EndBlocks.NEON_CACTUS).build();
|
||||
|
@ -202,7 +211,7 @@ public class CraftingRecipes {
|
|||
GridRecipe.make("tag_smith_table", Blocks.SMITHING_TABLE).setShape("II", "##", "##").addMaterial('#', ItemTags.PLANKS).addMaterial('I', EndTags.IRON_INGOTS).build();
|
||||
GridRecipe.make("tag_cauldron", Blocks.CAULDRON).setShape("I I", "I I", "III").addMaterial('I', EndTags.IRON_INGOTS).build();
|
||||
GridRecipe.make("tag_hopper", Blocks.HOPPER).setShape("I I", "ICI", " I ").addMaterial('I', EndTags.IRON_INGOTS).addMaterial('C', EndTags.ITEM_CHEST).build();
|
||||
GridRecipe.make("tag_piston", Blocks.PISTON).setShape("WWW", "CIC", "CDC").addMaterial('I', EndTags.IRON_INGOTS).addMaterial('D', Items.REDSTONE).addMaterial('C', Items.COBBLESTONE).build();
|
||||
GridRecipe.make("tag_piston", Blocks.PISTON).setShape("WWW", "CIC", "CDC").addMaterial('I', EndTags.IRON_INGOTS).addMaterial('D', Items.REDSTONE).addMaterial('C', Items.COBBLESTONE).addMaterial('W', ItemTags.PLANKS).build();
|
||||
GridRecipe.make("tag_rail", Blocks.RAIL).setShape("I I", "ISI", "I I").addMaterial('I', EndTags.IRON_INGOTS).addMaterial('S', Items.STICK).build();
|
||||
GridRecipe.make("tag_stonecutter", Blocks.STONECUTTER).setShape(" I ", "SSS").addMaterial('I', EndTags.IRON_INGOTS).addMaterial('S', Items.STONE).build();
|
||||
|
||||
|
@ -210,6 +219,8 @@ public class CraftingRecipes {
|
|||
GridRecipe.make("tag_compass", Items.COMPASS).setShape(" I ", "IDI", " I ").addMaterial('I', EndTags.IRON_INGOTS).addMaterial('D', Items.REDSTONE).build();
|
||||
GridRecipe.make("tag_minecart", Items.MINECART).setShape("I I", "III").addMaterial('I', EndTags.IRON_INGOTS).build();
|
||||
GridRecipe.make("tag_shield", Items.SHIELD).setShape("WIW", "WWW", " W ").addMaterial('I', EndTags.IRON_INGOTS).addMaterial('W', ItemTags.PLANKS).build();
|
||||
|
||||
GridRecipe.make("sugar_from_root", Items.SUGAR).setList("###").addMaterial('#', EndItems.AMBER_ROOT_RAW).build();
|
||||
}
|
||||
|
||||
private static void registerLantern(String name, Block lantern, Block slab) {
|
||||
|
|
|
@ -54,22 +54,22 @@ public class SmithingRecipes {
|
|||
SmithingTableRecipe.create("aeternium_helmet")
|
||||
.setResult(EndItems.AETERNIUM_HELMET)
|
||||
.setBase(EndBlocks.TERMINITE.helmet)
|
||||
.setAddition(EndItems.AETERNIUM_INGOT)
|
||||
.setAddition(EndItems.AETERNIUM_FORGED_PLATE)
|
||||
.build();
|
||||
SmithingTableRecipe.create("aeternium_chestplate")
|
||||
.setResult(EndItems.AETERNIUM_CHESTPLATE)
|
||||
.setBase(EndBlocks.TERMINITE.chestplate)
|
||||
.setAddition(EndItems.AETERNIUM_INGOT)
|
||||
.setAddition(EndItems.AETERNIUM_FORGED_PLATE)
|
||||
.build();
|
||||
SmithingTableRecipe.create("aeternium_leggings")
|
||||
.setResult(EndItems.AETERNIUM_LEGGINGS)
|
||||
.setBase(EndBlocks.TERMINITE.leggings)
|
||||
.setAddition(EndItems.AETERNIUM_INGOT)
|
||||
.setAddition(EndItems.AETERNIUM_FORGED_PLATE)
|
||||
.build();
|
||||
SmithingTableRecipe.create("aeternium_boots")
|
||||
.setResult(EndItems.AETERNIUM_BOOTS)
|
||||
.setBase(EndBlocks.TERMINITE.boots)
|
||||
.setAddition(EndItems.AETERNIUM_INGOT)
|
||||
.setAddition(EndItems.AETERNIUM_FORGED_PLATE)
|
||||
.build();
|
||||
|
||||
SmithingTableRecipe.create("thallasium_anvil_updrade")
|
||||
|
@ -80,7 +80,7 @@ public class SmithingRecipes {
|
|||
SmithingTableRecipe.create("terminite_anvil_updrade")
|
||||
.setResult(EndBlocks.AETERNIUM_ANVIL)
|
||||
.setBase(EndBlocks.TERMINITE.anvil)
|
||||
.setAddition(EndBlocks.AETERNIUM_BLOCK)
|
||||
.setAddition(EndItems.AETERNIUM_INGOT)
|
||||
.build();
|
||||
|
||||
SmithingTableRecipe.create("armored_elytra")
|
||||
|
|
21
src/main/java/ru/betterend/registry/EndAttributes.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package ru.betterend.registry;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.item.EndAttribute;
|
||||
|
||||
public class EndAttributes {
|
||||
public final static Attribute BLINDNESS_RESISTANCE = registerAttribute("generic.blindness_resistance", 0.0, true);
|
||||
|
||||
public static Attribute registerAttribute(String name, double value, boolean syncable) {
|
||||
return Registry.register(Registry.ATTRIBUTE, BetterEnd.makeID(name), new EndAttribute("attribute.name." + name, value).setSyncable(syncable));
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder addLivingEntityAttributes(AttributeSupplier.Builder builder) {
|
||||
return builder.add(EndAttributes.BLINDNESS_RESISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5,7 +5,6 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -58,8 +57,10 @@ import ru.betterend.world.biome.land.PaintedMountainsBiome;
|
|||
import ru.betterend.world.biome.land.ShadowForestBiome;
|
||||
import ru.betterend.world.biome.land.SulphurSpringsBiome;
|
||||
import ru.betterend.world.biome.land.UmbrellaJungleBiome;
|
||||
import ru.betterend.world.generator.BiomeMap;
|
||||
import ru.betterend.world.generator.BiomePicker;
|
||||
import ru.betterend.world.generator.BiomeType;
|
||||
import ru.betterend.world.generator.GeneratorOptions;
|
||||
|
||||
public class EndBiomes {
|
||||
private static final HashMap<ResourceLocation, EndBiome> ID_MAP = Maps.newHashMap();
|
||||
|
@ -74,6 +75,7 @@ public class EndBiomes {
|
|||
private static final JsonObject EMPTY_JSON = new JsonObject();
|
||||
|
||||
private static Registry<Biome> biomeRegistry;
|
||||
private static BiomeMap caveBiomeMap;
|
||||
|
||||
// Vanilla Land
|
||||
public static final EndBiome END = registerBiome(Biomes.THE_END, BiomeType.LAND, 1F);
|
||||
|
@ -118,6 +120,12 @@ public class EndBiomes {
|
|||
CAVE_BIOMES.rebuild();
|
||||
}
|
||||
|
||||
public static void onWorldLoad(long seed) {
|
||||
if (caveBiomeMap == null || caveBiomeMap.getSeed() != seed) {
|
||||
caveBiomeMap = new BiomeMap(seed, GeneratorOptions.getBiomeSizeCaves(), CAVE_BIOMES);
|
||||
}
|
||||
}
|
||||
|
||||
public static void mutateRegistry(Registry<Biome> biomeRegistry) {
|
||||
EndBiomes.biomeRegistry = biomeRegistry;
|
||||
|
||||
|
@ -222,7 +230,7 @@ public class EndBiomes {
|
|||
* @param server - {@link MinecraftServer}
|
||||
*/
|
||||
public static void initRegistry(MinecraftServer server) {
|
||||
if (biomeRegistry == null) {
|
||||
if (biomeRegistry == null || biomeRegistry == BuiltinRegistries.BIOME) {
|
||||
biomeRegistry = server.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
}
|
||||
}
|
||||
|
@ -439,8 +447,8 @@ public class EndBiomes {
|
|||
return biome;
|
||||
}
|
||||
|
||||
public static EndCaveBiome getCaveBiome(Random random) {
|
||||
return (EndCaveBiome) CAVE_BIOMES.getBiome(random);
|
||||
public static EndCaveBiome getCaveBiome(int x, int z) {
|
||||
return (EndCaveBiome) caveBiomeMap.getBiome(x, z);
|
||||
}
|
||||
|
||||
public static boolean hasBiome(ResourceLocation biomeID) {
|
||||
|
|
|
@ -148,7 +148,7 @@ public class EndBlocks {
|
|||
public static final Block JELLYSHROOM_CAP_PURPLE = registerBlock("jellyshroom_cap_purple", new JellyshroomCapBlock(217, 142, 255, 164, 0, 255));
|
||||
public static final WoodenMaterial JELLYSHROOM = new WoodenMaterial("jellyshroom", MaterialColor.COLOR_PURPLE, MaterialColor.COLOR_LIGHT_BLUE);
|
||||
|
||||
public static final Block LUCERNIA_SAPLING = registerBlock("lucernia_sapling", new TenaneaSaplingBlock());
|
||||
public static final Block LUCERNIA_SAPLING = registerBlock("lucernia_sapling", new LucerniaSaplingBlock());
|
||||
public static final Block LUCERNIA_LEAVES = registerBlock("lucernia_leaves", new EndLeavesBlock(LUCERNIA_SAPLING, MaterialColor.COLOR_ORANGE));
|
||||
public static final Block LUCERNIA_OUTER_LEAVES = registerBlock("lucernia_outer_leaves", new FurBlock(LUCERNIA_SAPLING, 32));
|
||||
public static final WoodenMaterial LUCERNIA = new WoodenMaterial("lucernia", MaterialColor.COLOR_ORANGE, MaterialColor.COLOR_ORANGE);
|
||||
|
|
|
@ -257,7 +257,7 @@ public class EndFeatures {
|
|||
addFeature(ENDER_ORE, features);
|
||||
addFeature(CRASHED_SHIP, features);
|
||||
|
||||
if (EndBiomes.getBiome(id).hasCaves()) {
|
||||
if (EndBiomes.getBiome(id).hasCaves() && !EndBiomes.VOID_BIOMES.containsImmutable(id)) {
|
||||
addFeature(ROUND_CAVE, features);
|
||||
addFeature(TUNEL_CAVE, features);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.core.BlockSource;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -21,7 +22,6 @@ import net.minecraft.world.food.FoodProperties;
|
|||
import net.minecraft.world.food.Foods;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Item.Properties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.Rarity;
|
||||
|
@ -33,9 +33,7 @@ import net.minecraft.world.item.Tiers;
|
|||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.config.Configs;
|
||||
import ru.betterend.interfaces.BreakableItem;
|
||||
import ru.betterend.item.*;
|
||||
import ru.betterend.item.ModelProviderItem;
|
||||
import ru.betterend.item.material.EndArmorMaterial;
|
||||
import ru.betterend.item.material.EndToolMaterial;
|
||||
import ru.betterend.item.tool.EndAxeItem;
|
||||
|
@ -55,6 +53,7 @@ public class EndItems {
|
|||
public final static Item ENDER_DUST = registerItem("ender_dust");
|
||||
public final static Item ENDER_SHARD = registerItem("ender_shard");
|
||||
public final static Item AETERNIUM_INGOT = registerItem("aeternium_ingot");
|
||||
public final static Item AETERNIUM_FORGED_PLATE = registerItem("aeternium_forged_plate");
|
||||
public final static Item END_LILY_LEAF = registerItem("end_lily_leaf");
|
||||
public final static Item END_LILY_LEAF_DRIED = registerItem("end_lily_leaf_dried");
|
||||
public final static Item CRYSTAL_SHARDS = registerItem("crystal_shards");
|
||||
|
@ -73,18 +72,21 @@ public class EndItems {
|
|||
public final static Item SILK_MOTH_MATRIX = registerItem("silk_moth_matrix");
|
||||
|
||||
// Music Discs
|
||||
public final static Item MUSIC_DISC_STRANGE_AND_ALIEN = registerDisc("music_disc_strange_and_alien", 0, EndSounds.STRANGE_AND_ALIEN);
|
||||
public final static Item MUSIC_DISC_STRANGE_AND_ALIEN = registerDisc("music_disc_strange_and_alien", 0, EndSounds.RECORD_STRANGE_AND_ALIEN);
|
||||
public final static Item MUSIC_DISC_GRASPING_AT_STARS = registerDisc("music_disc_grasping_at_stars", 0, EndSounds.RECORD_GRASPING_AT_STARS);
|
||||
public final static Item MUSIC_DISC_ENDSEEKER = registerDisc("music_disc_endseeker", 0, EndSounds.RECORD_ENDSEEKER);
|
||||
public final static Item MUSIC_DISC_EO_DRACONA = registerDisc("music_disc_eo_dracona", 0, EndSounds.RECORD_EO_DRACONA);
|
||||
|
||||
// Armor //
|
||||
public static final Item AETERNIUM_HELMET = registerItem("aeternium_helmet", new EndArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.HEAD, makeItemSettings().fireResistant()));
|
||||
public static final Item AETERNIUM_CHESTPLATE = registerItem("aeternium_chestplate", new EndArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.CHEST, makeItemSettings().fireResistant()));
|
||||
public static final Item AETERNIUM_LEGGINGS = registerItem("aeternium_leggings", new EndArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.LEGS, makeItemSettings().fireResistant()));
|
||||
public static final Item AETERNIUM_BOOTS = registerItem("aeternium_boots", new EndArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.FEET, makeItemSettings().fireResistant()));
|
||||
public static final Item CRYSTALITE_HELMET = registerItem("crystalite_helmet", new EndArmorItem(EndArmorMaterial.CRYSTALITE, EquipmentSlot.HEAD, makeItemSettings().rarity(Rarity.UNCOMMON)));
|
||||
public static final Item CRYSTALITE_CHESTPLATE = registerItem("crystalite_chestplate", new EndArmorItem(EndArmorMaterial.CRYSTALITE, EquipmentSlot.CHEST, makeItemSettings().rarity(Rarity.UNCOMMON)));
|
||||
public static final Item CRYSTALITE_LEGGINGS = registerItem("crystalite_leggings", new EndArmorItem(EndArmorMaterial.CRYSTALITE, EquipmentSlot.LEGS, makeItemSettings().rarity(Rarity.UNCOMMON)));
|
||||
public static final Item CRYSTALITE_BOOTS = registerItem("crystalite_boots", new EndArmorItem(EndArmorMaterial.CRYSTALITE, EquipmentSlot.FEET, makeItemSettings().rarity(Rarity.UNCOMMON)));
|
||||
public static final Item ARMORED_ELYTRA = registerItem("elytra_armored", new ArmoredElytra("elytra_armored", AETERNIUM_INGOT, 700, 0.96D, true));
|
||||
public static final Item CRYSTALITE_HELMET = registerItem("crystalite_helmet", new CrystaliteHelmet());
|
||||
public static final Item CRYSTALITE_CHESTPLATE = registerItem("crystalite_chestplate", new CrystaliteChestplate());
|
||||
public static final Item CRYSTALITE_LEGGINGS = registerItem("crystalite_leggings", new CrystaliteLeggings());
|
||||
public static final Item CRYSTALITE_BOOTS = registerItem("crystalite_boots", new CrystaliteBoots());
|
||||
public static final Item ARMORED_ELYTRA = registerItem("elytra_armored", new ArmoredElytra("elytra_armored", EndArmorMaterial.AETERNIUM, Items.PHANTOM_MEMBRANE, 900, 0.96D, true));
|
||||
|
||||
// Tools //
|
||||
public static final TieredItem AETERNIUM_SHOVEL = registerTool("aeternium_shovel", new EndShovelItem(EndToolMaterial.AETERNIUM, 1.5F, -3.0F, makeItemSettings().fireResistant()));
|
||||
|
@ -114,10 +116,11 @@ public class EndItems {
|
|||
public final static Item SHADOW_BERRY_COOKED = registerFood("shadow_berry_cooked", 6, 0.7F);
|
||||
public final static Item END_FISH_RAW = registerFood("end_fish_raw", Foods.SALMON);
|
||||
public final static Item END_FISH_COOKED = registerFood("end_fish_cooked", Foods.COOKED_SALMON);
|
||||
public final static Item BUCKET_END_FISH = registerItem("bucket_end_fish", new EndBucketItem());
|
||||
public final static Item BUCKET_CUBOZOA = registerItem("bucket_cubozoa", new EndBucketItem());
|
||||
public final static Item SWEET_BERRY_JELLY = registerFood("sweet_berry_jelly", 6, 0.75F);
|
||||
public final static Item SHADOW_BERRY_JELLY = registerFood("shadow_berry_jelly", 7, 0.75F, new MobEffectInstance(MobEffects.NIGHT_VISION, 400));
|
||||
public final static Item BUCKET_END_FISH = registerItem("bucket_end_fish", new EndBucketItem(EndEntities.END_FISH));
|
||||
public final static Item BUCKET_CUBOZOA = registerItem("bucket_cubozoa", new EndBucketItem(EndEntities.CUBOZOA));
|
||||
public final static Item SWEET_BERRY_JELLY = registerFood("sweet_berry_jelly", 8, 0.7F);
|
||||
public final static Item SHADOW_BERRY_JELLY = registerFood("shadow_berry_jelly", 6, 0.8F, new MobEffectInstance(MobEffects.NIGHT_VISION, 400));
|
||||
public final static Item BLOSSOM_BERRY_JELLY = registerFood("blossom_berry_jelly", 8, 0.7F);
|
||||
public final static Item BLOSSOM_BERRY = registerFood("blossom_berry", Foods.APPLE);
|
||||
public final static Item AMBER_ROOT_RAW = registerFood("amber_root_raw", 2, 0.8F);
|
||||
public final static Item CHORUS_MUSHROOM_RAW = registerFood("chorus_mushroom_raw", 3, 0.5F);
|
||||
|
@ -129,11 +132,11 @@ public class EndItems {
|
|||
public final static Item UMBRELLA_CLUSTER_JUICE = registerDrink("umbrella_cluster_juice", 5, 0.7F);
|
||||
|
||||
public static Item registerDisc(String name, int power, SoundEvent sound) {
|
||||
return registerItem(BetterEnd.makeID(name), new ModelProviderDiscItem(power, sound, makeItemSettings()));
|
||||
return registerItem(BetterEnd.makeID(name), new PatternedDiscItem(power, sound, makeItemSettings()));
|
||||
}
|
||||
|
||||
public static Item registerItem(String name) {
|
||||
return registerItem(BetterEnd.makeID(name), new ModelProviderItem(makeItemSettings()));
|
||||
return registerItem(BetterEnd.makeID(name), new PatternedItem(makeItemSettings()));
|
||||
}
|
||||
|
||||
public static Item registerItem(String name, Item item) {
|
||||
|
@ -148,9 +151,6 @@ public class EndItems {
|
|||
return item;
|
||||
}
|
||||
registerItem(id, item, MOD_ITEMS);
|
||||
if (item instanceof BreakableItem) {
|
||||
((BreakableItem) item).registerBrokenItem();
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,7 @@ public class EndItems {
|
|||
}
|
||||
|
||||
public static Item registerFood(String name, FoodProperties foodComponent) {
|
||||
return registerItem(name, new ModelProviderItem(makeItemSettings().food(foodComponent)));
|
||||
return registerItem(name, new PatternedItem(makeItemSettings().food(foodComponent)));
|
||||
}
|
||||
|
||||
public static Item registerDrink(String name) {
|
||||
|
@ -238,12 +238,14 @@ public class EndItems {
|
|||
return registerDrink(name, builder.build());
|
||||
}
|
||||
|
||||
public static Properties makeItemSettings() {
|
||||
return new Item.Properties().tab(CreativeTabs.TAB_ITEMS);
|
||||
public static FabricItemSettings makeItemSettings() {
|
||||
FabricItemSettings properties = new FabricItemSettings();
|
||||
return (FabricItemSettings) properties.tab(CreativeTabs.TAB_ITEMS);
|
||||
}
|
||||
|
||||
public static Properties makeBlockItemSettings() {
|
||||
return new Item.Properties().tab(CreativeTabs.TAB_BLOCKS);
|
||||
public static FabricItemSettings makeBlockItemSettings() {
|
||||
FabricItemSettings properties = new FabricItemSettings();
|
||||
return (FabricItemSettings) properties.tab(CreativeTabs.TAB_BLOCKS);
|
||||
}
|
||||
|
||||
public static void register() {}
|
||||
|
|
|
@ -10,6 +10,7 @@ public class EndSounds {
|
|||
public static final SoundEvent MUSIC_WATER = register("music", "water");
|
||||
public static final SoundEvent MUSIC_DARK = register("music", "dark");
|
||||
public static final SoundEvent MUSIC_OPENSPACE = register("music", "openspace");
|
||||
public static final SoundEvent MUSIC_CAVES = register("music", "caves");
|
||||
|
||||
// Ambient
|
||||
public static final SoundEvent AMBIENT_FOGGY_MUSHROOMLAND = register("ambient", "foggy_mushroomland");
|
||||
|
@ -21,6 +22,7 @@ public class EndSounds {
|
|||
public static final SoundEvent AMBIENT_SULPHUR_SPRINGS = register("ambient", "sulphur_springs");
|
||||
public static final SoundEvent AMBIENT_UMBRELLA_JUNGLE = register("ambient", "umbrella_jungle");
|
||||
public static final SoundEvent AMBIENT_GLOWING_GRASSLANDS = register("ambient", "glowing_grasslands");
|
||||
public static final SoundEvent AMBIENT_CAVES = register("ambient", "caves");
|
||||
|
||||
// Entity
|
||||
public static final SoundEvent ENTITY_DRAGONFLY = register("entity", "dragonfly");
|
||||
|
@ -29,7 +31,10 @@ public class EndSounds {
|
|||
public static final SoundEvent ENTITY_SHADOW_WALKER_DEATH = register("entity", "shadow_walker_death");
|
||||
|
||||
// Records
|
||||
public static final SoundEvent STRANGE_AND_ALIEN = register("record", "strange_and_alien");
|
||||
public static final SoundEvent RECORD_STRANGE_AND_ALIEN = register("record", "strange_and_alien");
|
||||
public static final SoundEvent RECORD_GRASPING_AT_STARS = register("record", "grasping_at_stars");
|
||||
public static final SoundEvent RECORD_ENDSEEKER = register("record", "endseeker");
|
||||
public static final SoundEvent RECORD_EO_DRACONA = register("record", "eo_dracona");
|
||||
|
||||
public static void register() {}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ public class EndTags {
|
|||
TagHelper.addTag(EndTags.DRAGON_IMMUNE, EndBlocks.ENDER_ORE, EndBlocks.ETERNAL_PEDESTAL, EndBlocks.FLAVOLITE_RUNED_ETERNAL, EndBlocks.FLAVOLITE_RUNED);
|
||||
|
||||
TagHelper.addTag(EndTags.IRON_INGOTS, Items.IRON_INGOT);
|
||||
TagHelper.addTag(EndTags.IRON_INGOTS, EndBlocks.TERMINITE.ingot);
|
||||
TagHelper.addTag(EndTags.IRON_INGOTS, EndBlocks.THALLASIUM.ingot);
|
||||
}
|
||||
|
||||
public static void addSurfaceBlock(Block block) {
|
||||
|
|
|
@ -19,7 +19,15 @@ public class LootTableUtil {
|
|||
builder.setRolls(RandomValueBounds.between(0, 5));
|
||||
builder.withCondition(LootItemRandomChanceCondition.randomChance(0.5f).build());
|
||||
builder.withEntry(LootItem.lootTableItem(Items.GHAST_TEAR).build());
|
||||
supplier.withPool(builder);
|
||||
|
||||
builder = FabricLootPoolBuilder.builder();
|
||||
builder.setRolls(RandomValueBounds.between(0, 5));
|
||||
builder.withCondition(LootItemRandomChanceCondition.randomChance(0.1f).build());
|
||||
builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_STRANGE_AND_ALIEN).build());
|
||||
builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_GRASPING_AT_STARS).build());
|
||||
builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_ENDSEEKER).build());
|
||||
builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_EO_DRACONA).build());
|
||||
supplier.withPool(builder);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -68,6 +68,7 @@ public class BiomeDefinition {
|
|||
private float genChance = 1F;
|
||||
private boolean hasCaves = true;
|
||||
private boolean isCaveBiome = false;
|
||||
private float temperature = 1F;
|
||||
|
||||
private ConfiguredSurfaceBuilder<?> surface;
|
||||
|
||||
|
@ -118,6 +119,11 @@ public class BiomeDefinition {
|
|||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setTemperature(float temperature) {
|
||||
this.temperature = temperature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addMobSpawn(EntityType<?> type, int weight, int minGroupSize, int maxGroupSize) {
|
||||
ResourceLocation eID = Registry.ENTITY_TYPE.getKey(type);
|
||||
if (eID != Registry.ENTITY_TYPE.getDefaultKey()) {
|
||||
|
@ -263,7 +269,7 @@ public class BiomeDefinition {
|
|||
.biomeCategory(isCaveBiome ? BiomeCategory.NONE : BiomeCategory.THEEND)
|
||||
.depth(depth)
|
||||
.scale(0.2F)
|
||||
.temperature(2.0F)
|
||||
.temperature(temperature)
|
||||
.downfall(0.0F)
|
||||
.specialEffects(effects.build())
|
||||
.mobSpawnSettings(spawnSettings.build())
|
||||
|
|
|
@ -11,9 +11,11 @@ public class BiomeIceStarfield extends EndBiome {
|
|||
public BiomeIceStarfield() {
|
||||
super(new BiomeDefinition("ice_starfield")
|
||||
.setFogColor(224, 245, 254)
|
||||
.setTemperature(0F)
|
||||
.setFogDensity(2.2F)
|
||||
.setFoliageColor(193, 244, 244)
|
||||
.setGenChance(0.25F)
|
||||
.setCaves(false)
|
||||
.setParticles(EndParticles.SNOWFLAKE, 0.002F)
|
||||
.addStructureFeature(EndStructures.GIANT_ICE_STAR)
|
||||
.addFeature(EndFeatures.ICE_STAR)
|
||||
|
|
|
@ -2,7 +2,6 @@ package ru.betterend.world.biome.cave;
|
|||
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
import ru.betterend.registry.EndParticles;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.world.biome.BiomeDefinition;
|
||||
|
||||
public class EmptyAuroraCaveBiome extends EndCaveBiome {
|
||||
|
@ -12,7 +11,6 @@ public class EmptyAuroraCaveBiome extends EndCaveBiome {
|
|||
.setFogDensity(2.0F)
|
||||
.setPlantsColor(108, 25, 46)
|
||||
.setWaterAndFogColor(186, 77, 237)
|
||||
.setMusic(EndSounds.MUSIC_FOREST)
|
||||
.setParticles(EndParticles.GLOWING_SPHERE, 0.001F));
|
||||
|
||||
this.addFloorFeature(EndFeatures.BIG_AURORA_CRYSTAL, 1);
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
package ru.betterend.world.biome.cave;
|
||||
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.world.biome.BiomeDefinition;
|
||||
|
||||
public class EmptyEndCaveBiome extends EndCaveBiome {
|
||||
public EmptyEndCaveBiome() {
|
||||
super(new BiomeDefinition("empty_end_cave")
|
||||
.setFogDensity(2.0F)
|
||||
.setMusic(EndSounds.MUSIC_FOREST));
|
||||
|
||||
super(new BiomeDefinition("empty_end_cave").setFogDensity(2.0F));
|
||||
this.addFloorFeature(EndFeatures.END_STONE_STALAGMITE, 1);
|
||||
this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package ru.betterend.world.biome.cave;
|
|||
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
import ru.betterend.registry.EndParticles;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.world.biome.BiomeDefinition;
|
||||
|
||||
public class EmptySmaragdantCaveBiome extends EndCaveBiome {
|
||||
|
@ -12,7 +11,6 @@ public class EmptySmaragdantCaveBiome extends EndCaveBiome {
|
|||
.setFogDensity(2.0F)
|
||||
.setPlantsColor(0, 131, 145)
|
||||
.setWaterAndFogColor(31, 167, 212)
|
||||
.setMusic(EndSounds.MUSIC_FOREST)
|
||||
.setParticles(EndParticles.SMARAGDANT, 0.001F));
|
||||
|
||||
this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL, 1);
|
||||
|
|
|
@ -7,6 +7,7 @@ import net.minecraft.world.entity.ai.behavior.WeightedList;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import ru.betterend.registry.EndBiomes;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.world.biome.BiomeDefinition;
|
||||
import ru.betterend.world.biome.EndBiome;
|
||||
import ru.betterend.world.features.EndFeature;
|
||||
|
@ -26,6 +27,8 @@ public class EndCaveBiome extends EndBiome {
|
|||
new CaveChunkPopulatorFeature(() -> (EndCaveBiome) EndBiomes.getBiome(definition.getID()))
|
||||
);
|
||||
definition.addFeature(feature).setCaveBiome();
|
||||
definition.setMusic(EndSounds.MUSIC_CAVES);
|
||||
definition.setLoop(EndSounds.AMBIENT_CAVES);
|
||||
return definition;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import net.minecraft.util.Mth;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import ru.betterend.noise.OpenSimplexNoise;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.world.biome.BiomeDefinition;
|
||||
|
||||
public class JadeCaveBiome extends EndCaveBiome {
|
||||
|
@ -18,7 +17,6 @@ public class JadeCaveBiome extends EndCaveBiome {
|
|||
.setFogColor(118, 150, 112)
|
||||
.setFogDensity(2.0F)
|
||||
.setWaterAndFogColor(95, 223, 255)
|
||||
.setMusic(EndSounds.MUSIC_FOREST)
|
||||
);
|
||||
JADE[0] = EndBlocks.VIRID_JADESTONE.stone.defaultBlockState();
|
||||
JADE[1] = EndBlocks.AZURE_JADESTONE.stone.defaultBlockState();
|
||||
|
|
|
@ -7,7 +7,6 @@ import ru.betterend.blocks.BlockProperties.TripleShape;
|
|||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
import ru.betterend.registry.EndParticles;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.world.biome.BiomeDefinition;
|
||||
|
||||
public class LushAuroraCaveBiome extends EndCaveBiome {
|
||||
|
@ -17,7 +16,6 @@ public class LushAuroraCaveBiome extends EndCaveBiome {
|
|||
.setFogDensity(2.0F)
|
||||
.setPlantsColor(108, 25, 46)
|
||||
.setWaterAndFogColor(186, 77, 237)
|
||||
.setMusic(EndSounds.MUSIC_FOREST)
|
||||
.setParticles(EndParticles.GLOWING_SPHERE, 0.001F)
|
||||
.setSurface(EndBlocks.CAVE_MOSS));
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package ru.betterend.world.biome.cave;
|
|||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
import ru.betterend.registry.EndParticles;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.world.biome.BiomeDefinition;
|
||||
|
||||
public class LushSmaragdantCaveBiome extends EndCaveBiome {
|
||||
|
@ -13,7 +12,6 @@ public class LushSmaragdantCaveBiome extends EndCaveBiome {
|
|||
.setFogDensity(2.0F)
|
||||
.setPlantsColor(0, 131, 145)
|
||||
.setWaterAndFogColor(31, 167, 212)
|
||||
.setMusic(EndSounds.MUSIC_FOREST)
|
||||
.setParticles(EndParticles.SMARAGDANT, 0.001F)
|
||||
.setSurface(EndBlocks.CAVE_MOSS));
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ public class PaintedMountainsBiome extends EndBiome {
|
|||
super(new BiomeDefinition("painted_mountains")
|
||||
.setFogColor(226, 239, 168)
|
||||
.setFogDensity(2)
|
||||
.setCaves(false)
|
||||
.setWaterAndFogColor(192, 180, 131)
|
||||
.setMusic(EndSounds.MUSIC_OPENSPACE)
|
||||
.setLoop(EndSounds.AMBIENT_DUST_WASTELANDS)
|
||||
|
|
|
@ -26,18 +26,15 @@ import ru.betterend.world.features.DefaultFeature;
|
|||
|
||||
public class ObsidianPillarBasementFeature extends DefaultFeature {
|
||||
@Override
|
||||
public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos,
|
||||
NoneFeatureConfiguration config) {
|
||||
pos = getPosOnSurface(world,
|
||||
new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)));
|
||||
public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, NoneFeatureConfiguration config) {
|
||||
pos = getPosOnSurface(world, new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)));
|
||||
if (!world.getBlockState(pos.below(5)).is(EndTags.GEN_TERRAIN)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float height = MHelper.randRange(10F, 35F, random);
|
||||
float radius = MHelper.randRange(2F, 5F, random);
|
||||
SDF pillar = new SDFCappedCone().setRadius1(radius).setRadius2(radius).setHeight(height * 0.5F)
|
||||
.setBlock(Blocks.OBSIDIAN);
|
||||
SDF pillar = new SDFCappedCone().setRadius1(radius).setRadius2(radius).setHeight(height * 0.5F).setBlock(Blocks.OBSIDIAN);
|
||||
pillar = new SDFTranslate().setTranslate(0, height * 0.5F - 3, 0).setSource(pillar);
|
||||
SDF cut = new SDFFlatland().setBlock(Blocks.OBSIDIAN);
|
||||
OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong());
|
||||
|
@ -52,7 +49,6 @@ public class ObsidianPillarBasementFeature extends DefaultFeature {
|
|||
vec = MHelper.randomHorizontal(random);
|
||||
angle = random.nextFloat() * 0.2F;
|
||||
pillar = new SDFRotation().setRotation(vec, angle).setSource(pillar);
|
||||
|
||||
BlockState mossy = EndBlocks.MOSSY_OBSIDIAN.defaultBlockState();
|
||||
pillar.addPostProcess((info) -> {
|
||||
if (info.getStateUp().isAir() && random.nextFloat() > 0.1F) {
|
||||
|
@ -60,8 +56,7 @@ public class ObsidianPillarBasementFeature extends DefaultFeature {
|
|||
}
|
||||
return info.getState();
|
||||
}).setReplaceFunction((state) -> {
|
||||
return state.getMaterial().isReplaceable() || state.is(EndTags.GEN_TERRAIN)
|
||||
|| state.getMaterial().equals(Material.PLANT);
|
||||
return state.getMaterial().isReplaceable() || state.is(EndTags.GEN_TERRAIN) || state.getMaterial().equals(Material.PLANT);
|
||||
}).fillRecursive(world, pos);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -51,7 +51,7 @@ public abstract class EndCaveFeature extends DefaultFeature {
|
|||
return false;
|
||||
}
|
||||
|
||||
EndCaveBiome biome = EndBiomes.getCaveBiome(random);
|
||||
EndCaveBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ());
|
||||
Set<BlockPos> caveBlocks = generate(world, center, radius, random);
|
||||
if (!caveBlocks.isEmpty()) {
|
||||
if (biome != null) {
|
||||
|
@ -88,7 +88,9 @@ public abstract class EndCaveFeature extends DefaultFeature {
|
|||
protected void placeFloor(WorldGenLevel world, EndCaveBiome biome, Set<BlockPos> floorPositions, Random random, BlockState surfaceBlock) {
|
||||
float density = biome.getFloorDensity();
|
||||
floorPositions.forEach((pos) -> {
|
||||
BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock);
|
||||
if (!surfaceBlock.is(Blocks.END_STONE)) {
|
||||
BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock);
|
||||
}
|
||||
if (density > 0 && random.nextFloat() <= density) {
|
||||
Feature<?> feature = biome.getFloorFeature(random);
|
||||
if (feature != null) {
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
package ru.betterend.world.features.terrain.caves;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
import ru.betterend.noise.OpenSimplexNoise;
|
||||
|
@ -20,12 +25,14 @@ import ru.betterend.util.BlocksHelper;
|
|||
import ru.betterend.world.biome.cave.EndCaveBiome;
|
||||
|
||||
public class TunelCaveFeature extends EndCaveFeature {
|
||||
private static final OpenSimplexNoise BIOME_NOISE_X = new OpenSimplexNoise("biome_noise_x".hashCode());
|
||||
private static final OpenSimplexNoise BIOME_NOISE_Z = new OpenSimplexNoise("biome_noise_z".hashCode());
|
||||
|
||||
private Set<BlockPos> generate(WorldGenLevel world, BlockPos center, Random random) {
|
||||
int x1 = (center.getX() >> 4) << 4;
|
||||
int z1 = (center.getZ() >> 4) << 4;
|
||||
int cx = center.getX() >> 4;
|
||||
int cz = center.getZ() >> 4;
|
||||
if ((long) cx * (long) cx + (long) cz + (long) cz < 256) {
|
||||
return Sets.newHashSet();
|
||||
}
|
||||
int x1 = cx << 4;
|
||||
int z1 = cz << 4;
|
||||
int x2 = x1 + 16;
|
||||
int z2 = z1 + 16;
|
||||
int y2 = world.getHeight();
|
||||
|
@ -43,12 +50,19 @@ public class TunelCaveFeature extends EndCaveFeature {
|
|||
for (int y = 0; y < y2; y++) {
|
||||
pos.setY(y);
|
||||
float val = Mth.abs((float) noiseH.eval(x * 0.02, y * 0.01, z * 0.02));
|
||||
float vert = Mth.sin((y + (float) noiseV.eval(x * 0.01, z * 0.01) * 20) * 0.1F) * 0.9F;//Mth.abs(y - 50 + (float) noiseV.eval(x * 0.01, z * 0.01) * 20) * 0.1F;
|
||||
float vert = Mth.sin((y + (float) noiseV.eval(x * 0.01, z * 0.01) * 20) * 0.1F) * 0.9F;
|
||||
float dist = (float) noiseD.eval(x * 0.1, y * 0.1, z * 0.1) * 0.12F;
|
||||
vert *= vert;
|
||||
if (val + vert + dist < 0.15 && world.getBlockState(pos).is(EndTags.GEN_TERRAIN)) {
|
||||
if (val + vert + dist < 0.15 && world.getBlockState(pos).is(EndTags.GEN_TERRAIN) && noWaterNear(world, pos)) {
|
||||
BlocksHelper.setWithoutUpdate(world, pos, AIR);
|
||||
positions.add(pos.immutable());
|
||||
int height = world.getHeight(Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ());
|
||||
if (height < pos.getY() + 4) {
|
||||
while (pos.getY() < height && noWaterNear(world, pos)) {
|
||||
pos.setY(pos.getY() + 1);
|
||||
BlocksHelper.setWithoutUpdate(world, pos, AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +70,23 @@ public class TunelCaveFeature extends EndCaveFeature {
|
|||
return positions;
|
||||
}
|
||||
|
||||
private boolean noWaterNear(WorldGenLevel world, BlockPos pos) {
|
||||
BlockPos above1 = pos.above();
|
||||
BlockPos above2 = pos.above(2);
|
||||
if (!world.getFluidState(above1).isEmpty() || !world.getFluidState(above2).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (Direction dir: BlocksHelper.HORIZONTAL) {
|
||||
if (!world.getFluidState(above1.relative(dir)).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (!world.getFluidState(above2.relative(dir)).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, NoneFeatureConfiguration config) {
|
||||
if (pos.getX() * pos.getX() + pos.getZ() * pos.getZ() <= 2500) {
|
||||
|
@ -66,49 +97,62 @@ public class TunelCaveFeature extends EndCaveFeature {
|
|||
return false;
|
||||
}
|
||||
|
||||
EndCaveBiome biome = EndBiomes.getCaveBiome(random);
|
||||
Set<BlockPos> preCaveBlocks = generate(world, pos, random);
|
||||
Set<BlockPos> caveBlocks = mutateBlocks(preCaveBlocks);
|
||||
if (!caveBlocks.isEmpty()) {
|
||||
if (biome != null) {
|
||||
setBiomes(world, biome, caveBlocks);
|
||||
Set<BlockPos> floorPositions = Sets.newHashSet();
|
||||
Set<BlockPos> ceilPositions = Sets.newHashSet();
|
||||
MutableBlockPos mut = new MutableBlockPos();
|
||||
caveBlocks.forEach((bpos) -> {
|
||||
mut.set(bpos);
|
||||
if (world.getBlockState(mut).getMaterial().isReplaceable()) {
|
||||
mut.setY(bpos.getY() - 1);
|
||||
if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) {
|
||||
floorPositions.add(mut.immutable());
|
||||
}
|
||||
mut.setY(bpos.getY() + 1);
|
||||
if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) {
|
||||
ceilPositions.add(mut.immutable());
|
||||
}
|
||||
}
|
||||
});
|
||||
BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
|
||||
placeFloor(world, biome, floorPositions, random, surfaceBlock);
|
||||
placeCeil(world, biome, ceilPositions, random);
|
||||
placeWalls(world, biome, caveBlocks, random);
|
||||
}
|
||||
fixBlocks(world, preCaveBlocks);
|
||||
Set<BlockPos> caveBlocks = generate(world, pos, random);
|
||||
if (caveBlocks.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Set<BlockPos> mutateBlocks(Set<BlockPos> caveBlocks) {
|
||||
Set<BlockPos> result = Sets.newHashSet();
|
||||
caveBlocks.forEach(pos -> {
|
||||
int dx = pos.getX() + (int) (BIOME_NOISE_X.eval(pos.getX() * 0.2, pos.getZ() * 0.2) * 5);
|
||||
int dz = pos.getZ() + (int) (BIOME_NOISE_Z.eval(pos.getX() * 0.2, pos.getZ() * 0.2) * 5);
|
||||
if ((dx >> 4) == (pos.getX() >> 4) && (dz >> 4) == (pos.getZ() >> 4)) {
|
||||
result.add(pos);
|
||||
Map<EndCaveBiome, Set<BlockPos>> floorSets = Maps.newHashMap();
|
||||
Map<EndCaveBiome, Set<BlockPos>> ceilSets = Maps.newHashMap();
|
||||
MutableBlockPos mut = new MutableBlockPos();
|
||||
Set<BlockPos> remove = Sets.newHashSet();
|
||||
caveBlocks.forEach((bpos) -> {
|
||||
mut.set(bpos);
|
||||
EndCaveBiome bio = EndBiomes.getCaveBiome(bpos.getX(), bpos.getZ());
|
||||
int height = world.getHeight(Types.WORLD_SURFACE, bpos.getX(), bpos.getZ());
|
||||
if (mut.getY() >= height) {
|
||||
remove.add(bpos);
|
||||
}
|
||||
else if (world.getBlockState(mut).getMaterial().isReplaceable()) {
|
||||
mut.setY(bpos.getY() - 1);
|
||||
if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) {
|
||||
Set<BlockPos> floorPositions = floorSets.get(bio);
|
||||
if (floorPositions == null) {
|
||||
floorPositions = Sets.newHashSet();
|
||||
floorSets.put(bio, floorPositions);
|
||||
}
|
||||
floorPositions.add(mut.immutable());
|
||||
}
|
||||
mut.setY(bpos.getY() + 1);
|
||||
if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) {
|
||||
Set<BlockPos> ceilPositions = ceilSets.get(bio);
|
||||
if (ceilPositions == null) {
|
||||
ceilPositions = Sets.newHashSet();
|
||||
ceilSets.put(bio, ceilPositions);
|
||||
}
|
||||
ceilPositions.add(mut.immutable());
|
||||
}
|
||||
setBiome(world, bpos, bio);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
caveBlocks.removeAll(remove);
|
||||
|
||||
if (caveBlocks.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
floorSets.forEach((biome, floorPositions) -> {
|
||||
BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
|
||||
placeFloor(world, biome, floorPositions, random, surfaceBlock);
|
||||
});
|
||||
ceilSets.forEach((biome, ceilPositions) -> {
|
||||
placeCeil(world, biome, ceilPositions, random);
|
||||
});
|
||||
EndCaveBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ());
|
||||
placeWalls(world, biome, caveBlocks, random);
|
||||
fixBlocks(world, caveBlocks);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,7 +164,9 @@ public class TunelCaveFeature extends EndCaveFeature {
|
|||
protected void placeFloor(WorldGenLevel world, EndCaveBiome biome, Set<BlockPos> floorPositions, Random random, BlockState surfaceBlock) {
|
||||
float density = biome.getFloorDensity() * 0.2F;
|
||||
floorPositions.forEach((pos) -> {
|
||||
BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock);
|
||||
if (!surfaceBlock.is(Blocks.END_STONE)) {
|
||||
BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock);
|
||||
}
|
||||
if (density > 0 && random.nextFloat() <= density) {
|
||||
Feature<?> feature = biome.getFloorFeature(random);
|
||||
if (feature != null) {
|
||||
|
|
|
@ -95,6 +95,9 @@ public class BetterEndBiomeSource extends BiomeSource {
|
|||
endBiome = mapLand.getBiome(biomeX << 2, biomeZ << 2);
|
||||
}
|
||||
else {
|
||||
if (!GeneratorOptions.noRingVoid() && dist <= 65536L) {
|
||||
return barrens;
|
||||
}
|
||||
endBiome = mapVoid.getBiome(biomeX << 2, biomeZ << 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ public class BiomeMap {
|
|||
private final OpenSimplexNoise noiseX;
|
||||
private final OpenSimplexNoise noiseZ;
|
||||
private final BiomePicker picker;
|
||||
private final long seed;
|
||||
|
||||
public BiomeMap(long seed, int size, BiomePicker picker) {
|
||||
maps.clear();
|
||||
|
@ -30,6 +31,11 @@ public class BiomeMap {
|
|||
depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2;
|
||||
this.size = 1 << depth;
|
||||
this.picker = picker;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
public long getSeed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
|
|
|
@ -7,6 +7,7 @@ import ru.betterend.config.Configs;
|
|||
public class GeneratorOptions {
|
||||
private static int biomeSizeLand;
|
||||
private static int biomeSizeVoid;
|
||||
private static int biomeSizeCaves;
|
||||
private static boolean hasPortal;
|
||||
private static boolean hasPillars;
|
||||
private static boolean hasDragonFights;
|
||||
|
@ -28,10 +29,12 @@ public class GeneratorOptions {
|
|||
private static boolean replacePillars;
|
||||
private static long islandDistBlock;
|
||||
private static int islandDistChunk;
|
||||
private static boolean directSpikeHeight;
|
||||
|
||||
public static void init() {
|
||||
biomeSizeLand = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeLand", 256);
|
||||
biomeSizeVoid = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeVoid", 256);
|
||||
biomeSizeCaves = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeCaves", 32);
|
||||
hasPortal = Configs.GENERATOR_CONFIG.getBoolean("portal", "hasPortal", true);
|
||||
hasPillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "hasSpikes", true);
|
||||
hasDragonFights = Configs.GENERATOR_CONFIG.getBooleanRoot("hasDragonFights", true);
|
||||
|
@ -67,6 +70,10 @@ public class GeneratorOptions {
|
|||
return Mth.clamp(biomeSizeVoid, 1, 8192);
|
||||
}
|
||||
|
||||
public static int getBiomeSizeCaves() {
|
||||
return Mth.clamp(biomeSizeCaves, 1, 8192);
|
||||
}
|
||||
|
||||
public static boolean hasPortal() {
|
||||
return hasPortal;
|
||||
}
|
||||
|
@ -142,4 +149,14 @@ public class GeneratorOptions {
|
|||
public static int getIslandDistChunk() {
|
||||
return islandDistChunk;
|
||||
}
|
||||
|
||||
public static void setDirectSpikeHeight() {
|
||||
directSpikeHeight = true;
|
||||
}
|
||||
|
||||
public static boolean isDirectSpikeHeight() {
|
||||
boolean height = directSpikeHeight;
|
||||
directSpikeHeight = false;
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,25 +26,25 @@ public class EternalPortalStructure extends FeatureBaseStructure {
|
|||
private static final StructureTemplate STRUCTURE = StructureHelper.readStructure(STRUCTURE_ID);
|
||||
|
||||
@Override
|
||||
protected boolean shouldStartAt(ChunkGenerator chunkGenerator, BiomeSource biomeSource, long worldSeed, WorldgenRandom chunkRandom, int chunkX, int chunkZ, Biome biome, ChunkPos chunkPos, NoneFeatureConfiguration featureConfig) {
|
||||
long x = chunkPos.x;
|
||||
long z = chunkPos.z;
|
||||
if (x * x + z * z < 10000) {
|
||||
protected boolean isFeatureChunk(ChunkGenerator chunkGenerator, BiomeSource biomeSource, long worldSeed, WorldgenRandom chunkRandom, int chunkX, int chunkZ, Biome biome, ChunkPos chunkPos, NoneFeatureConfiguration featureConfig) {
|
||||
long x = (long) chunkPos.x * (long) chunkPos.x;
|
||||
long z = (long) chunkPos.z * (long) chunkPos.z;
|
||||
if (x + z < 1024L) {
|
||||
return false;
|
||||
}
|
||||
if (chunkGenerator.getBaseHeight((chunkX << 4) | 8, (chunkZ << 4) | 8, Heightmap.Types.WORLD_SURFACE_WG) < 10) {
|
||||
return false;
|
||||
}
|
||||
return super.shouldStartAt(chunkGenerator, biomeSource, worldSeed, chunkRandom, chunkX, chunkZ, biome, chunkPos, featureConfig);
|
||||
return super.isFeatureChunk(chunkGenerator, biomeSource, worldSeed, chunkRandom, chunkX, chunkZ, biome, chunkPos, featureConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureFeature.StructureStartFactory<NoneFeatureConfiguration> getStartFactory() {
|
||||
return SDFStructureStart::new;
|
||||
return PortalStructureStart::new;
|
||||
}
|
||||
|
||||
public static class SDFStructureStart extends StructureStart<NoneFeatureConfiguration> {
|
||||
public SDFStructureStart(StructureFeature<NoneFeatureConfiguration> feature, int chunkX, int chunkZ, BoundingBox box, int references, long seed) {
|
||||
public static class PortalStructureStart extends StructureStart<NoneFeatureConfiguration> {
|
||||
public PortalStructureStart(StructureFeature<NoneFeatureConfiguration> feature, int chunkX, int chunkZ, BoundingBox box, int references, long seed) {
|
||||
super(feature, chunkX, chunkZ, box, references, seed);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@ public abstract class FeatureBaseStructure extends StructureFeature<NoneFeatureC
|
|||
super(NoneFeatureConfiguration.CODEC);
|
||||
}
|
||||
|
||||
protected boolean shouldStartAt(ChunkGenerator chunkGenerator, BiomeSource biomeSource, long worldSeed, WorldgenRandom chunkRandom, int chunkX, int chunkZ, Biome biome, ChunkPos chunkPos, NoneFeatureConfiguration featureConfig) {
|
||||
@Override
|
||||
protected boolean isFeatureChunk(ChunkGenerator chunkGenerator, BiomeSource biomeSource, long worldSeed, WorldgenRandom chunkRandom, int chunkX, int chunkZ, Biome biome, ChunkPos chunkPos, NoneFeatureConfiguration featureConfig) {
|
||||
return getGenerationHeight(chunkX, chunkZ, chunkGenerator) >= 20;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public class NBTPiece extends BasePiece {
|
|||
|
||||
@Override
|
||||
protected void addAdditionalSaveData(CompoundTag tag) {
|
||||
tag.putString("id", structureID.toString());
|
||||
tag.putString("structureID", structureID.toString());
|
||||
tag.putInt("rotation", rotation.ordinal());
|
||||
tag.putInt("mirror", mirror.ordinal());
|
||||
tag.putInt("erosion", erosion);
|
||||
|
@ -58,7 +58,7 @@ public class NBTPiece extends BasePiece {
|
|||
|
||||
@Override
|
||||
protected void fromNbt(CompoundTag tag) {
|
||||
structureID = new ResourceLocation(tag.getString("id"));
|
||||
structureID = new ResourceLocation(tag.getString("structureID"));
|
||||
rotation = Rotation.values()[tag.getInt("rotation")];
|
||||
mirror = Mirror.values()[tag.getInt("mirror")];
|
||||
erosion = tag.getInt("erosion");
|
||||
|
|
|
@ -506,7 +506,7 @@
|
|||
"block.betterend.vent_bubble_column": "Vent Bubble Column",
|
||||
"block.betterend.respawn_obelisk": "Respawn Obelisk",
|
||||
"message.betterend.set_spawn": "\u00A7b\u00A7lYour spawn point is set here",
|
||||
"message.betterend.fail_spawn": "\u00A7c\u00A7lYour need to hold 6 Amber Gems to set your spawn point",
|
||||
"message.betterend.fail_spawn": "\u00A7c\u00A7lYou need to hold 6 Amber Gems to set your spawn point",
|
||||
|
||||
"block.betterend.dragon_tree_composter": "Dragon Tree Composter",
|
||||
"block.betterend.end_lotus_composter": "End Lotus Composter",
|
||||
|
@ -821,6 +821,12 @@
|
|||
|
||||
"item.betterend.music_disc_strange_and_alien": "§bMusic Disc§r",
|
||||
"item.betterend.music_disc_strange_and_alien.desc": "§5Firel§r - §fStrange And Alien§r",
|
||||
"item.betterend.music_disc_grasping_at_stars": "§bMusic Disc§r",
|
||||
"item.betterend.music_disc_grasping_at_stars.desc": "§5Firel§r - §fGrasping At Stars§r",
|
||||
"item.betterend.music_disc_endseeker": "§bMusic Disc§r",
|
||||
"item.betterend.music_disc_endseeker.desc": "§5Firel§r - §fEndseeker§r",
|
||||
"item.betterend.music_disc_eo_dracona": "§bMusic Disc§r",
|
||||
"item.betterend.music_disc_eo_dracona.desc": "§5Firel§r - §fEo Dracona§r",
|
||||
|
||||
"block.betterend.hydralux_petal_block_amber": "Amber Petal Block",
|
||||
"block.betterend.hydralux_petal_block_beige": "Beige Petal Block",
|
||||
|
@ -855,5 +861,15 @@
|
|||
"block.betterend.neon_cactus_block": "Neon Cactus Block",
|
||||
"block.betterend.neon_cactus_slab": "Neon Cactus Slab",
|
||||
"block.betterend.neon_cactus_stairs": "Neon Cactus Stairs",
|
||||
"biome.betterend.jade_cave": "Jade Cave"
|
||||
"biome.betterend.jade_cave": "Jade Cave",
|
||||
"item.betterend.blossom_berry_jelly": "Blossom Berry Jelly",
|
||||
"item.betterend.aeternium_forged_plate": "Aeternium Forged Plate",
|
||||
"item.betterend.terminite_forged_plate": "Terminite Forged Plate",
|
||||
"item.betterend.thallasium_forged_plate": "Thallasium Forged Plate",
|
||||
|
||||
"attribute.name.generic.blindness_resistance": "Blindness Resistance",
|
||||
|
||||
"tooltip.armor.crystalite_set": "Set bonus: Regeneration I",
|
||||
"tooltip.armor.crystalite_chest": "Effect: Dig Speed I",
|
||||
"tooltip.armor.crystalite_boots": "Effect: Swiftness I"
|
||||
}
|
||||
|
|
|
@ -840,6 +840,9 @@
|
|||
"item.betterend.cave_pumpkin_pie": "Пирог из пещерной тыквы",
|
||||
|
||||
"item.betterend.music_disc_strange_and_alien": "§bПластинка§r",
|
||||
"item.betterend.music_disc_grasping_at_stars": "§bПластинка§r",
|
||||
"item.betterend.music_disc_endseeker": "§bПластинка§r",
|
||||
"item.betterend.music_disc_eo_dracona": "§bПластинка§r",
|
||||
|
||||
"block.betterend.hydralux_petal_block_amber": "Янтарный блок лепестков",
|
||||
"block.betterend.hydralux_petal_block_beige": "Бежевый блок лепестков",
|
||||
|
@ -874,5 +877,15 @@
|
|||
"block.betterend.neon_cactus_block": "Блок неонового кактуса",
|
||||
"block.betterend.neon_cactus_slab": "Плита из неонового кактуса",
|
||||
"block.betterend.neon_cactus_stairs": "Ступени из неонового кактуса",
|
||||
"biome.betterend.jade_cave": "Нефритовая пещера"
|
||||
"biome.betterend.jade_cave": "Нефритовая пещера",
|
||||
"item.betterend.blossom_berry_jelly": "Желе из цветущей ягоды",
|
||||
"item.betterend.aeternium_forged_plate": "Этериевая кованная пластина",
|
||||
"item.betterend.terminite_forged_plate": "Терминитовая кованная пластина",
|
||||
"item.betterend.thallasium_forged_plate": "Талласиевая кованная пластина",
|
||||
|
||||
"attribute.name.generic.blindness_resistance": "Сопротивление ослеплению",
|
||||
|
||||
"tooltip.armor.crystalite_set": "Бонус сета: Регенерация I",
|
||||
"tooltip.armor.crystalite_chest": "Эффект: Ускорение I",
|
||||
"tooltip.armor.crystalite_boots": "Эффект: Стремительность I"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "betterend:item/elytra_armored"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"predicate": {
|
||||
"broken": 1
|
||||
},
|
||||
"model": "betterend:item/elytra_armored_broken"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "betterend:item/elytra_armored_broken"
|
||||
}
|
||||
}
|
|
@ -99,6 +99,31 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"betterend.music.caves": {
|
||||
"category": "music",
|
||||
"sounds": [
|
||||
{
|
||||
"name": "betterend:music/godmode-future_rennaisance",
|
||||
"volume": 0.1,
|
||||
"stream": false
|
||||
},
|
||||
{
|
||||
"name": "betterend:music/futuremono-moonrise",
|
||||
"volume": 0.1,
|
||||
"stream": false
|
||||
},
|
||||
{
|
||||
"name": "betterend:music/emmit_fenn-wander",
|
||||
"volume": 0.1,
|
||||
"stream": false
|
||||
},
|
||||
{
|
||||
"name": "betterend:music/corbyn_kites-orbit",
|
||||
"volume": 0.1,
|
||||
"stream": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"betterend.ambient.foggy_mushroomland": {
|
||||
"category": "ambient",
|
||||
|
@ -184,6 +209,16 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"betterend.ambient.caves": {
|
||||
"category": "ambient",
|
||||
"sounds": [
|
||||
{
|
||||
"name": "betterend:ambient/caves",
|
||||
"volume": 0.5,
|
||||
"stream": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"betterend.entity.dragonfly": {
|
||||
"category": "entity",
|
||||
|
@ -242,5 +277,32 @@
|
|||
"stream": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"betterend.record.grasping_at_stars": {
|
||||
"category": "record",
|
||||
"sounds": [
|
||||
{
|
||||
"name": "betterend:records/firel-grasping_at_stars",
|
||||
"stream": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"betterend.record.endseeker": {
|
||||
"category": "record",
|
||||
"sounds": [
|
||||
{
|
||||
"name": "betterend:records/firel-endseeker",
|
||||
"stream": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"betterend.record.eo_dracona": {
|
||||
"category": "record",
|
||||
"sounds": [
|
||||
{
|
||||
"name": "betterend:records/firel-eo_dracona",
|
||||
"stream": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
BIN
src/main/resources/assets/betterend/sounds/ambient/caves.ogg
Normal file
Before Width: | Height: | Size: 725 B After Width: | Height: | Size: 690 B |
After Width: | Height: | Size: 191 B |
After Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 498 B After Width: | Height: | Size: 453 B |
After Width: | Height: | Size: 468 B |
After Width: | Height: | Size: 213 B |
After Width: | Height: | Size: 213 B |
After Width: | Height: | Size: 213 B |
Before Width: | Height: | Size: 215 B After Width: | Height: | Size: 209 B |
After Width: | Height: | Size: 191 B |
After Width: | Height: | Size: 191 B |
|
@ -8,6 +8,8 @@
|
|||
"ClientPlayNetworkHandlerMixin",
|
||||
"NamespaceResourceManagerMixin",
|
||||
"EnchantingTableBlockMixin",
|
||||
"HumanoidMobRendererMixin",
|
||||
"ArmorStandRendererMixin",
|
||||
"BackgroundRendererMixin",
|
||||
"ClientRecipeBookMixin",
|
||||
"ModelVariantMapMixin",
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
"RecipeManagerAccessor",
|
||||
"EnchantmentMenuMixin",
|
||||
"MinecraftServerMixin",
|
||||
"EndDragonFightMixin",
|
||||
"BlockBehaviourMixin",
|
||||
"DimensionTypeMixin",
|
||||
"RecipeManagerMixin",
|
||||
"ArmorItemAccessor",
|
||||
"BoneMealItemMixin",
|
||||
"CraftingMenuMixin",
|
||||
"LivingEntityMixin",
|
||||
|
@ -33,6 +33,7 @@
|
|||
"AnvilMenuMixin",
|
||||
"TagLoaderMixin",
|
||||
"EnderManMixin",
|
||||
"EndSpikeMixin",
|
||||
"MonsterMixin",
|
||||
"EntityMixin",
|
||||
"PlayerMixin",
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
],
|
||||
|
||||
"depends": {
|
||||
"fabricloader": ">=0.10.0",
|
||||
"fabric": ">=0.29.0",
|
||||
"minecraft": ">=1.16.3"
|
||||
"fabricloader": ">=0.11.0",
|
||||
"fabric": ">=0.32.0",
|
||||
"minecraft": ">=1.16.4"
|
||||
},
|
||||
"suggests": {
|
||||
"byg": ">=1.1.3",
|
||||
|
|