Merge and fix
This commit is contained in:
parent
b91c85529d
commit
ce9f4add97
548 changed files with 17517 additions and 16862 deletions
|
@ -1,64 +1,64 @@
|
|||
package ru.betterend;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.api.BetterEndPlugin;
|
||||
import ru.betterend.config.MainConfig;
|
||||
import ru.betterend.effects.EndEnchantments;
|
||||
import ru.betterend.effects.EndPotions;
|
||||
import ru.betterend.recipe.AlloyingRecipes;
|
||||
import ru.betterend.recipe.CraftingRecipes;
|
||||
import ru.betterend.recipe.FurnaceRecipes;
|
||||
import ru.betterend.recipe.SmithingRecipes;
|
||||
import ru.betterend.registry.EndBiomes;
|
||||
import ru.betterend.registry.EndBlockEntities;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndEntities;
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
import ru.betterend.registry.EndItems;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.registry.EndStructures;
|
||||
import ru.betterend.registry.EndTags;
|
||||
import ru.betterend.util.Logger;
|
||||
import ru.betterend.world.generator.BetterEndBiomeSource;
|
||||
|
||||
public class BetterEnd implements ModInitializer {
|
||||
public static final String MOD_ID = "betterend";
|
||||
public static final Logger LOGGER = Logger.get();
|
||||
public static final MainConfig CONFIG = MainConfig.getInstance();
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
EndSounds.register();
|
||||
EndItems.register();
|
||||
EndBlocks.register();
|
||||
EndBlockEntities.register();
|
||||
EndFeatures.register();
|
||||
EndEntities.register();
|
||||
EndBiomes.register();
|
||||
BetterEndBiomeSource.register();
|
||||
EndTags.register();
|
||||
EndEnchantments.register();
|
||||
EndPotions.register();
|
||||
CraftingRecipes.register();
|
||||
FurnaceRecipes.register();
|
||||
AlloyingRecipes.register();
|
||||
SmithingRecipes.register();
|
||||
EndStructures.register();
|
||||
|
||||
FabricLoader.getInstance().getEntrypoints("betterend", BetterEndPlugin.class).forEach(BetterEndPlugin::register);
|
||||
}
|
||||
|
||||
public static Identifier makeID(String path) {
|
||||
return new Identifier(MOD_ID, path);
|
||||
}
|
||||
|
||||
public static String getStringId(String id) {
|
||||
return String.format("%s:%s", MOD_ID, id);
|
||||
}
|
||||
|
||||
public static boolean isDevEnvironment() {
|
||||
return FabricLoader.getInstance().isDevelopmentEnvironment();
|
||||
}
|
||||
}
|
||||
package ru.betterend;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.api.BetterEndPlugin;
|
||||
import ru.betterend.config.MainConfig;
|
||||
import ru.betterend.effects.EndEnchantments;
|
||||
import ru.betterend.effects.EndPotions;
|
||||
import ru.betterend.recipe.AlloyingRecipes;
|
||||
import ru.betterend.recipe.CraftingRecipes;
|
||||
import ru.betterend.recipe.FurnaceRecipes;
|
||||
import ru.betterend.recipe.SmithingRecipes;
|
||||
import ru.betterend.registry.EndBiomes;
|
||||
import ru.betterend.registry.EndBlockEntities;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndEntities;
|
||||
import ru.betterend.registry.EndFeatures;
|
||||
import ru.betterend.registry.EndItems;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.registry.EndStructures;
|
||||
import ru.betterend.registry.EndTags;
|
||||
import ru.betterend.util.Logger;
|
||||
import ru.betterend.world.generator.BetterEndBiomeSource;
|
||||
|
||||
public class BetterEnd implements ModInitializer {
|
||||
public static final String MOD_ID = "betterend";
|
||||
public static final Logger LOGGER = Logger.get();
|
||||
public static final MainConfig CONFIG = MainConfig.getInstance();
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
EndSounds.register();
|
||||
EndItems.register();
|
||||
EndBlocks.register();
|
||||
EndBlockEntities.register();
|
||||
EndFeatures.register();
|
||||
EndEntities.register();
|
||||
EndBiomes.register();
|
||||
BetterEndBiomeSource.register();
|
||||
EndTags.register();
|
||||
EndEnchantments.register();
|
||||
EndPotions.register();
|
||||
CraftingRecipes.register();
|
||||
FurnaceRecipes.register();
|
||||
AlloyingRecipes.register();
|
||||
SmithingRecipes.register();
|
||||
EndStructures.register();
|
||||
|
||||
FabricLoader.getInstance().getEntrypoints("betterend", BetterEndPlugin.class).forEach(BetterEndPlugin::register);
|
||||
}
|
||||
|
||||
public static Identifier makeID(String path) {
|
||||
return new Identifier(MOD_ID, path);
|
||||
}
|
||||
|
||||
public static String getStringId(String id) {
|
||||
return String.format("%s:%s", MOD_ID, id);
|
||||
}
|
||||
|
||||
public static boolean isDevEnvironment() {
|
||||
return FabricLoader.getInstance().isDevelopmentEnvironment();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
package ru.betterend.api;
|
||||
|
||||
public interface BetterEndPlugin {
|
||||
/**
|
||||
* Alloying recipes registration.
|
||||
* See AlloyingRecipe.Builder for details.
|
||||
*/
|
||||
default void registerAlloyingRecipes() {}
|
||||
|
||||
/**
|
||||
* Smithing recipes registration.
|
||||
* See AnvilSmithingRecipe.Builder for details.
|
||||
*/
|
||||
default void registerSmithingRecipes() {}
|
||||
|
||||
/**
|
||||
* Additional biomes registration.
|
||||
* See BiomeRegistry.registerBiome for details.
|
||||
*/
|
||||
default void registerEndBiomes() {}
|
||||
|
||||
/**
|
||||
* Register other mod stuff, for example, EndHammers.
|
||||
*/
|
||||
default void registerOthers() {}
|
||||
|
||||
|
||||
public static void register(BetterEndPlugin plugin) {
|
||||
plugin.registerAlloyingRecipes();
|
||||
plugin.registerSmithingRecipes();
|
||||
plugin.registerEndBiomes();
|
||||
plugin.registerOthers();
|
||||
}
|
||||
}
|
||||
package ru.betterend.api;
|
||||
|
||||
public interface BetterEndPlugin {
|
||||
/**
|
||||
* Alloying recipes registration.
|
||||
* See AlloyingRecipe.Builder for details.
|
||||
*/
|
||||
default void registerAlloyingRecipes() {}
|
||||
|
||||
/**
|
||||
* Smithing recipes registration.
|
||||
* See AnvilSmithingRecipe.Builder for details.
|
||||
*/
|
||||
default void registerSmithingRecipes() {}
|
||||
|
||||
/**
|
||||
* Additional biomes registration.
|
||||
* See BiomeRegistry.registerBiome for details.
|
||||
*/
|
||||
default void registerEndBiomes() {}
|
||||
|
||||
/**
|
||||
* Register other mod stuff, for example, EndHammers.
|
||||
*/
|
||||
default void registerOthers() {}
|
||||
|
||||
|
||||
public static void register(BetterEndPlugin plugin) {
|
||||
plugin.registerAlloyingRecipes();
|
||||
plugin.registerSmithingRecipes();
|
||||
plugin.registerEndBiomes();
|
||||
plugin.registerOthers();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class AeterniumBlock extends BlockBase {
|
||||
|
||||
public AeterniumBlock() {
|
||||
super(FabricBlockSettings.of(Material.METAL, MaterialColor.GRAY)
|
||||
.hardness(65F)
|
||||
.resistance(1200F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.NETHERITE));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getColor(BlockState state, BlockView world, BlockPos pos) {
|
||||
return 0xFF657A7A;
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class AeterniumBlock extends BlockBase {
|
||||
|
||||
public AeterniumBlock() {
|
||||
super(FabricBlockSettings.of(Material.METAL, MaterialColor.GRAY)
|
||||
.hardness(65F)
|
||||
.resistance(1200F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.NETHERITE));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getColor(BlockState state, BlockView world, BlockPos pos) {
|
||||
return 0xFF657A7A;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class BlockStone extends BlockBase {
|
||||
|
||||
public BlockStone(MaterialColor color) {
|
||||
super(FabricBlockSettings.copyOf(Blocks.END_STONE).materialColor(color).sounds(BlockSoundGroup.STONE));
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class BlockStone extends BlockBase {
|
||||
|
||||
public BlockStone(MaterialColor color) {
|
||||
super(FabricBlockSettings.copyOf(Blocks.END_STONE).materialColor(color).sounds(BlockSoundGroup.STONE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,119 +1,119 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.NetherPortalBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import ru.betterend.client.render.ERenderLayer;
|
||||
import ru.betterend.interfaces.IRenderTypeable;
|
||||
import ru.betterend.interfaces.TeleportingEntity;
|
||||
import ru.betterend.registry.EndParticles;
|
||||
|
||||
public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable {
|
||||
public EndPortalBlock() {
|
||||
super(FabricBlockSettings.copyOf(Blocks.NETHER_PORTAL).resistance(Blocks.BEDROCK.getBlastResistance()).luminance(state -> {
|
||||
return 12;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
|
||||
if (random.nextInt(100) == 0) {
|
||||
world.playSound(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, SoundEvents.BLOCK_PORTAL_AMBIENT, SoundCategory.BLOCKS, 0.5F, random.nextFloat() * 0.4F + 0.8F, false);
|
||||
}
|
||||
|
||||
double x = pos.getX() + random.nextDouble();
|
||||
double y = pos.getY() + random.nextDouble();
|
||||
double z = pos.getZ() + random.nextDouble();
|
||||
int k = random.nextInt(2) * 2 - 1;
|
||||
if (!world.getBlockState(pos.west()).isOf(this) && !world.getBlockState(pos.east()).isOf(this)) {
|
||||
x = pos.getX() + 0.5D + 0.25D * k;
|
||||
} else {
|
||||
z = pos.getZ() + 0.5D + 0.25D * k;
|
||||
}
|
||||
|
||||
world.addParticle(EndParticles.PORTAL_SPHERE, x, y, z, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState newState, WorldAccess world, BlockPos pos, BlockPos posFrom) {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
|
||||
if (world instanceof ServerWorld && !entity.hasVehicle() && !entity.hasPassengers() && entity.canUsePortals()) {
|
||||
TeleportingEntity teleEntity = TeleportingEntity.class.cast(entity);
|
||||
if (teleEntity.hasCooldown()) return;
|
||||
boolean isOverworld = world.getRegistryKey().equals(World.OVERWORLD);
|
||||
ServerWorld destination = ((ServerWorld) world).getServer().getWorld(isOverworld ? World.END : World.OVERWORLD);
|
||||
BlockPos exitPos = this.findExitPos(destination, pos, entity);
|
||||
if (exitPos == null) return;
|
||||
if (entity instanceof ServerPlayerEntity) {
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) entity;
|
||||
player.teleport(destination, exitPos.getX(), exitPos.getY(), exitPos.getZ(), entity.yaw, entity.pitch);
|
||||
teleEntity.beSetCooldown(player.isCreative() ? 50 : 300);
|
||||
} else {
|
||||
teleEntity.beSetExitPos(exitPos);
|
||||
entity.moveToWorld(destination);
|
||||
teleEntity.beSetCooldown(300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ERenderLayer getRenderLayer() {
|
||||
return ERenderLayer.TRANSLUCENT;
|
||||
}
|
||||
|
||||
private BlockPos findExitPos(ServerWorld world, BlockPos pos, Entity entity) {
|
||||
Registry<DimensionType> registry = world.getRegistryManager().getDimensionTypes();
|
||||
double mult = registry.get(DimensionType.THE_END_ID).getCoordinateScale();
|
||||
BlockPos.Mutable basePos;
|
||||
if (world.getRegistryKey().equals(World.OVERWORLD)) {
|
||||
basePos = pos.mutableCopy().set(pos.getX() / mult, pos.getY(), pos.getZ() / mult);
|
||||
} else {
|
||||
basePos = pos.mutableCopy().set(pos.getX() * mult, pos.getY(), pos.getZ() * mult);
|
||||
}
|
||||
Direction direction = Direction.EAST;
|
||||
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
||||
for (int step = 1; step < 64; step++) {
|
||||
for (int i = 0; i < step; i++) {
|
||||
checkPos.setY(5);
|
||||
while(checkPos.getY() < world.getHeight()) {
|
||||
BlockState state = world.getBlockState(checkPos);
|
||||
if(state.isOf(this)) {
|
||||
if (state.get(AXIS).equals(Direction.Axis.X)) {
|
||||
return checkPos.add(0, 0, 1);
|
||||
} else {
|
||||
return checkPos.add(1, 0, 0);
|
||||
}
|
||||
}
|
||||
checkPos.move(Direction.UP);
|
||||
}
|
||||
checkPos.move(direction);
|
||||
}
|
||||
direction = direction.rotateYClockwise();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.NetherPortalBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import ru.betterend.client.render.ERenderLayer;
|
||||
import ru.betterend.interfaces.IRenderTypeable;
|
||||
import ru.betterend.interfaces.TeleportingEntity;
|
||||
import ru.betterend.registry.EndParticles;
|
||||
|
||||
public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable {
|
||||
public EndPortalBlock() {
|
||||
super(FabricBlockSettings.copyOf(Blocks.NETHER_PORTAL).resistance(Blocks.BEDROCK.getBlastResistance()).luminance(state -> {
|
||||
return 12;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
|
||||
if (random.nextInt(100) == 0) {
|
||||
world.playSound(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, SoundEvents.BLOCK_PORTAL_AMBIENT, SoundCategory.BLOCKS, 0.5F, random.nextFloat() * 0.4F + 0.8F, false);
|
||||
}
|
||||
|
||||
double x = pos.getX() + random.nextDouble();
|
||||
double y = pos.getY() + random.nextDouble();
|
||||
double z = pos.getZ() + random.nextDouble();
|
||||
int k = random.nextInt(2) * 2 - 1;
|
||||
if (!world.getBlockState(pos.west()).isOf(this) && !world.getBlockState(pos.east()).isOf(this)) {
|
||||
x = pos.getX() + 0.5D + 0.25D * k;
|
||||
} else {
|
||||
z = pos.getZ() + 0.5D + 0.25D * k;
|
||||
}
|
||||
|
||||
world.addParticle(EndParticles.PORTAL_SPHERE, x, y, z, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState newState, WorldAccess world, BlockPos pos, BlockPos posFrom) {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
|
||||
if (world instanceof ServerWorld && !entity.hasVehicle() && !entity.hasPassengers() && entity.canUsePortals()) {
|
||||
TeleportingEntity teleEntity = TeleportingEntity.class.cast(entity);
|
||||
if (teleEntity.hasCooldown()) return;
|
||||
boolean isOverworld = world.getRegistryKey().equals(World.OVERWORLD);
|
||||
ServerWorld destination = ((ServerWorld) world).getServer().getWorld(isOverworld ? World.END : World.OVERWORLD);
|
||||
BlockPos exitPos = this.findExitPos(destination, pos, entity);
|
||||
if (exitPos == null) return;
|
||||
if (entity instanceof ServerPlayerEntity) {
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) entity;
|
||||
player.teleport(destination, exitPos.getX(), exitPos.getY(), exitPos.getZ(), entity.yaw, entity.pitch);
|
||||
teleEntity.beSetCooldown(player.isCreative() ? 50 : 300);
|
||||
} else {
|
||||
teleEntity.beSetExitPos(exitPos);
|
||||
entity.moveToWorld(destination);
|
||||
teleEntity.beSetCooldown(300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ERenderLayer getRenderLayer() {
|
||||
return ERenderLayer.TRANSLUCENT;
|
||||
}
|
||||
|
||||
private BlockPos findExitPos(ServerWorld world, BlockPos pos, Entity entity) {
|
||||
Registry<DimensionType> registry = world.getRegistryManager().getDimensionTypes();
|
||||
double mult = registry.get(DimensionType.THE_END_ID).getCoordinateScale();
|
||||
BlockPos.Mutable basePos;
|
||||
if (world.getRegistryKey().equals(World.OVERWORLD)) {
|
||||
basePos = pos.mutableCopy().set(pos.getX() / mult, pos.getY(), pos.getZ() / mult);
|
||||
} else {
|
||||
basePos = pos.mutableCopy().set(pos.getX() * mult, pos.getY(), pos.getZ() * mult);
|
||||
}
|
||||
Direction direction = Direction.EAST;
|
||||
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
||||
for (int step = 1; step < 64; step++) {
|
||||
for (int i = 0; i < step; i++) {
|
||||
checkPos.setY(5);
|
||||
while(checkPos.getY() < world.getHeight()) {
|
||||
BlockState state = world.getBlockState(checkPos);
|
||||
if(state.isOf(this)) {
|
||||
if (state.get(AXIS).equals(Direction.Axis.X)) {
|
||||
return checkPos.add(0, 0, 1);
|
||||
} else {
|
||||
return checkPos.add(1, 0, 0);
|
||||
}
|
||||
}
|
||||
checkPos.move(Direction.UP);
|
||||
}
|
||||
checkPos.move(direction);
|
||||
}
|
||||
direction = direction.rotateYClockwise();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,140 +1,140 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.HorizontalFacingBlock;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.state.property.DirectionProperty;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.BlockMirror;
|
||||
import net.minecraft.util.BlockRotation;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.blocks.basis.BaseBlockWithEntity;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
|
||||
public class EndStoneSmelter extends BaseBlockWithEntity {
|
||||
public static final DirectionProperty FACING = HorizontalFacingBlock.FACING;
|
||||
public static final BooleanProperty LIT = Properties.LIT;
|
||||
public static final String ID = "end_stone_smelter";
|
||||
|
||||
public EndStoneSmelter() {
|
||||
super(FabricBlockSettings.of(Material.STONE, MaterialColor.GRAY)
|
||||
.hardness(4F)
|
||||
.resistance(100F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.STONE));
|
||||
this.setDefaultState(this.stateManager.getDefaultState()
|
||||
.with(FACING, Direction.NORTH)
|
||||
.with(LIT, false));
|
||||
}
|
||||
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
if (world.isClient) {
|
||||
return ActionResult.SUCCESS;
|
||||
} else {
|
||||
this.openScreen(world, pos, player);
|
||||
return ActionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
|
||||
private void openScreen(World world, BlockPos pos, PlayerEntity player) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof EndStoneSmelterBlockEntity) {
|
||||
player.openHandledScreen((NamedScreenHandlerFactory) blockEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
return this.getDefaultState().with(FACING, ctx.getPlayerFacing().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return new EndStoneSmelterBlockEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasComparatorOutput(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
|
||||
//TODO
|
||||
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState rotate(BlockState state, BlockRotation rotation) {
|
||||
return (BlockState)state.with(FACING, rotation.rotate((Direction)state.get(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState mirror(BlockState state, BlockMirror mirror) {
|
||||
return state.rotate(mirror.getRotation((Direction)state.get(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING, LIT);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
|
||||
if (state.get(LIT)) {
|
||||
double x = pos.getX() + 0.5D;
|
||||
double y = pos.getY();
|
||||
double z = pos.getZ() + 0.5D;
|
||||
if (random.nextDouble() < 0.1D) {
|
||||
world.playSound(x, y, z, SoundEvents.BLOCK_BLASTFURNACE_FIRE_CRACKLE, SoundCategory.BLOCKS, 1.0F, 1.0F, false);
|
||||
}
|
||||
|
||||
Direction direction = (Direction)state.get(FACING);
|
||||
Direction.Axis axis = direction.getAxis();
|
||||
double defOffset = random.nextDouble() * 0.6D - 0.3D;
|
||||
double offX = axis == Direction.Axis.X ? direction.getOffsetX() * 0.52D : defOffset;
|
||||
double offY = random.nextDouble() * 9.0D / 16.0D;
|
||||
double offZ = axis == Direction.Axis.Z ? direction.getOffsetZ() * 0.52D : defOffset;
|
||||
world.addParticle(ParticleTypes.SMOKE, x + offX, y + offY, z + offZ, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.HorizontalFacingBlock;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.state.property.DirectionProperty;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.BlockMirror;
|
||||
import net.minecraft.util.BlockRotation;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.blocks.basis.BaseBlockWithEntity;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
|
||||
public class EndStoneSmelter extends BaseBlockWithEntity {
|
||||
public static final DirectionProperty FACING = HorizontalFacingBlock.FACING;
|
||||
public static final BooleanProperty LIT = Properties.LIT;
|
||||
public static final String ID = "end_stone_smelter";
|
||||
|
||||
public EndStoneSmelter() {
|
||||
super(FabricBlockSettings.of(Material.STONE, MaterialColor.GRAY)
|
||||
.hardness(4F)
|
||||
.resistance(100F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.STONE));
|
||||
this.setDefaultState(this.stateManager.getDefaultState()
|
||||
.with(FACING, Direction.NORTH)
|
||||
.with(LIT, false));
|
||||
}
|
||||
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
if (world.isClient) {
|
||||
return ActionResult.SUCCESS;
|
||||
} else {
|
||||
this.openScreen(world, pos, player);
|
||||
return ActionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
|
||||
private void openScreen(World world, BlockPos pos, PlayerEntity player) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof EndStoneSmelterBlockEntity) {
|
||||
player.openHandledScreen((NamedScreenHandlerFactory) blockEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
return this.getDefaultState().with(FACING, ctx.getPlayerFacing().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return new EndStoneSmelterBlockEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasComparatorOutput(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
|
||||
//TODO
|
||||
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState rotate(BlockState state, BlockRotation rotation) {
|
||||
return (BlockState)state.with(FACING, rotation.rotate((Direction)state.get(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState mirror(BlockState state, BlockMirror mirror) {
|
||||
return state.rotate(mirror.getRotation((Direction)state.get(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING, LIT);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
|
||||
if (state.get(LIT)) {
|
||||
double x = pos.getX() + 0.5D;
|
||||
double y = pos.getY();
|
||||
double z = pos.getZ() + 0.5D;
|
||||
if (random.nextDouble() < 0.1D) {
|
||||
world.playSound(x, y, z, SoundEvents.BLOCK_BLASTFURNACE_FIRE_CRACKLE, SoundCategory.BLOCKS, 1.0F, 1.0F, false);
|
||||
}
|
||||
|
||||
Direction direction = (Direction)state.get(FACING);
|
||||
Direction.Axis axis = direction.getAxis();
|
||||
double defOffset = random.nextDouble() * 0.6D - 0.3D;
|
||||
double offX = axis == Direction.Axis.X ? direction.getOffsetX() * 0.52D : defOffset;
|
||||
double offY = random.nextDouble() * 9.0D / 16.0D;
|
||||
double offZ = axis == Direction.Axis.Z ? direction.getOffsetZ() * 0.52D : defOffset;
|
||||
world.addParticle(ParticleTypes.SMOKE, x + offX, y + offY, z + offZ, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class EnderBlock extends BlockBase {
|
||||
|
||||
public EnderBlock() {
|
||||
super(FabricBlockSettings.of(Material.STONE, MaterialColor.field_25708)
|
||||
.hardness(5F)
|
||||
.resistance(6F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.STONE));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getColor(BlockState state, BlockView world, BlockPos pos) {
|
||||
return 0xFF005548;
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class EnderBlock extends BlockBase {
|
||||
|
||||
public EnderBlock() {
|
||||
super(FabricBlockSettings.of(Material.STONE, MaterialColor.field_25708)
|
||||
.hardness(5F)
|
||||
.resistance(6F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.STONE));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getColor(BlockState state, BlockView world, BlockPos pos) {
|
||||
return 0xFF005548;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,125 +1,125 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.loot.context.LootContextParameters;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.explosion.Explosion;
|
||||
import ru.betterend.blocks.basis.BlockPedestal;
|
||||
import ru.betterend.blocks.entities.EternalPedestalEntity;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndItems;
|
||||
import ru.betterend.rituals.EternalRitual;
|
||||
|
||||
public class EternalPedestal extends BlockPedestal {
|
||||
public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVATED;
|
||||
|
||||
public EternalPedestal() {
|
||||
super(EndBlocks.FLAVOLITE_RUNED_ETERNAL);
|
||||
this.setDefaultState(this.getDefaultState().with(ACTIVATED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
|
||||
if (result.equals(ActionResult.SUCCESS)) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof EternalPedestalEntity) {
|
||||
EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity;
|
||||
BlockState updatedState = world.getBlockState(pos);
|
||||
if (pedestal.isEmpty() && updatedState.get(ACTIVATED)) {
|
||||
if (pedestal.hasRitual()) {
|
||||
EternalRitual ritual = pedestal.getRitual();
|
||||
ritual.removePortal();
|
||||
}
|
||||
world.setBlockState(pos, updatedState.with(ACTIVATED, false));
|
||||
} else {
|
||||
ItemStack itemStack = pedestal.getStack(0);
|
||||
if (itemStack.getItem() == EndItems.ETERNAL_CRYSTAL) {
|
||||
world.setBlockState(pos, updatedState.with(ACTIVATED, true));
|
||||
if (pedestal.hasRitual()) {
|
||||
pedestal.getRitual().checkStructure();
|
||||
} else {
|
||||
EternalRitual ritual = new EternalRitual(world, pos);
|
||||
ritual.checkStructure();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState newState, WorldAccess world, BlockPos pos, BlockPos posFrom) {
|
||||
BlockState updated = super.getStateForNeighborUpdate(state, direction, newState, world, pos, posFrom);
|
||||
if (!updated.isOf(this)) return updated;
|
||||
if (!this.isPlaceable(updated)) {
|
||||
return updated.with(ACTIVATED, false);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBlastResistance() {
|
||||
return Blocks.BEDROCK.getBlastResistance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDropItemsOnExplosion(Explosion explosion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
if (state.isOf(this)) {
|
||||
BlockProperties.PedestalState currentState = state.get(BlockProperties.PEDESTAL_STATE);
|
||||
if (currentState.equals(BlockProperties.PedestalState.BOTTOM) || currentState.equals(BlockProperties.PedestalState.PILLAR)) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
}
|
||||
List<ItemStack> drop = Lists.newArrayList();
|
||||
BlockEntity blockEntity = builder.getNullable(LootContextParameters.BLOCK_ENTITY);
|
||||
if (blockEntity != null && blockEntity instanceof EternalPedestalEntity) {
|
||||
EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity;
|
||||
if (!pedestal.isEmpty()) {
|
||||
drop.add(pedestal.getStack(0));
|
||||
}
|
||||
}
|
||||
return drop;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
||||
super.appendProperties(stateManager);
|
||||
stateManager.add(ACTIVATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return new EternalPedestalEntity();
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.loot.context.LootContextParameters;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.explosion.Explosion;
|
||||
import ru.betterend.blocks.basis.BlockPedestal;
|
||||
import ru.betterend.blocks.entities.EternalPedestalEntity;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndItems;
|
||||
import ru.betterend.rituals.EternalRitual;
|
||||
|
||||
public class EternalPedestal extends BlockPedestal {
|
||||
public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVATED;
|
||||
|
||||
public EternalPedestal() {
|
||||
super(EndBlocks.FLAVOLITE_RUNED_ETERNAL);
|
||||
this.setDefaultState(this.getDefaultState().with(ACTIVATED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
|
||||
if (result.equals(ActionResult.SUCCESS)) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof EternalPedestalEntity) {
|
||||
EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity;
|
||||
BlockState updatedState = world.getBlockState(pos);
|
||||
if (pedestal.isEmpty() && updatedState.get(ACTIVATED)) {
|
||||
if (pedestal.hasRitual()) {
|
||||
EternalRitual ritual = pedestal.getRitual();
|
||||
ritual.removePortal();
|
||||
}
|
||||
world.setBlockState(pos, updatedState.with(ACTIVATED, false));
|
||||
} else {
|
||||
ItemStack itemStack = pedestal.getStack(0);
|
||||
if (itemStack.getItem() == EndItems.ETERNAL_CRYSTAL) {
|
||||
world.setBlockState(pos, updatedState.with(ACTIVATED, true));
|
||||
if (pedestal.hasRitual()) {
|
||||
pedestal.getRitual().checkStructure();
|
||||
} else {
|
||||
EternalRitual ritual = new EternalRitual(world, pos);
|
||||
ritual.checkStructure();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState newState, WorldAccess world, BlockPos pos, BlockPos posFrom) {
|
||||
BlockState updated = super.getStateForNeighborUpdate(state, direction, newState, world, pos, posFrom);
|
||||
if (!updated.isOf(this)) return updated;
|
||||
if (!this.isPlaceable(updated)) {
|
||||
return updated.with(ACTIVATED, false);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBlastResistance() {
|
||||
return Blocks.BEDROCK.getBlastResistance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDropItemsOnExplosion(Explosion explosion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
if (state.isOf(this)) {
|
||||
BlockProperties.PedestalState currentState = state.get(BlockProperties.PEDESTAL_STATE);
|
||||
if (currentState.equals(BlockProperties.PedestalState.BOTTOM) || currentState.equals(BlockProperties.PedestalState.PILLAR)) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
}
|
||||
List<ItemStack> drop = Lists.newArrayList();
|
||||
BlockEntity blockEntity = builder.getNullable(LootContextParameters.BLOCK_ENTITY);
|
||||
if (blockEntity != null && blockEntity instanceof EternalPedestalEntity) {
|
||||
EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity;
|
||||
if (!pedestal.isEmpty()) {
|
||||
drop.add(pedestal.getStack(0));
|
||||
}
|
||||
}
|
||||
return drop;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
||||
super.appendProperties(stateManager);
|
||||
stateManager.add(ACTIVATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return new EternalPedestalEntity();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.explosion.Explosion;
|
||||
|
||||
public class EternalRunedFlavolite extends RunedFlavolite {
|
||||
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBlastResistance() {
|
||||
return Blocks.BEDROCK.getBlastResistance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDropItemsOnExplosion(Explosion explosion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.explosion.Explosion;
|
||||
|
||||
public class EternalRunedFlavolite extends RunedFlavolite {
|
||||
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBlastResistance() {
|
||||
return Blocks.BEDROCK.getBlastResistance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDropItemsOnExplosion(Explosion explosion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.blocks.basis.BlockPedestal;
|
||||
import ru.betterend.blocks.entities.InfusionPedestalEntity;
|
||||
|
||||
public class InfusionPedestal extends BlockPedestal {
|
||||
private static final VoxelShape SHAPE_DEFAULT;
|
||||
private static final VoxelShape SHAPE_PEDESTAL_TOP;
|
||||
|
||||
public InfusionPedestal() {
|
||||
super(Blocks.OBSIDIAN);
|
||||
this.height = 1.08F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return new InfusionPedestalEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
if (state.isOf(this)) {
|
||||
switch(state.get(STATE)) {
|
||||
case PEDESTAL_TOP: {
|
||||
return SHAPE_PEDESTAL_TOP;
|
||||
}
|
||||
case DEFAULT: {
|
||||
return SHAPE_DEFAULT;
|
||||
}
|
||||
default: {
|
||||
return super.getOutlineShape(state, world, pos, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getOutlineShape(state, world, pos, context);
|
||||
}
|
||||
|
||||
static {
|
||||
VoxelShape basinUp = Block.createCuboidShape(2, 3, 2, 14, 4, 14);
|
||||
VoxelShape basinDown = Block.createCuboidShape(0, 0, 0, 16, 3, 16);
|
||||
VoxelShape pedestalTop = Block.createCuboidShape(1, 9, 1, 15, 11, 15);
|
||||
VoxelShape pedestalDefault = Block.createCuboidShape(1, 13, 1, 15, 15, 15);
|
||||
VoxelShape pillar = Block.createCuboidShape(3, 0, 3, 13, 9, 13);
|
||||
VoxelShape pillarDefault = Block.createCuboidShape(3, 4, 3, 13, 13, 13);
|
||||
VoxelShape eyeDefault = Block.createCuboidShape(4, 15, 4, 12, 16, 12);
|
||||
VoxelShape eyeTop = Block.createCuboidShape(4, 11, 4, 12, 12, 12);
|
||||
VoxelShape basin = VoxelShapes.union(basinDown, basinUp);
|
||||
SHAPE_DEFAULT = VoxelShapes.union(basin, pillarDefault, pedestalDefault, eyeDefault);
|
||||
SHAPE_PEDESTAL_TOP = VoxelShapes.union(pillar, pedestalTop, eyeTop);
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.blocks.basis.BlockPedestal;
|
||||
import ru.betterend.blocks.entities.InfusionPedestalEntity;
|
||||
|
||||
public class InfusionPedestal extends BlockPedestal {
|
||||
private static final VoxelShape SHAPE_DEFAULT;
|
||||
private static final VoxelShape SHAPE_PEDESTAL_TOP;
|
||||
|
||||
public InfusionPedestal() {
|
||||
super(Blocks.OBSIDIAN);
|
||||
this.height = 1.08F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return new InfusionPedestalEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
if (state.isOf(this)) {
|
||||
switch(state.get(STATE)) {
|
||||
case PEDESTAL_TOP: {
|
||||
return SHAPE_PEDESTAL_TOP;
|
||||
}
|
||||
case DEFAULT: {
|
||||
return SHAPE_DEFAULT;
|
||||
}
|
||||
default: {
|
||||
return super.getOutlineShape(state, world, pos, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getOutlineShape(state, world, pos, context);
|
||||
}
|
||||
|
||||
static {
|
||||
VoxelShape basinUp = Block.createCuboidShape(2, 3, 2, 14, 4, 14);
|
||||
VoxelShape basinDown = Block.createCuboidShape(0, 0, 0, 16, 3, 16);
|
||||
VoxelShape pedestalTop = Block.createCuboidShape(1, 9, 1, 15, 11, 15);
|
||||
VoxelShape pedestalDefault = Block.createCuboidShape(1, 13, 1, 15, 15, 15);
|
||||
VoxelShape pillar = Block.createCuboidShape(3, 0, 3, 13, 9, 13);
|
||||
VoxelShape pillarDefault = Block.createCuboidShape(3, 4, 3, 13, 13, 13);
|
||||
VoxelShape eyeDefault = Block.createCuboidShape(4, 15, 4, 12, 16, 12);
|
||||
VoxelShape eyeTop = Block.createCuboidShape(4, 11, 4, 12, 12, 12);
|
||||
VoxelShape basin = VoxelShapes.union(basinDown, basinUp);
|
||||
SHAPE_DEFAULT = VoxelShapes.union(basin, pillarDefault, pedestalDefault, eyeDefault);
|
||||
SHAPE_PEDESTAL_TOP = VoxelShapes.union(pillar, pedestalTop, eyeTop);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
|
||||
public class RunedFlavolite extends BlockBase {
|
||||
public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVATED;
|
||||
|
||||
public RunedFlavolite() {
|
||||
super(FabricBlockSettings.copyOf(EndBlocks.FLAVOLITE.polished).resistance(Blocks.OBSIDIAN.getBlastResistance()).luminance(state -> {
|
||||
return state.get(ACTIVATED) ? 8 : 0;
|
||||
}));
|
||||
this.setDefaultState(stateManager.getDefaultState().with(ACTIVATED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
||||
stateManager.add(ACTIVATED);
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
|
||||
public class RunedFlavolite extends BlockBase {
|
||||
public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVATED;
|
||||
|
||||
public RunedFlavolite() {
|
||||
super(FabricBlockSettings.copyOf(EndBlocks.FLAVOLITE.polished).resistance(Blocks.OBSIDIAN.getBlastResistance()).luminance(state -> {
|
||||
return state.get(ACTIVATED) ? 8 : 0;
|
||||
}));
|
||||
this.setDefaultState(stateManager.getDefaultState().with(ACTIVATED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
||||
stateManager.add(ACTIVATED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class TerminiteBlock extends BlockBase {
|
||||
public TerminiteBlock() {
|
||||
super(FabricBlockSettings.of(Material.METAL, MaterialColor.field_25708)
|
||||
.hardness(7F)
|
||||
.resistance(9F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.METAL));
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import ru.betterend.blocks.basis.BlockBase;
|
||||
|
||||
public class TerminiteBlock extends BlockBase {
|
||||
public TerminiteBlock() {
|
||||
super(FabricBlockSettings.of(Material.METAL, MaterialColor.field_25708)
|
||||
.hardness(7F)
|
||||
.resistance(9F)
|
||||
.requiresTool()
|
||||
.sounds(BlockSoundGroup.METAL));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
package ru.betterend.blocks.basis;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.BlockWithEntity;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
public class BaseBlockWithEntity extends BlockWithEntity {
|
||||
|
||||
public BaseBlockWithEntity(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks.basis;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.BlockWithEntity;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
public class BaseBlockWithEntity extends BlockWithEntity {
|
||||
|
||||
public BaseBlockWithEntity(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockView world) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.singletonList(new ItemStack(this));
|
||||
}
|
||||
}
|
||||
|
|
146
src/main/java/ru/betterend/blocks/basis/BlockStoneLantern.java
Normal file
146
src/main/java/ru/betterend/blocks/basis/BlockStoneLantern.java
Normal file
|
@ -0,0 +1,146 @@
|
|||
package ru.betterend.blocks.basis;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.block.Waterloggable;
|
||||
import net.minecraft.client.color.block.BlockColorProvider;
|
||||
import net.minecraft.client.color.item.ItemColorProvider;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.WorldView;
|
||||
import ru.betterend.blocks.AuroraCrystalBlock;
|
||||
import ru.betterend.interfaces.IColorProvider;
|
||||
import ru.betterend.interfaces.Patterned;
|
||||
import ru.betterend.util.MHelper;
|
||||
|
||||
public class BlockStoneLantern extends BlockBaseNotFull implements IColorProvider, Waterloggable {
|
||||
public static final BooleanProperty IS_FLOOR = BooleanProperty.of("is_floor");
|
||||
public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
|
||||
|
||||
private static final VoxelShape SHAPE_CEIL = Block.createCuboidShape(3, 1, 3, 13, 16, 13);
|
||||
private static final VoxelShape SHAPE_FLOOR = Block.createCuboidShape(3, 0, 3, 13, 15, 13);
|
||||
private static final Vec3i[] COLORS = AuroraCrystalBlock.COLORS;
|
||||
|
||||
public BlockStoneLantern(Block source) {
|
||||
super(FabricBlockSettings.copyOf(source).luminance(15));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
||||
stateManager.add(IS_FLOOR, WATERLOGGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
WorldView worldView = ctx.getWorld();
|
||||
BlockPos blockPos = ctx.getBlockPos();
|
||||
Direction dir = ctx.getSide();
|
||||
if (dir == Direction.DOWN) {
|
||||
if (sideCoversSmallSquare(worldView, blockPos.up(), Direction.DOWN)) {
|
||||
boolean water = worldView.getFluidState(blockPos).getFluid() == Fluids.WATER;
|
||||
return getDefaultState().with(IS_FLOOR, false).with(WATERLOGGED, water);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sideCoversSmallSquare(worldView, blockPos.down(), Direction.UP)) {
|
||||
boolean water = worldView.getFluidState(blockPos).getFluid() == Fluids.WATER;
|
||||
return getDefaultState().with(IS_FLOOR, true).with(WATERLOGGED, water);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockColorProvider getProvider() {
|
||||
return (state, world, pos, tintIndex) -> {
|
||||
long i = (long) pos.getX() + (long) pos.getY() + (long) pos.getZ();
|
||||
double delta = i * 0.1;
|
||||
int index = MHelper.floor(delta);
|
||||
int index2 = (index + 1) & 3;
|
||||
delta -= index;
|
||||
index &= 3;
|
||||
|
||||
Vec3i color1 = COLORS[index];
|
||||
Vec3i color2 = COLORS[index2];
|
||||
|
||||
int r = MHelper.floor(MathHelper.lerp(delta, color1.getX(), color2.getX()));
|
||||
int g = MHelper.floor(MathHelper.lerp(delta, color1.getY(), color2.getY()));
|
||||
int b = MHelper.floor(MathHelper.lerp(delta, color1.getZ(), color2.getZ()));
|
||||
|
||||
return MHelper.color(r, g, b);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemColorProvider getItemProvider() {
|
||||
return (stack, tintIndex) -> {
|
||||
return MHelper.color(COLORS[3].getX(), COLORS[3].getY(), COLORS[3].getZ());
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ePos) {
|
||||
return state.get(IS_FLOOR) ? SHAPE_FLOOR : SHAPE_CEIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
|
||||
if (state.get(IS_FLOOR)) {
|
||||
return sideCoversSmallSquare(world, pos.down(), Direction.UP);
|
||||
}
|
||||
else {
|
||||
return sideCoversSmallSquare(world, pos.up(), Direction.DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction facing, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
|
||||
Boolean water = state.get(WATERLOGGED);
|
||||
if (water) {
|
||||
world.getFluidTickScheduler().schedule(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
|
||||
}
|
||||
if (!canPlaceAt(state, world, pos)) {
|
||||
return water ? Blocks.WATER.getDefaultState() : Blocks.AIR.getDefaultState();
|
||||
}
|
||||
else {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier statePatternId() {
|
||||
return Patterned.STATE_STONE_LANTERN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModelPattern(String block) {
|
||||
Identifier blockId = Registry.BLOCK.getId(this);
|
||||
if (block.contains("ceil")) {
|
||||
return Patterned.createJson(Patterned.BLOCK_STONE_LANTERN_CEIL, blockId, blockId.getPath());
|
||||
}
|
||||
return Patterned.createJson(Patterned.BLOCK_STONE_LANTERN_FLOOR, blockId, blockId.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatesPattern(Reader data) {
|
||||
Identifier blockId = Registry.BLOCK.getId(this);
|
||||
return Patterned.createJson(data, blockId, blockId.getPath());
|
||||
}
|
||||
}
|
|
@ -1,48 +1,48 @@
|
|||
package ru.betterend.blocks.entities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.rituals.EternalRitual;
|
||||
|
||||
public class EternalPedestalEntity extends PedestalBlockEntity {
|
||||
private EternalRitual linkedRitual;
|
||||
|
||||
public boolean hasRitual() {
|
||||
return this.linkedRitual != null;
|
||||
}
|
||||
|
||||
public void linkRitual(EternalRitual ritual) {
|
||||
this.linkedRitual = ritual;
|
||||
}
|
||||
|
||||
public EternalRitual getRitual() {
|
||||
return this.linkedRitual;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocation(World world, BlockPos pos) {
|
||||
super.setLocation(world, pos);
|
||||
if (hasRitual()) {
|
||||
this.linkedRitual.setWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, CompoundTag tag) {
|
||||
super.fromTag(state, tag);
|
||||
if (tag.contains("ritual")) {
|
||||
this.linkedRitual = new EternalRitual(world);
|
||||
this.linkedRitual.fromTag(tag.getCompound("ritual"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
if (this.hasRitual()) {
|
||||
tag.put("ritual", linkedRitual.toTag(new CompoundTag()));
|
||||
}
|
||||
return super.toTag(tag);
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks.entities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.rituals.EternalRitual;
|
||||
|
||||
public class EternalPedestalEntity extends PedestalBlockEntity {
|
||||
private EternalRitual linkedRitual;
|
||||
|
||||
public boolean hasRitual() {
|
||||
return this.linkedRitual != null;
|
||||
}
|
||||
|
||||
public void linkRitual(EternalRitual ritual) {
|
||||
this.linkedRitual = ritual;
|
||||
}
|
||||
|
||||
public EternalRitual getRitual() {
|
||||
return this.linkedRitual;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocation(World world, BlockPos pos) {
|
||||
super.setLocation(world, pos);
|
||||
if (hasRitual()) {
|
||||
this.linkedRitual.setWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, CompoundTag tag) {
|
||||
super.fromTag(state, tag);
|
||||
if (tag.contains("ritual")) {
|
||||
this.linkedRitual = new EternalRitual(world);
|
||||
this.linkedRitual.fromTag(tag.getCompound("ritual"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
if (this.hasRitual()) {
|
||||
tag.put("ritual", linkedRitual.toTag(new CompoundTag()));
|
||||
}
|
||||
return super.toTag(tag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
package ru.betterend.blocks.entities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import ru.betterend.rituals.InfusionRitual;
|
||||
|
||||
public class InfusionPedestalEntity extends PedestalBlockEntity {
|
||||
|
||||
private InfusionRitual activeRitual;
|
||||
|
||||
public boolean hasRitual() {
|
||||
return this.activeRitual != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, CompoundTag tag) {
|
||||
super.fromTag(state, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
return super.toTag(tag);
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks.entities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import ru.betterend.rituals.InfusionRitual;
|
||||
|
||||
public class InfusionPedestalEntity extends PedestalBlockEntity {
|
||||
|
||||
private InfusionRitual activeRitual;
|
||||
|
||||
public boolean hasRitual() {
|
||||
return this.activeRitual != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, CompoundTag tag) {
|
||||
super.fromTag(state, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
return super.toTag(tag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,105 +1,105 @@
|
|||
package ru.betterend.blocks.entities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||
import net.minecraft.util.Tickable;
|
||||
import ru.betterend.registry.EndBlockEntities;
|
||||
|
||||
public class PedestalBlockEntity extends BlockEntity implements Inventory, Tickable {
|
||||
private ItemStack activeItem = ItemStack.EMPTY;
|
||||
|
||||
private final int maxAge = 314;
|
||||
private int age;
|
||||
|
||||
public PedestalBlockEntity() {
|
||||
super(EndBlockEntities.PEDESTAL);
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public int getMaxAge() {
|
||||
return this.maxAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.activeItem = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.activeItem.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStack(int slot) {
|
||||
return this.activeItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot, int amount) {
|
||||
return this.removeStack(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot) {
|
||||
return this.activeItem = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(int slot, ItemStack stack) {
|
||||
this.activeItem = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayerUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityUpdateS2CPacket toUpdatePacket() {
|
||||
return new BlockEntityUpdateS2CPacket(pos, 32, this.toInitialChunkDataTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toInitialChunkDataTag() {
|
||||
return this.toTag(new CompoundTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, CompoundTag tag) {
|
||||
super.fromTag(state, tag);
|
||||
if (tag.contains("active_item")) {
|
||||
CompoundTag itemTag = tag.getCompound("active_item");
|
||||
this.activeItem = ItemStack.fromTag(itemTag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
tag.put("active_item", activeItem.toTag(new CompoundTag()));
|
||||
return super.toTag(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (!isEmpty()) {
|
||||
this.age++;
|
||||
if (age > maxAge) {
|
||||
this.age = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks.entities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||
import net.minecraft.util.Tickable;
|
||||
import ru.betterend.registry.EndBlockEntities;
|
||||
|
||||
public class PedestalBlockEntity extends BlockEntity implements Inventory, Tickable {
|
||||
private ItemStack activeItem = ItemStack.EMPTY;
|
||||
|
||||
private final int maxAge = 314;
|
||||
private int age;
|
||||
|
||||
public PedestalBlockEntity() {
|
||||
super(EndBlockEntities.PEDESTAL);
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public int getMaxAge() {
|
||||
return this.maxAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.activeItem = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.activeItem.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStack(int slot) {
|
||||
return this.activeItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot, int amount) {
|
||||
return this.removeStack(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot) {
|
||||
return this.activeItem = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(int slot, ItemStack stack) {
|
||||
this.activeItem = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayerUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityUpdateS2CPacket toUpdatePacket() {
|
||||
return new BlockEntityUpdateS2CPacket(pos, 32, this.toInitialChunkDataTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toInitialChunkDataTag() {
|
||||
return this.toTag(new CompoundTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, CompoundTag tag) {
|
||||
super.fromTag(state, tag);
|
||||
if (tag.contains("active_item")) {
|
||||
CompoundTag itemTag = tag.getCompound("active_item");
|
||||
this.activeItem = ItemStack.fromTag(itemTag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
tag.put("active_item", activeItem.toTag(new CompoundTag()));
|
||||
return super.toTag(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (!isEmpty()) {
|
||||
this.age++;
|
||||
if (age > maxAge) {
|
||||
this.age = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,94 +1,94 @@
|
|||
package ru.betterend.blocks.entities.render;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Quaternion;
|
||||
|
||||
public class EndCrystalRenderer {
|
||||
private static final Identifier CRYSTAL_TEXTURE = new Identifier("textures/entity/end_crystal/end_crystal.png");
|
||||
private static final Identifier CRYSTAL_BEAM_TEXTURE = new Identifier("textures/entity/end_crystal/end_crystal_beam.png");
|
||||
private static final RenderLayer CRYSTAL_BEAM_LAYER;
|
||||
private static final RenderLayer END_CRYSTAL;
|
||||
private static final ModelPart CORE;
|
||||
private static final ModelPart FRAME;
|
||||
private static final int AGE_CYCLE = 240;
|
||||
private static final float SINE_45_DEGREES;
|
||||
|
||||
public static void render(int age, int maxAge, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumerProvider, int light) {
|
||||
float k = (float) AGE_CYCLE / maxAge;
|
||||
float rotation = (age * k + tickDelta) * 3.0F;
|
||||
VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(END_CRYSTAL);
|
||||
matrices.push();
|
||||
matrices.scale(0.8F, 0.8F, 0.8F);
|
||||
matrices.translate(0.0D, -0.5D, 0.0D);
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(rotation));
|
||||
matrices.translate(0.0D, 0.8F, 0.0D);
|
||||
matrices.multiply(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true));
|
||||
FRAME.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
|
||||
matrices.scale(0.875F, 0.875F, 0.875F);
|
||||
matrices.multiply(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true));
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(rotation));
|
||||
FRAME.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
|
||||
matrices.scale(0.875F, 0.875F, 0.875F);
|
||||
matrices.multiply(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true));
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(rotation));
|
||||
CORE.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
public static void renderBeam(BlockPos start, BlockPos end, float tickDelta, int age, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
|
||||
float dx = start.getX() - end.getX() + 1.0F;
|
||||
float dy = start.getY() - end.getY() + 1.0F;
|
||||
float dz = start.getZ() - end.getZ() + 1.0F;
|
||||
float f = MathHelper.sqrt(dx * dx + dz * dz);
|
||||
float g = MathHelper.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
matrices.push();
|
||||
matrices.translate(0.0D, 2.0D, 0.0D);
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion((float)(-Math.atan2((double)dz, (double)dx)) - 1.5707964F));
|
||||
matrices.multiply(Vector3f.POSITIVE_X.getRadialQuaternion((float)(-Math.atan2((double)f, (double)dy)) - 1.5707964F));
|
||||
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(CRYSTAL_BEAM_LAYER);
|
||||
float h = 0.0F - ((float)age + tickDelta) * 0.01F;
|
||||
float i = MathHelper.sqrt(dx * dx + dy * dy + dz * dz) / 32.0F - ((float)age + tickDelta) * 0.01F;
|
||||
float k = 0.0F;
|
||||
float l = 0.75F;
|
||||
float m = 0.0F;
|
||||
MatrixStack.Entry entry = matrices.peek();
|
||||
Matrix4f matrix4f = entry.getModel();
|
||||
Matrix3f matrix3f = entry.getNormal();
|
||||
|
||||
for(int n = 1; n <= 8; ++n) {
|
||||
float o = MathHelper.sin((float)n * 6.2831855F / 8.0F) * 0.75F;
|
||||
float p = MathHelper.cos((float)n * 6.2831855F / 8.0F) * 0.75F;
|
||||
float q = (float)n / 8.0F;
|
||||
vertexConsumer.vertex(matrix4f, k * 0.2F, l * 0.2F, 0.0F).color(0, 0, 0, 255).texture(m, h).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
vertexConsumer.vertex(matrix4f, k, l, g).color(255, 255, 255, 255).texture(m, i).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
vertexConsumer.vertex(matrix4f, o, p, g).color(255, 255, 255, 255).texture(q, i).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
vertexConsumer.vertex(matrix4f, o * 0.2F, p * 0.2F, 0.0F).color(0, 0, 0, 255).texture(q, h).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
k = o;
|
||||
l = p;
|
||||
m = q;
|
||||
}
|
||||
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
static {
|
||||
END_CRYSTAL = RenderLayer.getEntityCutoutNoCull(CRYSTAL_TEXTURE);
|
||||
CRYSTAL_BEAM_LAYER = RenderLayer.getEntitySmoothCutout(CRYSTAL_BEAM_TEXTURE);
|
||||
SINE_45_DEGREES = (float) Math.sin(0.7853981633974483D);
|
||||
FRAME = new ModelPart(64, 32, 0, 0);
|
||||
FRAME.addCuboid(-4.0F, -4.0F, -4.0F, 8.0F, 8.0F, 8.0F);
|
||||
CORE = new ModelPart(64, 32, 32, 0);
|
||||
CORE.addCuboid(-4.0F, -4.0F, -4.0F, 8.0F, 8.0F, 8.0F);
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks.entities.render;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Quaternion;
|
||||
|
||||
public class EndCrystalRenderer {
|
||||
private static final Identifier CRYSTAL_TEXTURE = new Identifier("textures/entity/end_crystal/end_crystal.png");
|
||||
private static final Identifier CRYSTAL_BEAM_TEXTURE = new Identifier("textures/entity/end_crystal/end_crystal_beam.png");
|
||||
private static final RenderLayer CRYSTAL_BEAM_LAYER;
|
||||
private static final RenderLayer END_CRYSTAL;
|
||||
private static final ModelPart CORE;
|
||||
private static final ModelPart FRAME;
|
||||
private static final int AGE_CYCLE = 240;
|
||||
private static final float SINE_45_DEGREES;
|
||||
|
||||
public static void render(int age, int maxAge, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumerProvider, int light) {
|
||||
float k = (float) AGE_CYCLE / maxAge;
|
||||
float rotation = (age * k + tickDelta) * 3.0F;
|
||||
VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(END_CRYSTAL);
|
||||
matrices.push();
|
||||
matrices.scale(0.8F, 0.8F, 0.8F);
|
||||
matrices.translate(0.0D, -0.5D, 0.0D);
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(rotation));
|
||||
matrices.translate(0.0D, 0.8F, 0.0D);
|
||||
matrices.multiply(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true));
|
||||
FRAME.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
|
||||
matrices.scale(0.875F, 0.875F, 0.875F);
|
||||
matrices.multiply(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true));
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(rotation));
|
||||
FRAME.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
|
||||
matrices.scale(0.875F, 0.875F, 0.875F);
|
||||
matrices.multiply(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true));
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(rotation));
|
||||
CORE.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
public static void renderBeam(BlockPos start, BlockPos end, float tickDelta, int age, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
|
||||
float dx = start.getX() - end.getX() + 1.0F;
|
||||
float dy = start.getY() - end.getY() + 1.0F;
|
||||
float dz = start.getZ() - end.getZ() + 1.0F;
|
||||
float f = MathHelper.sqrt(dx * dx + dz * dz);
|
||||
float g = MathHelper.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
matrices.push();
|
||||
matrices.translate(0.0D, 2.0D, 0.0D);
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion((float)(-Math.atan2((double)dz, (double)dx)) - 1.5707964F));
|
||||
matrices.multiply(Vector3f.POSITIVE_X.getRadialQuaternion((float)(-Math.atan2((double)f, (double)dy)) - 1.5707964F));
|
||||
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(CRYSTAL_BEAM_LAYER);
|
||||
float h = 0.0F - ((float)age + tickDelta) * 0.01F;
|
||||
float i = MathHelper.sqrt(dx * dx + dy * dy + dz * dz) / 32.0F - ((float)age + tickDelta) * 0.01F;
|
||||
float k = 0.0F;
|
||||
float l = 0.75F;
|
||||
float m = 0.0F;
|
||||
MatrixStack.Entry entry = matrices.peek();
|
||||
Matrix4f matrix4f = entry.getModel();
|
||||
Matrix3f matrix3f = entry.getNormal();
|
||||
|
||||
for(int n = 1; n <= 8; ++n) {
|
||||
float o = MathHelper.sin((float)n * 6.2831855F / 8.0F) * 0.75F;
|
||||
float p = MathHelper.cos((float)n * 6.2831855F / 8.0F) * 0.75F;
|
||||
float q = (float)n / 8.0F;
|
||||
vertexConsumer.vertex(matrix4f, k * 0.2F, l * 0.2F, 0.0F).color(0, 0, 0, 255).texture(m, h).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
vertexConsumer.vertex(matrix4f, k, l, g).color(255, 255, 255, 255).texture(m, i).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
vertexConsumer.vertex(matrix4f, o, p, g).color(255, 255, 255, 255).texture(q, i).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
vertexConsumer.vertex(matrix4f, o * 0.2F, p * 0.2F, 0.0F).color(0, 0, 0, 255).texture(q, h).overlay(OverlayTexture.DEFAULT_UV).light(light).normal(matrix3f, 0.0F, -1.0F, 0.0F).next();
|
||||
k = o;
|
||||
l = p;
|
||||
m = q;
|
||||
}
|
||||
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
static {
|
||||
END_CRYSTAL = RenderLayer.getEntityCutoutNoCull(CRYSTAL_TEXTURE);
|
||||
CRYSTAL_BEAM_LAYER = RenderLayer.getEntitySmoothCutout(CRYSTAL_BEAM_TEXTURE);
|
||||
SINE_45_DEGREES = (float) Math.sin(0.7853981633974483D);
|
||||
FRAME = new ModelPart(64, 32, 0, 0);
|
||||
FRAME.addCuboid(-4.0F, -4.0F, -4.0F, 8.0F, 8.0F, 8.0F);
|
||||
CORE = new ModelPart(64, 32, 32, 0);
|
||||
CORE.addCuboid(-4.0F, -4.0F, -4.0F, 8.0F, 8.0F, 8.0F);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,75 +1,75 @@
|
|||
package ru.betterend.blocks.entities.render;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import ru.betterend.blocks.EternalPedestal;
|
||||
import ru.betterend.blocks.basis.BlockPedestal;
|
||||
import ru.betterend.blocks.entities.PedestalBlockEntity;
|
||||
import ru.betterend.client.render.BeamRenderer;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class PedestalItemRenderer extends BlockEntityRenderer<PedestalBlockEntity> {
|
||||
private static final Identifier BEAM_TEXTURE = new Identifier("textures/entity/end_gateway_beam.png");
|
||||
|
||||
public PedestalItemRenderer(BlockEntityRenderDispatcher dispatcher) {
|
||||
super(dispatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PedestalBlockEntity blockEntity, float tickDelta, MatrixStack matrices,
|
||||
VertexConsumerProvider vertexConsumers, int light, int overlay) {
|
||||
|
||||
if (blockEntity.isEmpty()) return;
|
||||
|
||||
BlockState state = blockEntity.getWorld().getBlockState(blockEntity.getPos());
|
||||
ItemStack activeItem = blockEntity.getStack(0);
|
||||
matrices.push();
|
||||
MinecraftClient minecraft = MinecraftClient.getInstance();
|
||||
BakedModel model = minecraft.getItemRenderer().getHeldItemModel(activeItem, blockEntity.getWorld(), null);
|
||||
Vector3f translate = model.getTransformation().ground.translation;
|
||||
BlockPedestal pedestal = (BlockPedestal) state.getBlock();
|
||||
matrices.translate(translate.getX(), translate.getY(), translate.getZ());
|
||||
matrices.translate(0.5, pedestal.getHeight(state), 0.5);
|
||||
if (activeItem.getItem() instanceof BlockItem) {
|
||||
matrices.scale(1.5F, 1.5F, 1.5F);
|
||||
} else {
|
||||
matrices.scale(1.25F, 1.25F, 1.25F);
|
||||
}
|
||||
|
||||
float rotation = (blockEntity.getAge() + tickDelta) / 25.0F + 6.0F;
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion(rotation));
|
||||
if (state.isOf(EndBlocks.ETERNAL_PEDESTAL) && state.get(EternalPedestal.ACTIVATED)) {
|
||||
float altitude = MathHelper.sin((blockEntity.getAge() + tickDelta) / 10.0F) * 0.1F + 0.1F;
|
||||
matrices.translate(0.0D, altitude, 0.0D);
|
||||
float[] colors = DyeColor.MAGENTA.getColorComponents();
|
||||
int y = blockEntity.getPos().getY();
|
||||
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getBeaconBeam(BEAM_TEXTURE, true));
|
||||
BeamRenderer.renderLightBeam(matrices, vertexConsumer, tickDelta, -y, 1024 - y, colors, 0.25F, 0.15F, 0.2F);
|
||||
}
|
||||
|
||||
if (activeItem.getItem() == Items.END_CRYSTAL) {
|
||||
EndCrystalRenderer.render(blockEntity.getAge(), blockEntity.getMaxAge(), tickDelta, matrices, vertexConsumers, light);
|
||||
} else {
|
||||
minecraft.getItemRenderer().renderItem(activeItem, ModelTransformation.Mode.GROUND, false, matrices, vertexConsumers, light, overlay, model);
|
||||
}
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
||||
package ru.betterend.blocks.entities.render;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import ru.betterend.blocks.EternalPedestal;
|
||||
import ru.betterend.blocks.basis.BlockPedestal;
|
||||
import ru.betterend.blocks.entities.PedestalBlockEntity;
|
||||
import ru.betterend.client.render.BeamRenderer;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class PedestalItemRenderer extends BlockEntityRenderer<PedestalBlockEntity> {
|
||||
private static final Identifier BEAM_TEXTURE = new Identifier("textures/entity/end_gateway_beam.png");
|
||||
|
||||
public PedestalItemRenderer(BlockEntityRenderDispatcher dispatcher) {
|
||||
super(dispatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PedestalBlockEntity blockEntity, float tickDelta, MatrixStack matrices,
|
||||
VertexConsumerProvider vertexConsumers, int light, int overlay) {
|
||||
|
||||
if (blockEntity.isEmpty()) return;
|
||||
|
||||
BlockState state = blockEntity.getWorld().getBlockState(blockEntity.getPos());
|
||||
ItemStack activeItem = blockEntity.getStack(0);
|
||||
matrices.push();
|
||||
MinecraftClient minecraft = MinecraftClient.getInstance();
|
||||
BakedModel model = minecraft.getItemRenderer().getHeldItemModel(activeItem, blockEntity.getWorld(), null);
|
||||
Vector3f translate = model.getTransformation().ground.translation;
|
||||
BlockPedestal pedestal = (BlockPedestal) state.getBlock();
|
||||
matrices.translate(translate.getX(), translate.getY(), translate.getZ());
|
||||
matrices.translate(0.5, pedestal.getHeight(state), 0.5);
|
||||
if (activeItem.getItem() instanceof BlockItem) {
|
||||
matrices.scale(1.5F, 1.5F, 1.5F);
|
||||
} else {
|
||||
matrices.scale(1.25F, 1.25F, 1.25F);
|
||||
}
|
||||
|
||||
float rotation = (blockEntity.getAge() + tickDelta) / 25.0F + 6.0F;
|
||||
matrices.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion(rotation));
|
||||
if (state.isOf(EndBlocks.ETERNAL_PEDESTAL) && state.get(EternalPedestal.ACTIVATED)) {
|
||||
float altitude = MathHelper.sin((blockEntity.getAge() + tickDelta) / 10.0F) * 0.1F + 0.1F;
|
||||
matrices.translate(0.0D, altitude, 0.0D);
|
||||
float[] colors = DyeColor.MAGENTA.getColorComponents();
|
||||
int y = blockEntity.getPos().getY();
|
||||
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getBeaconBeam(BEAM_TEXTURE, true));
|
||||
BeamRenderer.renderLightBeam(matrices, vertexConsumer, tickDelta, -y, 1024 - y, colors, 0.25F, 0.15F, 0.2F);
|
||||
}
|
||||
|
||||
if (activeItem.getItem() == Items.END_CRYSTAL) {
|
||||
EndCrystalRenderer.render(blockEntity.getAge(), blockEntity.getMaxAge(), tickDelta, matrices, vertexConsumers, light);
|
||||
} else {
|
||||
minecraft.getItemRenderer().renderItem(activeItem, ModelTransformation.Mode.GROUND, false, matrices, vertexConsumers, light, overlay, model);
|
||||
}
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,102 +1,102 @@
|
|||
package ru.betterend.client.gui;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.recipebook.BlastFurnaceRecipeBookScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class EndStoneSmelterRecipeBookScreen extends BlastFurnaceRecipeBookScreen {
|
||||
private Iterator<Item> fuelIterator;
|
||||
private Set<Item> fuels;
|
||||
private Slot fuelSlot;
|
||||
private Item currentItem;
|
||||
private float frameTime;
|
||||
|
||||
@Override
|
||||
protected Set<Item> getAllowedFuels() {
|
||||
return EndStoneSmelterBlockEntity.availableFuels().keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void slotClicked(Slot slot) {
|
||||
super.slotClicked(slot);
|
||||
if (slot != null && slot.id < this.craftingScreenHandler.getCraftingSlotCount()) {
|
||||
this.fuelSlot = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showGhostRecipe(Recipe<?> recipe, List<Slot> slots) {
|
||||
this.ghostSlots.reset();
|
||||
ItemStack result = recipe.getOutput();
|
||||
this.ghostSlots.setRecipe(recipe);
|
||||
this.ghostSlots.addSlot(Ingredient.ofStacks(result), (slots.get(3)).x, (slots.get(3)).y);
|
||||
DefaultedList<Ingredient> inputs = recipe.getPreviewInputs();
|
||||
Iterator<Ingredient> iterator = inputs.iterator();
|
||||
for(int i = 0; i < 2; i++) {
|
||||
if (!iterator.hasNext()) {
|
||||
return;
|
||||
}
|
||||
Ingredient ingredient = iterator.next();
|
||||
if (!ingredient.isEmpty()) {
|
||||
Slot slot = slots.get(i);
|
||||
this.ghostSlots.addSlot(ingredient, slot.x, slot.y);
|
||||
}
|
||||
}
|
||||
this.fuelSlot = slots.get(2);
|
||||
if (this.fuels == null) {
|
||||
this.fuels = this.getAllowedFuels();
|
||||
}
|
||||
|
||||
this.fuelIterator = this.fuels.iterator();
|
||||
this.currentItem = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGhostSlots(MatrixStack matrices, int x, int y, boolean bl, float f) {
|
||||
this.ghostSlots.draw(matrices, client, x, y, bl, f);
|
||||
if (fuelSlot != null) {
|
||||
if (!Screen.hasControlDown()) {
|
||||
this.frameTime += f;
|
||||
}
|
||||
|
||||
int slotX = this.fuelSlot.x + x;
|
||||
int slotY = this.fuelSlot.y + y;
|
||||
DrawableHelper.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822018048);
|
||||
this.client.getItemRenderer().renderInGuiWithOverrides(client.player, this.getItem().getDefaultStack(), slotX, slotY);
|
||||
RenderSystem.depthFunc(516);
|
||||
DrawableHelper.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822083583);
|
||||
RenderSystem.depthFunc(515);
|
||||
}
|
||||
}
|
||||
|
||||
private Item getItem() {
|
||||
if (this.currentItem == null || this.frameTime > 30.0F) {
|
||||
this.frameTime = 0.0F;
|
||||
if (this.fuelIterator == null || !this.fuelIterator.hasNext()) {
|
||||
if (this.fuels == null) {
|
||||
this.fuels = this.getAllowedFuels();
|
||||
}
|
||||
this.fuelIterator = this.fuels.iterator();
|
||||
}
|
||||
this.currentItem = this.fuelIterator.next();
|
||||
}
|
||||
return this.currentItem;
|
||||
}
|
||||
}
|
||||
package ru.betterend.client.gui;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.recipebook.BlastFurnaceRecipeBookScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class EndStoneSmelterRecipeBookScreen extends BlastFurnaceRecipeBookScreen {
|
||||
private Iterator<Item> fuelIterator;
|
||||
private Set<Item> fuels;
|
||||
private Slot fuelSlot;
|
||||
private Item currentItem;
|
||||
private float frameTime;
|
||||
|
||||
@Override
|
||||
protected Set<Item> getAllowedFuels() {
|
||||
return EndStoneSmelterBlockEntity.availableFuels().keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void slotClicked(Slot slot) {
|
||||
super.slotClicked(slot);
|
||||
if (slot != null && slot.id < this.craftingScreenHandler.getCraftingSlotCount()) {
|
||||
this.fuelSlot = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showGhostRecipe(Recipe<?> recipe, List<Slot> slots) {
|
||||
this.ghostSlots.reset();
|
||||
ItemStack result = recipe.getOutput();
|
||||
this.ghostSlots.setRecipe(recipe);
|
||||
this.ghostSlots.addSlot(Ingredient.ofStacks(result), (slots.get(3)).x, (slots.get(3)).y);
|
||||
DefaultedList<Ingredient> inputs = recipe.getPreviewInputs();
|
||||
Iterator<Ingredient> iterator = inputs.iterator();
|
||||
for(int i = 0; i < 2; i++) {
|
||||
if (!iterator.hasNext()) {
|
||||
return;
|
||||
}
|
||||
Ingredient ingredient = iterator.next();
|
||||
if (!ingredient.isEmpty()) {
|
||||
Slot slot = slots.get(i);
|
||||
this.ghostSlots.addSlot(ingredient, slot.x, slot.y);
|
||||
}
|
||||
}
|
||||
this.fuelSlot = slots.get(2);
|
||||
if (this.fuels == null) {
|
||||
this.fuels = this.getAllowedFuels();
|
||||
}
|
||||
|
||||
this.fuelIterator = this.fuels.iterator();
|
||||
this.currentItem = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGhostSlots(MatrixStack matrices, int x, int y, boolean bl, float f) {
|
||||
this.ghostSlots.draw(matrices, client, x, y, bl, f);
|
||||
if (fuelSlot != null) {
|
||||
if (!Screen.hasControlDown()) {
|
||||
this.frameTime += f;
|
||||
}
|
||||
|
||||
int slotX = this.fuelSlot.x + x;
|
||||
int slotY = this.fuelSlot.y + y;
|
||||
DrawableHelper.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822018048);
|
||||
this.client.getItemRenderer().renderInGuiWithOverrides(client.player, this.getItem().getDefaultStack(), slotX, slotY);
|
||||
RenderSystem.depthFunc(516);
|
||||
DrawableHelper.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822083583);
|
||||
RenderSystem.depthFunc(515);
|
||||
}
|
||||
}
|
||||
|
||||
private Item getItem() {
|
||||
if (this.currentItem == null || this.frameTime > 30.0F) {
|
||||
this.frameTime = 0.0F;
|
||||
if (this.fuelIterator == null || !this.fuelIterator.hasNext()) {
|
||||
if (this.fuels == null) {
|
||||
this.fuels = this.getAllowedFuels();
|
||||
}
|
||||
this.fuelIterator = this.fuels.iterator();
|
||||
}
|
||||
this.currentItem = this.fuelIterator.next();
|
||||
}
|
||||
return this.currentItem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,130 +1,130 @@
|
|||
package ru.betterend.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||
import net.minecraft.client.gui.widget.TexturedButtonWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.text.StringVisitable;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.BetterEnd;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class EndStoneSmelterScreen extends HandledScreen<EndStoneSmelterScreenHandler> implements RecipeBookProvider {
|
||||
|
||||
private final static Identifier RECIPE_BUTTON_TEXTURE = new Identifier("textures/gui/recipe_button.png");
|
||||
private final static Identifier BACKGROUND_TEXTURE = BetterEnd.makeID("textures/gui/smelter_gui.png");
|
||||
|
||||
public final EndStoneSmelterRecipeBookScreen recipeBook;
|
||||
private boolean narrow;
|
||||
|
||||
public EndStoneSmelterScreen(EndStoneSmelterScreenHandler handler, PlayerInventory inventory, Text title) {
|
||||
super(handler, inventory, title);
|
||||
this.recipeBook = new EndStoneSmelterRecipeBookScreen();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
super.init();
|
||||
this.narrow = this.width < 379;
|
||||
this.recipeBook.initialize(width, height, client, narrow, handler);
|
||||
this.x = this.recipeBook.findLeftEdge(narrow, width, backgroundWidth);
|
||||
this.addButton(new TexturedButtonWidget(x + 20, height / 2 - 49, 20, 18, 0, 0, 19, RECIPE_BUTTON_TEXTURE, (buttonWidget) -> {
|
||||
this.recipeBook.reset(narrow);
|
||||
this.recipeBook.toggleOpen();
|
||||
this.x = this.recipeBook.findLeftEdge(narrow, width, backgroundWidth);
|
||||
((TexturedButtonWidget) buttonWidget).setPos(this.x + 20, height / 2 - 49);
|
||||
}));
|
||||
this.titleX = (this.backgroundWidth - this.textRenderer.getWidth((StringVisitable)this.title)) / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
this.recipeBook.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
this.renderBackground(matrices);
|
||||
if (this.recipeBook.isOpen() && this.narrow) {
|
||||
this.drawBackground(matrices, delta, mouseX, mouseY);
|
||||
this.recipeBook.render(matrices, mouseX, mouseY, delta);
|
||||
} else {
|
||||
this.recipeBook.render(matrices, mouseX, mouseY, delta);
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
this.recipeBook.drawGhostSlots(matrices, x, y, true, delta);
|
||||
}
|
||||
|
||||
this.drawMouseoverTooltip(matrices, mouseX, mouseY);
|
||||
this.recipeBook.drawTooltip(matrices, x, y, mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (this.recipeBook.mouseClicked(mouseX, mouseY, button)) {
|
||||
return true;
|
||||
} else {
|
||||
return this.narrow && this.recipeBook.isOpen() ? true : super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMouseClick(Slot slot, int invSlot, int clickData, SlotActionType actionType) {
|
||||
super.onMouseClick(slot, invSlot, clickData, actionType);
|
||||
this.recipeBook.slotClicked(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
return this.recipeBook.keyPressed(keyCode, scanCode, modifiers) ? false : super.keyPressed(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button) {
|
||||
boolean isMouseOut = mouseX < left || mouseY < top || mouseX >= (left + backgroundWidth) || mouseY >= (top + backgroundHeight);
|
||||
return this.recipeBook.isClickOutsideBounds(mouseX, mouseY, x, y, backgroundWidth, backgroundHeight, button) && isMouseOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char chr, int keyCode) {
|
||||
return this.recipeBook.charTyped(chr, keyCode) ? true : super.charTyped(chr, keyCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshRecipeBook() {
|
||||
this.recipeBook.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeBookWidget getRecipeBookWidget() {
|
||||
return this.recipeBook;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground(MatrixStack matrices, float delta, int mouseX, int mouseY) {
|
||||
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.client.getTextureManager().bindTexture(BACKGROUND_TEXTURE);
|
||||
this.drawTexture(matrices, x, y, 0, 0, backgroundWidth, backgroundHeight);
|
||||
int p;
|
||||
if (handler.isBurning()) {
|
||||
p = handler.getFuelProgress();
|
||||
this.drawTexture(matrices, x + 56, y + 36 + 12 - p, 176, 12 - p, 14, p + 1);
|
||||
}
|
||||
p = handler.getSmeltProgress();
|
||||
this.drawTexture(matrices, x + 92, y + 34, 176, 14, p + 1, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed() {
|
||||
this.recipeBook.close();
|
||||
super.removed();
|
||||
}
|
||||
}
|
||||
package ru.betterend.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||
import net.minecraft.client.gui.widget.TexturedButtonWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.text.StringVisitable;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.BetterEnd;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class EndStoneSmelterScreen extends HandledScreen<EndStoneSmelterScreenHandler> implements RecipeBookProvider {
|
||||
|
||||
private final static Identifier RECIPE_BUTTON_TEXTURE = new Identifier("textures/gui/recipe_button.png");
|
||||
private final static Identifier BACKGROUND_TEXTURE = BetterEnd.makeID("textures/gui/smelter_gui.png");
|
||||
|
||||
public final EndStoneSmelterRecipeBookScreen recipeBook;
|
||||
private boolean narrow;
|
||||
|
||||
public EndStoneSmelterScreen(EndStoneSmelterScreenHandler handler, PlayerInventory inventory, Text title) {
|
||||
super(handler, inventory, title);
|
||||
this.recipeBook = new EndStoneSmelterRecipeBookScreen();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
super.init();
|
||||
this.narrow = this.width < 379;
|
||||
this.recipeBook.initialize(width, height, client, narrow, handler);
|
||||
this.x = this.recipeBook.findLeftEdge(narrow, width, backgroundWidth);
|
||||
this.addButton(new TexturedButtonWidget(x + 20, height / 2 - 49, 20, 18, 0, 0, 19, RECIPE_BUTTON_TEXTURE, (buttonWidget) -> {
|
||||
this.recipeBook.reset(narrow);
|
||||
this.recipeBook.toggleOpen();
|
||||
this.x = this.recipeBook.findLeftEdge(narrow, width, backgroundWidth);
|
||||
((TexturedButtonWidget) buttonWidget).setPos(this.x + 20, height / 2 - 49);
|
||||
}));
|
||||
this.titleX = (this.backgroundWidth - this.textRenderer.getWidth((StringVisitable)this.title)) / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
this.recipeBook.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
this.renderBackground(matrices);
|
||||
if (this.recipeBook.isOpen() && this.narrow) {
|
||||
this.drawBackground(matrices, delta, mouseX, mouseY);
|
||||
this.recipeBook.render(matrices, mouseX, mouseY, delta);
|
||||
} else {
|
||||
this.recipeBook.render(matrices, mouseX, mouseY, delta);
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
this.recipeBook.drawGhostSlots(matrices, x, y, true, delta);
|
||||
}
|
||||
|
||||
this.drawMouseoverTooltip(matrices, mouseX, mouseY);
|
||||
this.recipeBook.drawTooltip(matrices, x, y, mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (this.recipeBook.mouseClicked(mouseX, mouseY, button)) {
|
||||
return true;
|
||||
} else {
|
||||
return this.narrow && this.recipeBook.isOpen() ? true : super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMouseClick(Slot slot, int invSlot, int clickData, SlotActionType actionType) {
|
||||
super.onMouseClick(slot, invSlot, clickData, actionType);
|
||||
this.recipeBook.slotClicked(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
return this.recipeBook.keyPressed(keyCode, scanCode, modifiers) ? false : super.keyPressed(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button) {
|
||||
boolean isMouseOut = mouseX < left || mouseY < top || mouseX >= (left + backgroundWidth) || mouseY >= (top + backgroundHeight);
|
||||
return this.recipeBook.isClickOutsideBounds(mouseX, mouseY, x, y, backgroundWidth, backgroundHeight, button) && isMouseOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char chr, int keyCode) {
|
||||
return this.recipeBook.charTyped(chr, keyCode) ? true : super.charTyped(chr, keyCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshRecipeBook() {
|
||||
this.recipeBook.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeBookWidget getRecipeBookWidget() {
|
||||
return this.recipeBook;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground(MatrixStack matrices, float delta, int mouseX, int mouseY) {
|
||||
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.client.getTextureManager().bindTexture(BACKGROUND_TEXTURE);
|
||||
this.drawTexture(matrices, x, y, 0, 0, backgroundWidth, backgroundHeight);
|
||||
int p;
|
||||
if (handler.isBurning()) {
|
||||
p = handler.getFuelProgress();
|
||||
this.drawTexture(matrices, x + 56, y + 36 + 12 - p, 176, 12 - p, 14, p + 1);
|
||||
}
|
||||
p = handler.getSmeltProgress();
|
||||
this.drawTexture(matrices, x + 92, y + 34, 176, 14, p + 1, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed() {
|
||||
this.recipeBook.close();
|
||||
super.removed();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,186 +1,186 @@
|
|||
package ru.betterend.client.gui;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.inventory.SimpleInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeFinder;
|
||||
import net.minecraft.recipe.RecipeInputProvider;
|
||||
import net.minecraft.recipe.book.RecipeBookCategory;
|
||||
import net.minecraft.screen.AbstractRecipeScreenHandler;
|
||||
import net.minecraft.screen.ArrayPropertyDelegate;
|
||||
import net.minecraft.screen.PropertyDelegate;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.blocks.EndStoneSmelter;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
import ru.betterend.client.gui.slot.SmelterFuelSlot;
|
||||
import ru.betterend.client.gui.slot.SmelterOutputSlot;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
public class EndStoneSmelterScreenHandler extends AbstractRecipeScreenHandler<Inventory> {
|
||||
|
||||
public final static ScreenHandlerType<EndStoneSmelterScreenHandler> HANDLER_TYPE = ScreenHandlerRegistry.registerSimple(
|
||||
BetterEnd.makeID(EndStoneSmelter.ID), EndStoneSmelterScreenHandler::new);
|
||||
|
||||
private final Inventory inventory;
|
||||
private final PropertyDelegate propertyDelegate;
|
||||
protected final World world;
|
||||
|
||||
public EndStoneSmelterScreenHandler(int syncId, PlayerInventory playerInventory) {
|
||||
this(syncId, playerInventory, new SimpleInventory(4), new ArrayPropertyDelegate(4));
|
||||
}
|
||||
|
||||
public EndStoneSmelterScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory, PropertyDelegate propertyDelegate) {
|
||||
super(HANDLER_TYPE, syncId);
|
||||
this.inventory = inventory;
|
||||
this.propertyDelegate = propertyDelegate;
|
||||
this.world = playerInventory.player.world;
|
||||
|
||||
this.addProperties(propertyDelegate);
|
||||
this.addSlot(new Slot(inventory, 0, 45, 17));
|
||||
this.addSlot(new Slot(inventory, 1, 67, 17));
|
||||
this.addSlot(new SmelterFuelSlot(this, inventory, 2, 56, 53));
|
||||
this.addSlot(new SmelterOutputSlot(playerInventory.player, inventory, 3, 129, 35));
|
||||
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
for(int j = 0; j < 9; ++j) {
|
||||
this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < 9; ++i) {
|
||||
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateRecipeFinder(RecipeFinder finder) {
|
||||
if (inventory instanceof RecipeInputProvider) {
|
||||
((RecipeInputProvider) inventory).provideRecipeInputs(finder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCraftingSlots() {
|
||||
this.inventory.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Recipe<? super Inventory> recipe) {
|
||||
return recipe.matches(this.inventory, this.world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingResultSlotIndex() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingWidth() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingSlotCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeBookCategory getCategory() {
|
||||
return RecipeBookCategory.BLAST_FURNACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(PlayerEntity player) {
|
||||
return this.inventory.canPlayerUse(player);
|
||||
}
|
||||
|
||||
protected boolean isSmeltable(ItemStack itemStack) {
|
||||
return this.world.getRecipeManager().getFirstMatch(AlloyingRecipe.TYPE, new SimpleInventory(new ItemStack[]{itemStack}), this.world).isPresent();
|
||||
}
|
||||
|
||||
public boolean isFuel(ItemStack itemStack) {
|
||||
return EndStoneSmelterBlockEntity.canUseAsFuel(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack transferSlot(PlayerEntity player, int index) {
|
||||
ItemStack itemStack = ItemStack.EMPTY;
|
||||
Slot slot = this.slots.get(index);
|
||||
if (slot != null && slot.hasStack()) {
|
||||
ItemStack itemStack2 = slot.getStack();
|
||||
itemStack = itemStack2.copy();
|
||||
if (index == 3) {
|
||||
if (insertItem(itemStack2, 4, 40, true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
slot.onStackChanged(itemStack2, itemStack);
|
||||
} else if (index != 2 && index != 1 && index != 0) {
|
||||
if (isSmeltable(itemStack2)) {
|
||||
if (!insertItem(itemStack2, 0, 2, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (isFuel(itemStack2)) {
|
||||
if (!this.insertItem(itemStack2, 2, 3, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (index >= 4 && index < 31) {
|
||||
if (!insertItem(itemStack2, 31, 40, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (index >= 31 && index < 40 && !insertItem(itemStack2, 4, 31, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!insertItem(itemStack2, 4, 40, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (itemStack2.isEmpty()) {
|
||||
slot.setStack(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.markDirty();
|
||||
}
|
||||
|
||||
if (itemStack2.getCount() == itemStack.getCount()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
slot.onTakeItem(player, itemStack2);
|
||||
}
|
||||
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getSmeltProgress() {
|
||||
int time = this.propertyDelegate.get(2);
|
||||
int timeTotal = this.propertyDelegate.get(3);
|
||||
return timeTotal != 0 && time != 0 ? time * 24 / timeTotal : 0;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getFuelProgress() {
|
||||
int fuelTime = this.propertyDelegate.get(1);
|
||||
if (fuelTime == 0) {
|
||||
fuelTime = 200;
|
||||
}
|
||||
return this.propertyDelegate.get(0) * 13 / fuelTime;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public boolean isBurning() {
|
||||
return this.propertyDelegate.get(0) > 0;
|
||||
}
|
||||
}
|
||||
package ru.betterend.client.gui;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.inventory.SimpleInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeFinder;
|
||||
import net.minecraft.recipe.RecipeInputProvider;
|
||||
import net.minecraft.recipe.book.RecipeBookCategory;
|
||||
import net.minecraft.screen.AbstractRecipeScreenHandler;
|
||||
import net.minecraft.screen.ArrayPropertyDelegate;
|
||||
import net.minecraft.screen.PropertyDelegate;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.blocks.EndStoneSmelter;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
import ru.betterend.client.gui.slot.SmelterFuelSlot;
|
||||
import ru.betterend.client.gui.slot.SmelterOutputSlot;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
public class EndStoneSmelterScreenHandler extends AbstractRecipeScreenHandler<Inventory> {
|
||||
|
||||
public final static ScreenHandlerType<EndStoneSmelterScreenHandler> HANDLER_TYPE = ScreenHandlerRegistry.registerSimple(
|
||||
BetterEnd.makeID(EndStoneSmelter.ID), EndStoneSmelterScreenHandler::new);
|
||||
|
||||
private final Inventory inventory;
|
||||
private final PropertyDelegate propertyDelegate;
|
||||
protected final World world;
|
||||
|
||||
public EndStoneSmelterScreenHandler(int syncId, PlayerInventory playerInventory) {
|
||||
this(syncId, playerInventory, new SimpleInventory(4), new ArrayPropertyDelegate(4));
|
||||
}
|
||||
|
||||
public EndStoneSmelterScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory, PropertyDelegate propertyDelegate) {
|
||||
super(HANDLER_TYPE, syncId);
|
||||
this.inventory = inventory;
|
||||
this.propertyDelegate = propertyDelegate;
|
||||
this.world = playerInventory.player.world;
|
||||
|
||||
this.addProperties(propertyDelegate);
|
||||
this.addSlot(new Slot(inventory, 0, 45, 17));
|
||||
this.addSlot(new Slot(inventory, 1, 67, 17));
|
||||
this.addSlot(new SmelterFuelSlot(this, inventory, 2, 56, 53));
|
||||
this.addSlot(new SmelterOutputSlot(playerInventory.player, inventory, 3, 129, 35));
|
||||
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
for(int j = 0; j < 9; ++j) {
|
||||
this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < 9; ++i) {
|
||||
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateRecipeFinder(RecipeFinder finder) {
|
||||
if (inventory instanceof RecipeInputProvider) {
|
||||
((RecipeInputProvider) inventory).provideRecipeInputs(finder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCraftingSlots() {
|
||||
this.inventory.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Recipe<? super Inventory> recipe) {
|
||||
return recipe.matches(this.inventory, this.world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingResultSlotIndex() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingWidth() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftingSlotCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeBookCategory getCategory() {
|
||||
return RecipeBookCategory.BLAST_FURNACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(PlayerEntity player) {
|
||||
return this.inventory.canPlayerUse(player);
|
||||
}
|
||||
|
||||
protected boolean isSmeltable(ItemStack itemStack) {
|
||||
return this.world.getRecipeManager().getFirstMatch(AlloyingRecipe.TYPE, new SimpleInventory(new ItemStack[]{itemStack}), this.world).isPresent();
|
||||
}
|
||||
|
||||
public boolean isFuel(ItemStack itemStack) {
|
||||
return EndStoneSmelterBlockEntity.canUseAsFuel(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack transferSlot(PlayerEntity player, int index) {
|
||||
ItemStack itemStack = ItemStack.EMPTY;
|
||||
Slot slot = this.slots.get(index);
|
||||
if (slot != null && slot.hasStack()) {
|
||||
ItemStack itemStack2 = slot.getStack();
|
||||
itemStack = itemStack2.copy();
|
||||
if (index == 3) {
|
||||
if (insertItem(itemStack2, 4, 40, true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
slot.onStackChanged(itemStack2, itemStack);
|
||||
} else if (index != 2 && index != 1 && index != 0) {
|
||||
if (isSmeltable(itemStack2)) {
|
||||
if (!insertItem(itemStack2, 0, 2, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (isFuel(itemStack2)) {
|
||||
if (!this.insertItem(itemStack2, 2, 3, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (index >= 4 && index < 31) {
|
||||
if (!insertItem(itemStack2, 31, 40, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (index >= 31 && index < 40 && !insertItem(itemStack2, 4, 31, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!insertItem(itemStack2, 4, 40, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (itemStack2.isEmpty()) {
|
||||
slot.setStack(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.markDirty();
|
||||
}
|
||||
|
||||
if (itemStack2.getCount() == itemStack.getCount()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
slot.onTakeItem(player, itemStack2);
|
||||
}
|
||||
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getSmeltProgress() {
|
||||
int time = this.propertyDelegate.get(2);
|
||||
int timeTotal = this.propertyDelegate.get(3);
|
||||
return timeTotal != 0 && time != 0 ? time * 24 / timeTotal : 0;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public int getFuelProgress() {
|
||||
int fuelTime = this.propertyDelegate.get(1);
|
||||
if (fuelTime == 0) {
|
||||
fuelTime = 200;
|
||||
}
|
||||
return this.propertyDelegate.get(0) * 13 / fuelTime;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public boolean isBurning() {
|
||||
return this.propertyDelegate.get(0) > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
package ru.betterend.client.gui.slot;
|
||||
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.FurnaceFuelSlot;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import ru.betterend.client.gui.EndStoneSmelterScreenHandler;
|
||||
|
||||
public class SmelterFuelSlot extends Slot {
|
||||
|
||||
private final EndStoneSmelterScreenHandler handler;
|
||||
|
||||
public SmelterFuelSlot(EndStoneSmelterScreenHandler handler, Inventory inventory, int index, int x, int y) {
|
||||
super(inventory, index, x, y);
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public boolean canInsert(ItemStack stack) {
|
||||
return this.handler.isFuel(stack) || FurnaceFuelSlot.isBucket(stack);
|
||||
}
|
||||
|
||||
public int getMaxItemCount(ItemStack stack) {
|
||||
return FurnaceFuelSlot.isBucket(stack) ? 1 : super.getMaxItemCount(stack);
|
||||
}
|
||||
}
|
||||
package ru.betterend.client.gui.slot;
|
||||
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.FurnaceFuelSlot;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import ru.betterend.client.gui.EndStoneSmelterScreenHandler;
|
||||
|
||||
public class SmelterFuelSlot extends Slot {
|
||||
|
||||
private final EndStoneSmelterScreenHandler handler;
|
||||
|
||||
public SmelterFuelSlot(EndStoneSmelterScreenHandler handler, Inventory inventory, int index, int x, int y) {
|
||||
super(inventory, index, x, y);
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public boolean canInsert(ItemStack stack) {
|
||||
return this.handler.isFuel(stack) || FurnaceFuelSlot.isBucket(stack);
|
||||
}
|
||||
|
||||
public int getMaxItemCount(ItemStack stack) {
|
||||
return FurnaceFuelSlot.isBucket(stack) ? 1 : super.getMaxItemCount(stack);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,49 +1,49 @@
|
|||
package ru.betterend.client.gui.slot;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
|
||||
public class SmelterOutputSlot extends Slot {
|
||||
|
||||
private PlayerEntity player;
|
||||
private int amount;
|
||||
|
||||
public SmelterOutputSlot(PlayerEntity player, Inventory inventory, int index, int x, int y) {
|
||||
super(inventory, index, x, y);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public boolean canInsert(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ItemStack takeStack(int amount) {
|
||||
if (this.hasStack()) {
|
||||
this.amount += Math.min(amount, this.getStack().getCount());
|
||||
}
|
||||
|
||||
return super.takeStack(amount);
|
||||
}
|
||||
|
||||
public ItemStack onTakeItem(PlayerEntity player, ItemStack stack) {
|
||||
this.onCrafted(stack);
|
||||
super.onTakeItem(player, stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
protected void onCrafted(ItemStack stack, int amount) {
|
||||
this.amount += amount;
|
||||
this.onCrafted(stack);
|
||||
}
|
||||
|
||||
protected void onCrafted(ItemStack stack) {
|
||||
stack.onCraft(this.player.world, this.player, this.amount);
|
||||
if (!this.player.world.isClient && this.inventory instanceof EndStoneSmelterBlockEntity) {
|
||||
((EndStoneSmelterBlockEntity) this.inventory).dropExperience(player);
|
||||
}
|
||||
this.amount = 0;
|
||||
}
|
||||
}
|
||||
package ru.betterend.client.gui.slot;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
|
||||
public class SmelterOutputSlot extends Slot {
|
||||
|
||||
private PlayerEntity player;
|
||||
private int amount;
|
||||
|
||||
public SmelterOutputSlot(PlayerEntity player, Inventory inventory, int index, int x, int y) {
|
||||
super(inventory, index, x, y);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public boolean canInsert(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ItemStack takeStack(int amount) {
|
||||
if (this.hasStack()) {
|
||||
this.amount += Math.min(amount, this.getStack().getCount());
|
||||
}
|
||||
|
||||
return super.takeStack(amount);
|
||||
}
|
||||
|
||||
public ItemStack onTakeItem(PlayerEntity player, ItemStack stack) {
|
||||
this.onCrafted(stack);
|
||||
super.onTakeItem(player, stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
protected void onCrafted(ItemStack stack, int amount) {
|
||||
this.amount += amount;
|
||||
this.onCrafted(stack);
|
||||
}
|
||||
|
||||
protected void onCrafted(ItemStack stack) {
|
||||
stack.onCraft(this.player.world, this.player, this.amount);
|
||||
if (!this.player.world.isClient && this.inventory instanceof EndStoneSmelterBlockEntity) {
|
||||
((EndStoneSmelterBlockEntity) this.inventory).dropExperience(player);
|
||||
}
|
||||
this.amount = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +1,62 @@
|
|||
package ru.betterend.client.render;
|
||||
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
|
||||
public class BeamRenderer {
|
||||
public static void renderLightBeam(MatrixStack matrixStack, VertexConsumer vertexConsumer, float tick, int minY, int maxY, float[] colors, float alpha, float h, float k) {
|
||||
int m = minY + maxY;
|
||||
|
||||
float o = maxY < 0 ? tick : -tick;
|
||||
float p = MathHelper.fractionalPart(o * 0.2F - (float) MathHelper.floor(o * 0.1F));
|
||||
float red = colors[0];
|
||||
float green = colors[1];
|
||||
float blue = colors[2];
|
||||
|
||||
matrixStack.push();
|
||||
matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(tick * 2.25F - 45.0F));
|
||||
float af = 0.0F;
|
||||
float ai = 0.0F;
|
||||
float aj = -h;
|
||||
float aa = -h;
|
||||
float ap = -1.0F + p;
|
||||
float aq = (float) maxY * (0.5F / h) + ap;
|
||||
|
||||
renderBeam(matrixStack, vertexConsumer, red, green, blue, alpha, minY, m, 0.0F, h, h, 0.0F, aj, 0.0F, 0.0F, aa, 0.0F, 1.0F, aq, ap);
|
||||
matrixStack.pop();
|
||||
|
||||
af = -k;
|
||||
float ag = -k;
|
||||
ai = -k;
|
||||
aj = -k;
|
||||
ap = -1.0F + p;
|
||||
aq = (float) maxY + ap;
|
||||
renderBeam(matrixStack, vertexConsumer, red, green, blue, alpha, minY, m, af, ag, k, ai, aj, k, k, k, 0.0F, 1.0F, aq, ap);
|
||||
}
|
||||
|
||||
private static void renderBeam(MatrixStack matrixStack, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, int j, int k, float l, float m, float n, float o, float p, float q, float r, float s, float t, float u, float v, float w) {
|
||||
MatrixStack.Entry entry = matrixStack.peek();
|
||||
Matrix4f matrix4f = entry.getModel();
|
||||
Matrix3f matrix3f = entry.getNormal();
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, l, m, n, o, t, u, v, w);
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, r, s, p, q, t, u, v, w);
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, n, o, r, s, t, u, v, w);
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, p, q, l, m, t, u, v, w);
|
||||
}
|
||||
|
||||
private static void renderBeam(Matrix4f matrix4f, Matrix3f matrix3f, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, int j, int k, float l, float m, float n, float o, float p, float q, float r, float s) {
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, k, l, m, q, r);
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, l, m, q, s);
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, n, o, p, s);
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, k, n, o, p, r);
|
||||
}
|
||||
|
||||
private static void addVertex(Matrix4f matrix4f, Matrix3f matrix3f, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, float y, float x, float l, float m, float n) {
|
||||
vertexConsumer.vertex(matrix4f, x, y, l).color(red, green, blue, alpha).texture(m, n).overlay(OverlayTexture.DEFAULT_UV).light(15728880).normal(matrix3f, 0.0F, 1.0F, 0.0F).next();
|
||||
}
|
||||
}
|
||||
package ru.betterend.client.render;
|
||||
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Matrix3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
|
||||
public class BeamRenderer {
|
||||
public static void renderLightBeam(MatrixStack matrixStack, VertexConsumer vertexConsumer, float tick, int minY, int maxY, float[] colors, float alpha, float h, float k) {
|
||||
int m = minY + maxY;
|
||||
|
||||
float o = maxY < 0 ? tick : -tick;
|
||||
float p = MathHelper.fractionalPart(o * 0.2F - (float) MathHelper.floor(o * 0.1F));
|
||||
float red = colors[0];
|
||||
float green = colors[1];
|
||||
float blue = colors[2];
|
||||
|
||||
matrixStack.push();
|
||||
matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(tick * 2.25F - 45.0F));
|
||||
float af = 0.0F;
|
||||
float ai = 0.0F;
|
||||
float aj = -h;
|
||||
float aa = -h;
|
||||
float ap = -1.0F + p;
|
||||
float aq = (float) maxY * (0.5F / h) + ap;
|
||||
|
||||
renderBeam(matrixStack, vertexConsumer, red, green, blue, alpha, minY, m, 0.0F, h, h, 0.0F, aj, 0.0F, 0.0F, aa, 0.0F, 1.0F, aq, ap);
|
||||
matrixStack.pop();
|
||||
|
||||
af = -k;
|
||||
float ag = -k;
|
||||
ai = -k;
|
||||
aj = -k;
|
||||
ap = -1.0F + p;
|
||||
aq = (float) maxY + ap;
|
||||
renderBeam(matrixStack, vertexConsumer, red, green, blue, alpha, minY, m, af, ag, k, ai, aj, k, k, k, 0.0F, 1.0F, aq, ap);
|
||||
}
|
||||
|
||||
private static void renderBeam(MatrixStack matrixStack, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, int j, int k, float l, float m, float n, float o, float p, float q, float r, float s, float t, float u, float v, float w) {
|
||||
MatrixStack.Entry entry = matrixStack.peek();
|
||||
Matrix4f matrix4f = entry.getModel();
|
||||
Matrix3f matrix3f = entry.getNormal();
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, l, m, n, o, t, u, v, w);
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, r, s, p, q, t, u, v, w);
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, n, o, r, s, t, u, v, w);
|
||||
renderBeam(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, k, p, q, l, m, t, u, v, w);
|
||||
}
|
||||
|
||||
private static void renderBeam(Matrix4f matrix4f, Matrix3f matrix3f, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, int j, int k, float l, float m, float n, float o, float p, float q, float r, float s) {
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, k, l, m, q, r);
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, l, m, q, s);
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, j, n, o, p, s);
|
||||
addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, k, n, o, p, r);
|
||||
}
|
||||
|
||||
private static void addVertex(Matrix4f matrix4f, Matrix3f matrix3f, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, float y, float x, float l, float m, float n) {
|
||||
vertexConsumer.vertex(matrix4f, x, y, l).color(red, green, blue, alpha).texture(m, n).overlay(OverlayTexture.DEFAULT_UV).light(15728880).normal(matrix3f, 0.0F, 1.0F, 0.0F).next();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ru.betterend.client.render;
|
||||
|
||||
public enum ERenderLayer {
|
||||
CUTOUT,
|
||||
TRANSLUCENT;
|
||||
}
|
||||
package ru.betterend.client.render;
|
||||
|
||||
public enum ERenderLayer {
|
||||
CUTOUT,
|
||||
TRANSLUCENT;
|
||||
}
|
||||
|
|
|
@ -1,111 +1,111 @@
|
|||
package ru.betterend.compat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.TransferRecipeDisplay;
|
||||
import me.shedaniel.rei.server.ContainerInfo;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.recipe.BlastingRecipe;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
public class REIAlloyingDisplay implements TransferRecipeDisplay {
|
||||
|
||||
private static List<EntryStack> fuel;
|
||||
|
||||
private Recipe<?> recipe;
|
||||
private List<List<EntryStack>> input;
|
||||
private List<EntryStack> output;
|
||||
private float xp;
|
||||
private double smeltTime;
|
||||
|
||||
public REIAlloyingDisplay(AlloyingRecipe recipe) {
|
||||
this.recipe = recipe;
|
||||
this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
|
||||
this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
|
||||
this.xp = recipe.getExperience();
|
||||
this.smeltTime = recipe.getSmeltTime();
|
||||
}
|
||||
|
||||
public REIAlloyingDisplay(BlastingRecipe recipe) {
|
||||
this.recipe = recipe;
|
||||
this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
|
||||
this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
|
||||
this.xp = recipe.getExperience();
|
||||
this.smeltTime = recipe.getCookTime();
|
||||
}
|
||||
|
||||
public static List<EntryStack> getFuel() {
|
||||
return fuel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<Identifier> getRecipeLocation() {
|
||||
return Optional.ofNullable(recipe).map(Recipe::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getInputEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getResultingEntries() {
|
||||
return Collections.singletonList(output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier getRecipeCategory() {
|
||||
return AlloyingRecipe.ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getRequiredEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
public float getXp() {
|
||||
return this.xp;
|
||||
}
|
||||
|
||||
public double getSmeltTime() {
|
||||
return this.smeltTime;
|
||||
}
|
||||
|
||||
public Optional<Recipe<?>> getOptionalRecipe() {
|
||||
return Optional.ofNullable(recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<ScreenHandler> containerInfo, ScreenHandler container) {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
static {
|
||||
fuel = EndStoneSmelterBlockEntity.availableFuels().keySet().stream()
|
||||
.map(Item::getDefaultStack).map(EntryStack::create)
|
||||
.map(e -> e.setting(EntryStack.Settings.TOOLTIP_APPEND_EXTRA, stack -> Collections.singletonList(new TranslatableText("category.rei.smelting.fuel")
|
||||
.formatted(Formatting.YELLOW)))).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
package ru.betterend.compat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.TransferRecipeDisplay;
|
||||
import me.shedaniel.rei.server.ContainerInfo;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.recipe.BlastingRecipe;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
public class REIAlloyingDisplay implements TransferRecipeDisplay {
|
||||
|
||||
private static List<EntryStack> fuel;
|
||||
|
||||
private Recipe<?> recipe;
|
||||
private List<List<EntryStack>> input;
|
||||
private List<EntryStack> output;
|
||||
private float xp;
|
||||
private double smeltTime;
|
||||
|
||||
public REIAlloyingDisplay(AlloyingRecipe recipe) {
|
||||
this.recipe = recipe;
|
||||
this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
|
||||
this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
|
||||
this.xp = recipe.getExperience();
|
||||
this.smeltTime = recipe.getSmeltTime();
|
||||
}
|
||||
|
||||
public REIAlloyingDisplay(BlastingRecipe recipe) {
|
||||
this.recipe = recipe;
|
||||
this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
|
||||
this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
|
||||
this.xp = recipe.getExperience();
|
||||
this.smeltTime = recipe.getCookTime();
|
||||
}
|
||||
|
||||
public static List<EntryStack> getFuel() {
|
||||
return fuel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<Identifier> getRecipeLocation() {
|
||||
return Optional.ofNullable(recipe).map(Recipe::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getInputEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getResultingEntries() {
|
||||
return Collections.singletonList(output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier getRecipeCategory() {
|
||||
return AlloyingRecipe.ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getRequiredEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
public float getXp() {
|
||||
return this.xp;
|
||||
}
|
||||
|
||||
public double getSmeltTime() {
|
||||
return this.smeltTime;
|
||||
}
|
||||
|
||||
public Optional<Recipe<?>> getOptionalRecipe() {
|
||||
return Optional.ofNullable(recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<ScreenHandler> containerInfo, ScreenHandler container) {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
static {
|
||||
fuel = EndStoneSmelterBlockEntity.availableFuels().keySet().stream()
|
||||
.map(Item::getDefaultStack).map(EntryStack::create)
|
||||
.map(e -> e.setting(EntryStack.Settings.TOOLTIP_APPEND_EXTRA, stack -> Collections.singletonList(new TranslatableText("category.rei.smelting.fuel")
|
||||
.formatted(Formatting.YELLOW)))).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,84 +1,84 @@
|
|||
package ru.betterend.compat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import me.shedaniel.math.Point;
|
||||
import me.shedaniel.math.Rectangle;
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.TransferRecipeCategory;
|
||||
import me.shedaniel.rei.api.widgets.Widgets;
|
||||
import me.shedaniel.rei.gui.entries.RecipeEntry;
|
||||
import me.shedaniel.rei.gui.entries.SimpleRecipeEntry;
|
||||
import me.shedaniel.rei.gui.widget.Widget;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.util.LangUtil;
|
||||
|
||||
public class REIAnvilCategory implements TransferRecipeCategory<REIAnvilDisplay> {
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier getIdentifier() {
|
||||
return REIPlugin.SMITHING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getCategoryName() {
|
||||
return LangUtil.translate(Blocks.ANVIL.getTranslationKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntryStack getLogo() {
|
||||
return REIPlugin.ANVIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<Widget> setupDisplay(REIAnvilDisplay display, Rectangle bounds) {
|
||||
Point startPoint = new Point(bounds.getCenterX() - 41, bounds.y + 10);
|
||||
List<Widget> widgets = Lists.newArrayList();
|
||||
widgets.add(Widgets.createRecipeBase(bounds));
|
||||
int x = startPoint.x + 10;
|
||||
int y = startPoint.y;
|
||||
widgets.add(Widgets.createResultSlotBackground(new Point(x + 61, y + 4)));
|
||||
List<List<EntryStack>> inputEntries = display.getInputEntries();
|
||||
widgets.add(Widgets.createArrow(new Point(x + 24, y + 3)));
|
||||
widgets.add(Widgets.createLabel(new Point(bounds.x + bounds.width - 5, bounds.y + bounds.height - 12),
|
||||
new TranslatableText("category.rei.damage.amount&dmg", display.getDamage())).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB));
|
||||
widgets.add(Widgets.createSlot(new Point(x - 20, y + 3)).entries(inputEntries.get(0)).markInput());
|
||||
widgets.add(Widgets.createSlot(new Point(x + 1, y + 3)).entries(inputEntries.get(1)).markInput());
|
||||
widgets.add(Widgets.createSlot(new Point(x + 61, y + 4)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
|
||||
return widgets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderRedSlots(MatrixStack matrices, List<Widget> widgets, Rectangle bounds, REIAnvilDisplay display,
|
||||
IntList redSlots) {
|
||||
Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 27);
|
||||
matrices.push();
|
||||
matrices.translate(0, 0, 400);
|
||||
if (redSlots.contains(0)) {
|
||||
DrawableHelper.fill(matrices, startPoint.x - 20, startPoint.y + 3, startPoint.x - 20 + 16, startPoint.y + 3 + 16, 1090453504);
|
||||
DrawableHelper.fill(matrices, startPoint.x + 1, startPoint.y + 3, startPoint.x + 1 + 16, startPoint.y + 3 + 16, 1090453504);
|
||||
}
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RecipeEntry getSimpleRenderer(REIAnvilDisplay recipe) {
|
||||
return SimpleRecipeEntry.from(Collections.singletonList(recipe.getInputEntries().get(0)), recipe.getResultingEntries());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplayHeight() {
|
||||
return 49;
|
||||
}
|
||||
|
||||
}
|
||||
package ru.betterend.compat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import me.shedaniel.math.Point;
|
||||
import me.shedaniel.math.Rectangle;
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.TransferRecipeCategory;
|
||||
import me.shedaniel.rei.api.widgets.Widgets;
|
||||
import me.shedaniel.rei.gui.entries.RecipeEntry;
|
||||
import me.shedaniel.rei.gui.entries.SimpleRecipeEntry;
|
||||
import me.shedaniel.rei.gui.widget.Widget;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.util.LangUtil;
|
||||
|
||||
public class REIAnvilCategory implements TransferRecipeCategory<REIAnvilDisplay> {
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier getIdentifier() {
|
||||
return REIPlugin.SMITHING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getCategoryName() {
|
||||
return LangUtil.translate(Blocks.ANVIL.getTranslationKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntryStack getLogo() {
|
||||
return REIPlugin.ANVIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<Widget> setupDisplay(REIAnvilDisplay display, Rectangle bounds) {
|
||||
Point startPoint = new Point(bounds.getCenterX() - 41, bounds.y + 10);
|
||||
List<Widget> widgets = Lists.newArrayList();
|
||||
widgets.add(Widgets.createRecipeBase(bounds));
|
||||
int x = startPoint.x + 10;
|
||||
int y = startPoint.y;
|
||||
widgets.add(Widgets.createResultSlotBackground(new Point(x + 61, y + 4)));
|
||||
List<List<EntryStack>> inputEntries = display.getInputEntries();
|
||||
widgets.add(Widgets.createArrow(new Point(x + 24, y + 3)));
|
||||
widgets.add(Widgets.createLabel(new Point(bounds.x + bounds.width - 5, bounds.y + bounds.height - 12),
|
||||
new TranslatableText("category.rei.damage.amount&dmg", display.getDamage())).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB));
|
||||
widgets.add(Widgets.createSlot(new Point(x - 20, y + 3)).entries(inputEntries.get(0)).markInput());
|
||||
widgets.add(Widgets.createSlot(new Point(x + 1, y + 3)).entries(inputEntries.get(1)).markInput());
|
||||
widgets.add(Widgets.createSlot(new Point(x + 61, y + 4)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
|
||||
return widgets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderRedSlots(MatrixStack matrices, List<Widget> widgets, Rectangle bounds, REIAnvilDisplay display,
|
||||
IntList redSlots) {
|
||||
Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 27);
|
||||
matrices.push();
|
||||
matrices.translate(0, 0, 400);
|
||||
if (redSlots.contains(0)) {
|
||||
DrawableHelper.fill(matrices, startPoint.x - 20, startPoint.y + 3, startPoint.x - 20 + 16, startPoint.y + 3 + 16, 1090453504);
|
||||
DrawableHelper.fill(matrices, startPoint.x + 1, startPoint.y + 3, startPoint.x + 1 + 16, startPoint.y + 3 + 16, 1090453504);
|
||||
}
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RecipeEntry getSimpleRenderer(REIAnvilDisplay recipe) {
|
||||
return SimpleRecipeEntry.from(Collections.singletonList(recipe.getInputEntries().get(0)), recipe.getResultingEntries());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplayHeight() {
|
||||
return 49;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,73 +1,73 @@
|
|||
package ru.betterend.compat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.TransferRecipeDisplay;
|
||||
import me.shedaniel.rei.server.ContainerInfo;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.recipe.builders.AnvilSmithingRecipe;
|
||||
|
||||
public class REIAnvilDisplay implements TransferRecipeDisplay {
|
||||
|
||||
private AnvilSmithingRecipe recipe;
|
||||
private List<List<EntryStack>> input;
|
||||
private List<EntryStack> output;
|
||||
|
||||
public REIAnvilDisplay(AnvilSmithingRecipe recipe) {
|
||||
this.recipe = recipe;
|
||||
this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
|
||||
this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
|
||||
}
|
||||
|
||||
public int getDamage() {
|
||||
return this.recipe.getDamage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<Identifier> getRecipeLocation() {
|
||||
return Optional.ofNullable(recipe).map(Recipe::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getInputEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getResultingEntries() {
|
||||
return Collections.singletonList(output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier getRecipeCategory() {
|
||||
return REIPlugin.SMITHING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getRequiredEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<ScreenHandler> containerInfo,
|
||||
ScreenHandler container) {
|
||||
return this.input;
|
||||
}
|
||||
}
|
||||
package ru.betterend.compat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.TransferRecipeDisplay;
|
||||
import me.shedaniel.rei.server.ContainerInfo;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.recipe.builders.AnvilSmithingRecipe;
|
||||
|
||||
public class REIAnvilDisplay implements TransferRecipeDisplay {
|
||||
|
||||
private AnvilSmithingRecipe recipe;
|
||||
private List<List<EntryStack>> input;
|
||||
private List<EntryStack> output;
|
||||
|
||||
public REIAnvilDisplay(AnvilSmithingRecipe recipe) {
|
||||
this.recipe = recipe;
|
||||
this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
|
||||
this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
|
||||
}
|
||||
|
||||
public int getDamage() {
|
||||
return this.recipe.getDamage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<Identifier> getRecipeLocation() {
|
||||
return Optional.ofNullable(recipe).map(Recipe::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getInputEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getResultingEntries() {
|
||||
return Collections.singletonList(output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier getRecipeCategory() {
|
||||
return REIPlugin.SMITHING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<List<EntryStack>> getRequiredEntries() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<ScreenHandler> containerInfo,
|
||||
ScreenHandler container) {
|
||||
return this.input;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package ru.betterend.compat;
|
||||
|
||||
import me.shedaniel.rei.plugin.containers.CraftingContainerInfoWrapper;
|
||||
import me.shedaniel.rei.server.ContainerInfoHandler;
|
||||
import ru.betterend.client.gui.EndStoneSmelterScreenHandler;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
public class REIContainer implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ContainerInfoHandler.registerContainerInfo(AlloyingRecipe.ID, CraftingContainerInfoWrapper.create(EndStoneSmelterScreenHandler.class));
|
||||
}
|
||||
}
|
||||
package ru.betterend.compat;
|
||||
|
||||
import me.shedaniel.rei.plugin.containers.CraftingContainerInfoWrapper;
|
||||
import me.shedaniel.rei.server.ContainerInfoHandler;
|
||||
import ru.betterend.client.gui.EndStoneSmelterScreenHandler;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
public class REIContainer implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ContainerInfoHandler.registerContainerInfo(AlloyingRecipe.ID, CraftingContainerInfoWrapper.create(EndStoneSmelterScreenHandler.class));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,115 +1,115 @@
|
|||
package ru.betterend.config;
|
||||
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.config.ConfigKeeper.BooleanEntry;
|
||||
import ru.betterend.config.ConfigKeeper.Entry;
|
||||
import ru.betterend.config.ConfigKeeper.FloatEntry;
|
||||
import ru.betterend.config.ConfigKeeper.IntegerEntry;
|
||||
import ru.betterend.config.ConfigKeeper.RangeEntry;
|
||||
import ru.betterend.config.ConfigKeeper.StringEntry;
|
||||
|
||||
public abstract class Config {
|
||||
|
||||
protected final ConfigKeeper configKeeper = new ConfigKeeper();
|
||||
|
||||
public abstract void saveChanges();
|
||||
|
||||
public <E extends Entry<?>> E getEntry(String key) {
|
||||
return this.configKeeper.getEntry(key);
|
||||
}
|
||||
|
||||
public <T> T getDefault(String key) {
|
||||
Entry<T> entry = configKeeper.getEntry(key);
|
||||
return entry != null ? entry.getDefault() : null;
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
String str = configKeeper.getValue(key);
|
||||
return str != null ? str : "";
|
||||
}
|
||||
|
||||
public boolean setString(String key, String value) {
|
||||
try {
|
||||
StringEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getInt(String key) {
|
||||
Integer val = configKeeper.getValue(key);
|
||||
return val != null ? val : 0;
|
||||
}
|
||||
|
||||
public boolean setInt(String key, int value) {
|
||||
try {
|
||||
IntegerEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T extends Comparable<T>> boolean setRanged(String key, T value) {
|
||||
try {
|
||||
RangeEntry<T> entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException | ClassCastException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public float getFloat(String key) {
|
||||
Float val = configKeeper.getValue(key);
|
||||
return val != null ? val : 0.0F;
|
||||
}
|
||||
|
||||
public boolean setFloat(String key, float value) {
|
||||
try {
|
||||
FloatEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String key) {
|
||||
Boolean val = configKeeper.getValue(key);
|
||||
return val != null ? val : false;
|
||||
}
|
||||
|
||||
public boolean setBoolean(String key, boolean value) {
|
||||
try {
|
||||
BooleanEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package ru.betterend.config;
|
||||
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.config.ConfigKeeper.BooleanEntry;
|
||||
import ru.betterend.config.ConfigKeeper.Entry;
|
||||
import ru.betterend.config.ConfigKeeper.FloatEntry;
|
||||
import ru.betterend.config.ConfigKeeper.IntegerEntry;
|
||||
import ru.betterend.config.ConfigKeeper.RangeEntry;
|
||||
import ru.betterend.config.ConfigKeeper.StringEntry;
|
||||
|
||||
public abstract class Config {
|
||||
|
||||
protected final ConfigKeeper configKeeper = new ConfigKeeper();
|
||||
|
||||
public abstract void saveChanges();
|
||||
|
||||
public <E extends Entry<?>> E getEntry(String key) {
|
||||
return this.configKeeper.getEntry(key);
|
||||
}
|
||||
|
||||
public <T> T getDefault(String key) {
|
||||
Entry<T> entry = configKeeper.getEntry(key);
|
||||
return entry != null ? entry.getDefault() : null;
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
String str = configKeeper.getValue(key);
|
||||
return str != null ? str : "";
|
||||
}
|
||||
|
||||
public boolean setString(String key, String value) {
|
||||
try {
|
||||
StringEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getInt(String key) {
|
||||
Integer val = configKeeper.getValue(key);
|
||||
return val != null ? val : 0;
|
||||
}
|
||||
|
||||
public boolean setInt(String key, int value) {
|
||||
try {
|
||||
IntegerEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T extends Comparable<T>> boolean setRanged(String key, T value) {
|
||||
try {
|
||||
RangeEntry<T> entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException | ClassCastException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public float getFloat(String key) {
|
||||
Float val = configKeeper.getValue(key);
|
||||
return val != null ? val : 0.0F;
|
||||
}
|
||||
|
||||
public boolean setFloat(String key, float value) {
|
||||
try {
|
||||
FloatEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String key) {
|
||||
Boolean val = configKeeper.getValue(key);
|
||||
return val != null ? val : false;
|
||||
}
|
||||
|
||||
public boolean setBoolean(String key, boolean value) {
|
||||
try {
|
||||
BooleanEntry entry = configKeeper.getEntry(key);
|
||||
entry.setValue(value);
|
||||
this.configKeeper.set(key, entry);
|
||||
|
||||
return true;
|
||||
} catch (NullPointerException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,342 +1,342 @@
|
|||
package ru.betterend.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import ru.betterend.BetterEnd;
|
||||
|
||||
public final class ConfigKeeper {
|
||||
|
||||
private Map<String, Entry<?>> configEntries = new HashMap<>();
|
||||
|
||||
public JsonElement toJson(JsonObject jsonObject) {
|
||||
for (String param : configEntries.keySet()) {
|
||||
jsonObject.addProperty(param, configEntries.get(param).asString());
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public void fromJson(JsonObject jsonObject) {
|
||||
for (String param : configEntries.keySet()) {
|
||||
if (jsonObject.has(param)) {
|
||||
Entry<?> entry = configEntries.get(param);
|
||||
entry.fromString(JsonHelper.getString(jsonObject, param));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends Entry<?>> E getEntry(String key) {
|
||||
Entry<?> entry = this.configEntries.get(key);
|
||||
if (entry == null) {
|
||||
BetterEnd.LOGGER.warning(String.format("Entry '%s' doesn't exists.", key));
|
||||
return null;
|
||||
}
|
||||
return (E) entry;
|
||||
}
|
||||
|
||||
public <T> T getValue(String key) {
|
||||
Entry<T> entry = this.getEntry(key);
|
||||
if (entry == null) {
|
||||
BetterEnd.LOGGER.warning("Empty value will be returned.");
|
||||
return null;
|
||||
}
|
||||
return entry.getValue();
|
||||
}
|
||||
|
||||
public void set(String key, Entry<?> entry) {
|
||||
configEntries.put(key, entry);
|
||||
}
|
||||
|
||||
public <T extends Entry<?>> void registerEntry(String key, T entry) {
|
||||
configEntries.put(key, entry);
|
||||
}
|
||||
|
||||
public static class BooleanEntry extends Entry<Boolean> {
|
||||
|
||||
public BooleanEntry(Boolean defaultValue, Consumer<Boolean> consumer, Supplier<Boolean> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Boolean value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return this.getValue() ? "true" : "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(value.equals("true") ? true : false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FloatEntry extends Entry<Float> {
|
||||
|
||||
public FloatEntry(Float defaultValue, Consumer<Float> consumer, Supplier<Float> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Float value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Float.toString(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Float.valueOf(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FloatRange extends RangeEntry<Float> {
|
||||
|
||||
public FloatRange(Float defaultValue, Consumer<Float> consumer, Supplier<Float> supplier, Float minVal, Float maxVal) {
|
||||
super(defaultValue, consumer, supplier, minVal, maxVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Float.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Float.toString(getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class IntegerEntry extends Entry<Integer> {
|
||||
|
||||
public IntegerEntry(Integer defaultValue, Consumer<Integer> consumer, Supplier<Integer> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Integer value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Integer.toString(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Integer.valueOf(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class IntegerRange extends RangeEntry<Integer> {
|
||||
|
||||
public IntegerRange(Integer defaultValue, Consumer<Integer> consumer, Supplier<Integer> supplier, Integer minVal, Integer maxVal) {
|
||||
super(defaultValue, consumer, supplier, minVal, maxVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Integer.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Integer.toString(getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class StringEntry extends Entry<String> {
|
||||
|
||||
public StringEntry(String defaultValue, Consumer<String> consumer, Supplier<String> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class EnumEntry<T extends Enum<T>> extends Entry<T> {
|
||||
|
||||
public EnumEntry(T defaultValue, Consumer<T> consumer, Supplier<T> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean setValue(String name) {
|
||||
try {
|
||||
this.setter.accept((T) Enum.valueOf(this.defaultValue.getClass(), name));
|
||||
return true;
|
||||
} catch(IllegalArgumentException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return getValue().name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class RangeEntry<T extends Comparable<T>> extends Entry<T> {
|
||||
|
||||
private final T min, max;
|
||||
|
||||
public RangeEntry(T defaultValue, Consumer<T> consumer, Supplier<T> supplier, T minVal, T maxVal) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
|
||||
this.min = minVal;
|
||||
this.max = maxVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T value) {
|
||||
this.setter.accept(value.compareTo(min) < 0 ? min : value.compareTo(max) > 0 ? max : value);
|
||||
}
|
||||
|
||||
public T minValue() {
|
||||
return this.min;
|
||||
}
|
||||
|
||||
public T maxValue() {
|
||||
return this.max;
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Entry<T> {
|
||||
|
||||
protected final T defaultValue;
|
||||
|
||||
protected final Consumer<T> setter;
|
||||
protected final Supplier<T> getter;
|
||||
|
||||
public Entry (T defaultValue, Consumer<T> consumer, Supplier<T> supplier) {
|
||||
this.defaultValue = defaultValue;
|
||||
this.setter = consumer;
|
||||
this.getter = supplier;
|
||||
}
|
||||
|
||||
public abstract T getValue();
|
||||
public abstract void setValue(T value);
|
||||
public abstract T getDefault();
|
||||
public abstract void fromString(String value);
|
||||
public abstract String asString();
|
||||
|
||||
public void setDefault() {
|
||||
this.setter.accept(defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import ru.betterend.BetterEnd;
|
||||
|
||||
public final class ConfigKeeper {
|
||||
|
||||
private Map<String, Entry<?>> configEntries = new HashMap<>();
|
||||
|
||||
public JsonElement toJson(JsonObject jsonObject) {
|
||||
for (String param : configEntries.keySet()) {
|
||||
jsonObject.addProperty(param, configEntries.get(param).asString());
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public void fromJson(JsonObject jsonObject) {
|
||||
for (String param : configEntries.keySet()) {
|
||||
if (jsonObject.has(param)) {
|
||||
Entry<?> entry = configEntries.get(param);
|
||||
entry.fromString(JsonHelper.getString(jsonObject, param));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends Entry<?>> E getEntry(String key) {
|
||||
Entry<?> entry = this.configEntries.get(key);
|
||||
if (entry == null) {
|
||||
BetterEnd.LOGGER.warning(String.format("Entry '%s' doesn't exists.", key));
|
||||
return null;
|
||||
}
|
||||
return (E) entry;
|
||||
}
|
||||
|
||||
public <T> T getValue(String key) {
|
||||
Entry<T> entry = this.getEntry(key);
|
||||
if (entry == null) {
|
||||
BetterEnd.LOGGER.warning("Empty value will be returned.");
|
||||
return null;
|
||||
}
|
||||
return entry.getValue();
|
||||
}
|
||||
|
||||
public void set(String key, Entry<?> entry) {
|
||||
configEntries.put(key, entry);
|
||||
}
|
||||
|
||||
public <T extends Entry<?>> void registerEntry(String key, T entry) {
|
||||
configEntries.put(key, entry);
|
||||
}
|
||||
|
||||
public static class BooleanEntry extends Entry<Boolean> {
|
||||
|
||||
public BooleanEntry(Boolean defaultValue, Consumer<Boolean> consumer, Supplier<Boolean> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Boolean value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return this.getValue() ? "true" : "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(value.equals("true") ? true : false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FloatEntry extends Entry<Float> {
|
||||
|
||||
public FloatEntry(Float defaultValue, Consumer<Float> consumer, Supplier<Float> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Float value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Float.toString(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Float.valueOf(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FloatRange extends RangeEntry<Float> {
|
||||
|
||||
public FloatRange(Float defaultValue, Consumer<Float> consumer, Supplier<Float> supplier, Float minVal, Float maxVal) {
|
||||
super(defaultValue, consumer, supplier, minVal, maxVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Float.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Float.toString(getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class IntegerEntry extends Entry<Integer> {
|
||||
|
||||
public IntegerEntry(Integer defaultValue, Consumer<Integer> consumer, Supplier<Integer> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Integer value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Integer.toString(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Integer.valueOf(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class IntegerRange extends RangeEntry<Integer> {
|
||||
|
||||
public IntegerRange(Integer defaultValue, Consumer<Integer> consumer, Supplier<Integer> supplier, Integer minVal, Integer maxVal) {
|
||||
super(defaultValue, consumer, supplier, minVal, maxVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(Integer.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return Integer.toString(getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class StringEntry extends Entry<String> {
|
||||
|
||||
public StringEntry(String defaultValue, Consumer<String> consumer, Supplier<String> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class EnumEntry<T extends Enum<T>> extends Entry<T> {
|
||||
|
||||
public EnumEntry(T defaultValue, Consumer<T> consumer, Supplier<T> supplier) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getValue() {
|
||||
return this.getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T value) {
|
||||
this.setter.accept(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean setValue(String name) {
|
||||
try {
|
||||
this.setter.accept((T) Enum.valueOf(this.defaultValue.getClass(), name));
|
||||
return true;
|
||||
} catch(IllegalArgumentException ex) {
|
||||
BetterEnd.LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getDefault() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return getValue().name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromString(String value) {
|
||||
this.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class RangeEntry<T extends Comparable<T>> extends Entry<T> {
|
||||
|
||||
private final T min, max;
|
||||
|
||||
public RangeEntry(T defaultValue, Consumer<T> consumer, Supplier<T> supplier, T minVal, T maxVal) {
|
||||
super(defaultValue, consumer, supplier);
|
||||
|
||||
this.min = minVal;
|
||||
this.max = maxVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T value) {
|
||||
this.setter.accept(value.compareTo(min) < 0 ? min : value.compareTo(max) > 0 ? max : value);
|
||||
}
|
||||
|
||||
public T minValue() {
|
||||
return this.min;
|
||||
}
|
||||
|
||||
public T maxValue() {
|
||||
return this.max;
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Entry<T> {
|
||||
|
||||
protected final T defaultValue;
|
||||
|
||||
protected final Consumer<T> setter;
|
||||
protected final Supplier<T> getter;
|
||||
|
||||
public Entry (T defaultValue, Consumer<T> consumer, Supplier<T> supplier) {
|
||||
this.defaultValue = defaultValue;
|
||||
this.setter = consumer;
|
||||
this.getter = supplier;
|
||||
}
|
||||
|
||||
public abstract T getValue();
|
||||
public abstract void setValue(T value);
|
||||
public abstract T getDefault();
|
||||
public abstract void fromString(String value);
|
||||
public abstract String asString();
|
||||
|
||||
public void setDefault() {
|
||||
this.setter.accept(defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,79 +1,79 @@
|
|||
package ru.betterend.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.util.JsonFactory;
|
||||
|
||||
public class ConfigWriter {
|
||||
|
||||
private final static Path GAME_CONFIG_DIR = FabricLoader.getInstance().getConfigDir();
|
||||
public final static File MOD_CONFIG_DIR = new File(GAME_CONFIG_DIR.toFile(), BetterEnd.MOD_ID);
|
||||
private final static File MAIN_CONFIG_FILE = new File(MOD_CONFIG_DIR, "settings.json");
|
||||
|
||||
private static JsonObject mainConfig;
|
||||
|
||||
private JsonObject configObject;
|
||||
private File configFile;
|
||||
|
||||
public JsonObject getConfig() {
|
||||
return configObject;
|
||||
}
|
||||
|
||||
public JsonObject loadConfig(File configFile) {
|
||||
this.configFile = configFile;
|
||||
if (configObject == null) {
|
||||
configObject = load(configFile);
|
||||
}
|
||||
|
||||
return configObject;
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
if (configFile == null || configObject == null) {
|
||||
return;
|
||||
}
|
||||
save(configFile, configObject);
|
||||
}
|
||||
|
||||
public static JsonObject load() {
|
||||
if (mainConfig == null) {
|
||||
mainConfig = load(MAIN_CONFIG_FILE);
|
||||
}
|
||||
return mainConfig;
|
||||
}
|
||||
|
||||
public static JsonObject load(File configFile) {
|
||||
return JsonFactory.getJsonObject(configFile);
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
save(MAIN_CONFIG_FILE, mainConfig);
|
||||
}
|
||||
|
||||
public static void save(JsonElement config) {
|
||||
save(MAIN_CONFIG_FILE, config);
|
||||
}
|
||||
|
||||
public static void save(File configFile, JsonElement config) {
|
||||
JsonFactory.storeJson(configFile, config);
|
||||
}
|
||||
|
||||
public static String scrubFileName(String input) {
|
||||
input = input.replaceAll("[/\\ ]+", "_");
|
||||
input = input.replaceAll("[,:&\"\\|\\<\\>\\?\\*]", "_");
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
static {
|
||||
if (!MOD_CONFIG_DIR.exists()) {
|
||||
MOD_CONFIG_DIR.mkdirs();
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.util.JsonFactory;
|
||||
|
||||
public class ConfigWriter {
|
||||
|
||||
private final static Path GAME_CONFIG_DIR = FabricLoader.getInstance().getConfigDir();
|
||||
public final static File MOD_CONFIG_DIR = new File(GAME_CONFIG_DIR.toFile(), BetterEnd.MOD_ID);
|
||||
private final static File MAIN_CONFIG_FILE = new File(MOD_CONFIG_DIR, "settings.json");
|
||||
|
||||
private static JsonObject mainConfig;
|
||||
|
||||
private JsonObject configObject;
|
||||
private File configFile;
|
||||
|
||||
public JsonObject getConfig() {
|
||||
return configObject;
|
||||
}
|
||||
|
||||
public JsonObject loadConfig(File configFile) {
|
||||
this.configFile = configFile;
|
||||
if (configObject == null) {
|
||||
configObject = load(configFile);
|
||||
}
|
||||
|
||||
return configObject;
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
if (configFile == null || configObject == null) {
|
||||
return;
|
||||
}
|
||||
save(configFile, configObject);
|
||||
}
|
||||
|
||||
public static JsonObject load() {
|
||||
if (mainConfig == null) {
|
||||
mainConfig = load(MAIN_CONFIG_FILE);
|
||||
}
|
||||
return mainConfig;
|
||||
}
|
||||
|
||||
public static JsonObject load(File configFile) {
|
||||
return JsonFactory.getJsonObject(configFile);
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
save(MAIN_CONFIG_FILE, mainConfig);
|
||||
}
|
||||
|
||||
public static void save(JsonElement config) {
|
||||
save(MAIN_CONFIG_FILE, config);
|
||||
}
|
||||
|
||||
public static void save(File configFile, JsonElement config) {
|
||||
JsonFactory.storeJson(configFile, config);
|
||||
}
|
||||
|
||||
public static String scrubFileName(String input) {
|
||||
input = input.replaceAll("[/\\ ]+", "_");
|
||||
input = input.replaceAll("[,:&\"\\|\\<\\>\\?\\*]", "_");
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
static {
|
||||
if (!MOD_CONFIG_DIR.exists()) {
|
||||
MOD_CONFIG_DIR.mkdirs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
package ru.betterend.config;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class MainConfig extends Config {
|
||||
|
||||
private static MainConfig instance;
|
||||
|
||||
public static MainConfig getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new MainConfig();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private MainConfig() {
|
||||
//TODO: Need to register config params in the Keeper
|
||||
|
||||
JsonObject config = ConfigWriter.load();
|
||||
if (config.size() > 0) {
|
||||
this.configKeeper.fromJson(config);
|
||||
} else {
|
||||
this.configKeeper.toJson(config);
|
||||
ConfigWriter.save();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges() {
|
||||
this.configKeeper.toJson(ConfigWriter.load());
|
||||
ConfigWriter.save();
|
||||
}
|
||||
}
|
||||
package ru.betterend.config;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class MainConfig extends Config {
|
||||
|
||||
private static MainConfig instance;
|
||||
|
||||
public static MainConfig getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new MainConfig();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private MainConfig() {
|
||||
//TODO: Need to register config params in the Keeper
|
||||
|
||||
JsonObject config = ConfigWriter.load();
|
||||
if (config.size() > 0) {
|
||||
this.configKeeper.fromJson(config);
|
||||
} else {
|
||||
this.configKeeper.toJson(config);
|
||||
ConfigWriter.save();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges() {
|
||||
this.configKeeper.toJson(ConfigWriter.load());
|
||||
ConfigWriter.save();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package ru.betterend.effects;
|
||||
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.effects.enchantment.EndVeilEnchantment;
|
||||
|
||||
public class EndEnchantments {
|
||||
public final static Enchantment END_VEIL = registerEnchantment("end_veil", new EndVeilEnchantment());
|
||||
|
||||
public static Enchantment registerEnchantment(String name, Enchantment enchantment) {
|
||||
return Registry.register(Registry.ENCHANTMENT, BetterEnd.makeID(name), enchantment);
|
||||
}
|
||||
|
||||
public static void register() {}
|
||||
}
|
||||
package ru.betterend.effects;
|
||||
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.effects.enchantment.EndVeilEnchantment;
|
||||
|
||||
public class EndEnchantments {
|
||||
public final static Enchantment END_VEIL = registerEnchantment("end_veil", new EndVeilEnchantment());
|
||||
|
||||
public static Enchantment registerEnchantment(String name, Enchantment enchantment) {
|
||||
return Registry.register(Registry.ENCHANTMENT, BetterEnd.makeID(name), enchantment);
|
||||
}
|
||||
|
||||
public static void register() {}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package ru.betterend.effects;
|
||||
|
||||
import net.minecraft.entity.effect.StatusEffect;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.effects.status.EndVeilEffect;
|
||||
|
||||
public class EndStatusEffects {
|
||||
|
||||
public final static StatusEffect END_VEIL = registerEffect("end_veil", new EndVeilEffect());
|
||||
|
||||
public static <E extends StatusEffect> StatusEffect registerEffect(String name, E effect) {
|
||||
return Registry.register(Registry.STATUS_EFFECT, BetterEnd.makeID(name), effect);
|
||||
}
|
||||
}
|
||||
package ru.betterend.effects;
|
||||
|
||||
import net.minecraft.entity.effect.StatusEffect;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.effects.status.EndVeilEffect;
|
||||
|
||||
public class EndStatusEffects {
|
||||
|
||||
public final static StatusEffect END_VEIL = registerEffect("end_veil", new EndVeilEffect());
|
||||
|
||||
public static <E extends StatusEffect> StatusEffect registerEffect(String name, E effect) {
|
||||
return Registry.register(Registry.STATUS_EFFECT, BetterEnd.makeID(name), effect);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package ru.betterend.effects.enchantment;
|
||||
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.enchantment.EnchantmentTarget;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
|
||||
public class EndVeilEnchantment extends Enchantment {
|
||||
|
||||
public EndVeilEnchantment() {
|
||||
super(Enchantment.Rarity.VERY_RARE, EnchantmentTarget.ARMOR_HEAD, new EquipmentSlot[] { EquipmentSlot.HEAD });
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailableForRandomSelection() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package ru.betterend.effects.enchantment;
|
||||
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.enchantment.EnchantmentTarget;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
|
||||
public class EndVeilEnchantment extends Enchantment {
|
||||
|
||||
public EndVeilEnchantment() {
|
||||
super(Enchantment.Rarity.VERY_RARE, EnchantmentTarget.ARMOR_HEAD, new EquipmentSlot[] { EquipmentSlot.HEAD });
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailableForRandomSelection() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package ru.betterend.effects.status;
|
||||
|
||||
import net.minecraft.entity.effect.StatusEffect;
|
||||
import net.minecraft.entity.effect.StatusEffectType;
|
||||
|
||||
public class EndVeilEffect extends StatusEffect {
|
||||
|
||||
public EndVeilEffect() {
|
||||
super(StatusEffectType.BENEFICIAL, 0x0D554A);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyUpdateEffect(int duration, int amplifier) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package ru.betterend.effects.status;
|
||||
|
||||
import net.minecraft.entity.effect.StatusEffect;
|
||||
import net.minecraft.entity.effect.StatusEffectType;
|
||||
|
||||
public class EndVeilEffect extends StatusEffect {
|
||||
|
||||
public EndVeilEffect() {
|
||||
super(StatusEffectType.BENEFICIAL, 0x0D554A);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyUpdateEffect(int duration, int amplifier) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
139
src/main/java/ru/betterend/entity/EntityShadowWalker.java
Normal file
139
src/main/java/ru/betterend/entity/EntityShadowWalker.java
Normal file
|
@ -0,0 +1,139 @@
|
|||
package ru.betterend.entity;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.ai.goal.FollowTargetGoal;
|
||||
import net.minecraft.entity.ai.goal.LookAroundGoal;
|
||||
import net.minecraft.entity.ai.goal.LookAtEntityGoal;
|
||||
import net.minecraft.entity.ai.goal.MeleeAttackGoal;
|
||||
import net.minecraft.entity.ai.goal.WanderAroundFarGoal;
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||
import net.minecraft.entity.effect.StatusEffects;
|
||||
import net.minecraft.entity.mob.HostileEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.registry.EndSounds;
|
||||
import ru.betterend.util.MHelper;
|
||||
|
||||
public class EntityShadowWalker extends HostileEntity {
|
||||
public EntityShadowWalker(EntityType<EntityShadowWalker> entityType, World world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initGoals() {
|
||||
this.goalSelector.add(2, new AttackGoal(this, 1.0D, false));
|
||||
this.goalSelector.add(7, new WanderAroundFarGoal(this, 1.0D));
|
||||
this.goalSelector.add(8, new LookAtEntityGoal(this, PlayerEntity.class, 8.0F));
|
||||
this.goalSelector.add(8, new LookAroundGoal(this));
|
||||
this.targetSelector.add(2, new FollowTargetGoal<PlayerEntity>(this, PlayerEntity.class, true));
|
||||
}
|
||||
|
||||
public static DefaultAttributeContainer.Builder createMobAttributes() {
|
||||
return HostileEntity.createHostileAttributes()
|
||||
.add(EntityAttributes.GENERIC_FOLLOW_RANGE, 35.0)
|
||||
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.15)
|
||||
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 4.5)
|
||||
.add(EntityAttributes.GENERIC_ARMOR, 2.0)
|
||||
.add(EntityAttributes.ZOMBIE_SPAWN_REINFORCEMENTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
world.addParticle(ParticleTypes.ASH,
|
||||
getX() + random.nextGaussian() * 0.2,
|
||||
getY() + random.nextGaussian() * 0.5 + 1,
|
||||
getZ() + random.nextGaussian() * 0.2,
|
||||
0, 0, 0);
|
||||
world.addParticle(ParticleTypes.SMOKE,
|
||||
getX() + random.nextGaussian() * 0.2,
|
||||
getY() + random.nextGaussian() * 0.5 + 1,
|
||||
getZ() + random.nextGaussian() * 0.2,
|
||||
0, 0, 0);
|
||||
world.addParticle(ParticleTypes.ENTITY_EFFECT,
|
||||
getX() + random.nextGaussian() * 0.2,
|
||||
getY() + random.nextGaussian() * 0.5 + 1,
|
||||
getZ() + random.nextGaussian() * 0.2,
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return EndSounds.ENTITY_SHADOW_WALKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getHurtSound(DamageSource source) {
|
||||
return EndSounds.ENTITY_SHADOW_WALKER_DAMAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getDeathSound() {
|
||||
return EndSounds.ENTITY_SHADOW_WALKER_DEATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playStepSound(BlockPos pos, BlockState state) {}
|
||||
|
||||
@Override
|
||||
protected float getSoundVolume() {
|
||||
return MHelper.randRange(0.4F, 0.6F, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getSoundPitch() {
|
||||
return MHelper.randRange(0.75F, 1.25F, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAttack(Entity target) {
|
||||
boolean attack = super.tryAttack(target);
|
||||
if (attack && target instanceof LivingEntity) {
|
||||
LivingEntity living = (LivingEntity) target;
|
||||
if (!(living.hasStatusEffect(StatusEffects.BLINDNESS))) {
|
||||
living.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, 60));
|
||||
}
|
||||
}
|
||||
return attack;
|
||||
}
|
||||
|
||||
private final class AttackGoal extends MeleeAttackGoal {
|
||||
private final EntityShadowWalker walker;
|
||||
private int ticks;
|
||||
|
||||
public AttackGoal(EntityShadowWalker walker, double speed, boolean pauseWhenMobIdle) {
|
||||
super(walker, speed, pauseWhenMobIdle);
|
||||
this.walker = walker;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
super.start();
|
||||
this.ticks = 0;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
super.stop();
|
||||
this.walker.setAttacking(false);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
++this.ticks;
|
||||
if (this.ticks >= 5 && this.method_28348() < this.method_28349() / 2) {
|
||||
this.walker.setAttacking(true);
|
||||
}
|
||||
else {
|
||||
this.walker.setAttacking(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package ru.betterend.entity.render;
|
||||
|
||||
import net.minecraft.client.render.entity.BipedEntityRenderer;
|
||||
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.render.entity.model.PlayerEntityModel;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.entity.EntityShadowWalker;
|
||||
|
||||
public class RendererEntityShadowWalker extends BipedEntityRenderer<EntityShadowWalker, PlayerEntityModel<EntityShadowWalker>> {
|
||||
private static final Identifier TEXTURE = BetterEnd.makeID("textures/entity/shadow_walker.png");
|
||||
|
||||
public RendererEntityShadowWalker(EntityRenderDispatcher entityRenderDispatcher) {
|
||||
super(entityRenderDispatcher, new PlayerEntityModel<EntityShadowWalker>(0.0F, false), 0.5F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getTexture(EntityShadowWalker zombieEntity) {
|
||||
return TEXTURE;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
public interface CompoundSerializer<T> {
|
||||
public abstract CompoundTag toTag(CompoundTag tag);
|
||||
public abstract T fromTag(CompoundTag tag);
|
||||
}
|
||||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
public interface CompoundSerializer<T> {
|
||||
public abstract CompoundTag toTag(CompoundTag tag);
|
||||
public abstract T fromTag(CompoundTag tag);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.client.color.block.BlockColorProvider;
|
||||
import net.minecraft.client.color.item.ItemColorProvider;
|
||||
|
||||
public interface IColorProvider {
|
||||
BlockColorProvider getProvider();
|
||||
|
||||
ItemColorProvider getItemProvider();
|
||||
}
|
||||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.client.color.block.BlockColorProvider;
|
||||
import net.minecraft.client.color.item.ItemColorProvider;
|
||||
|
||||
public interface IColorProvider {
|
||||
BlockColorProvider getProvider();
|
||||
|
||||
ItemColorProvider getItemProvider();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
import ru.betterend.client.render.ERenderLayer;
|
||||
|
||||
public interface IRenderTypeable
|
||||
{
|
||||
public ERenderLayer getRenderLayer();
|
||||
}
|
||||
package ru.betterend.interfaces;
|
||||
|
||||
import ru.betterend.client.render.ERenderLayer;
|
||||
|
||||
public interface IRenderTypeable
|
||||
{
|
||||
public ERenderLayer getRenderLayer();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
public interface ISlime {
|
||||
public void setSlimeSize(int size, boolean heal);
|
||||
}
|
||||
package ru.betterend.interfaces;
|
||||
|
||||
public interface ISlime {
|
||||
public void setSlimeSize(int size, boolean heal);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public interface IdentifiedContext {
|
||||
public Identifier getContextId();
|
||||
public void setContextId(Identifier id);
|
||||
|
||||
default void removeId() {
|
||||
this.setContextId(null);
|
||||
}
|
||||
}
|
||||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public interface IdentifiedContext {
|
||||
public Identifier getContextId();
|
||||
public void setContextId(Identifier id);
|
||||
|
||||
default void removeId() {
|
||||
this.setContextId(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public interface TeleportingEntity {
|
||||
public abstract long beGetCooldown();
|
||||
public abstract void beSetCooldown(long time);
|
||||
public abstract void beSetExitPos(BlockPos pos);
|
||||
public abstract BlockPos beGetExitPos();
|
||||
|
||||
default boolean hasCooldown() {
|
||||
return this.beGetCooldown() > 0;
|
||||
}
|
||||
}
|
||||
package ru.betterend.interfaces;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public interface TeleportingEntity {
|
||||
public abstract long beGetCooldown();
|
||||
public abstract void beSetCooldown(long time);
|
||||
public abstract void beSetExitPos(BlockPos pos);
|
||||
public abstract BlockPos beGetExitPos();
|
||||
|
||||
default boolean hasCooldown() {
|
||||
return this.beGetCooldown() > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.AxeItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
import net.minecraft.tag.Tag;
|
||||
|
||||
public class EndAxe extends AxeItem implements DynamicAttributeTool {
|
||||
|
||||
public EndAxe(ToolMaterial material, float attackDamage, float attackSpeed, Settings settings) {
|
||||
super(material, attackDamage, attackSpeed, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(FabricToolTags.AXES)) {
|
||||
return this.getMaterial().getMiningLevel();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
package ru.betterend.item;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.AxeItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
import net.minecraft.tag.Tag;
|
||||
|
||||
public class EndAxe extends AxeItem implements DynamicAttributeTool {
|
||||
|
||||
public EndAxe(ToolMaterial material, float attackDamage, float attackSpeed, Settings settings) {
|
||||
super(material, attackDamage, attackSpeed, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(FabricToolTags.AXES)) {
|
||||
return this.getMaterial().getMiningLevel();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,135 +1,135 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableMultimap.Builder;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.MiningToolItem;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.registry.EndTags;
|
||||
|
||||
public class EndHammer extends MiningToolItem implements DynamicAttributeTool {
|
||||
|
||||
public final static UUID ATTACK_KNOCKBACK_MODIFIER_ID = MathHelper.randomUuid(ThreadLocalRandom.current());
|
||||
|
||||
private final Multimap<EntityAttribute, EntityAttributeModifier> attributeModifiers;
|
||||
|
||||
public EndHammer(ToolMaterial material, float attackDamage, float attackSpeed, double knockback, Settings settings) {
|
||||
super(attackDamage, attackSpeed, material, Sets.newHashSet(), settings);
|
||||
|
||||
Builder<EntityAttribute, EntityAttributeModifier> builder = ImmutableMultimap.builder();
|
||||
builder.put(EntityAttributes.GENERIC_ATTACK_DAMAGE, new EntityAttributeModifier(ATTACK_DAMAGE_MODIFIER_ID, "Weapon modifier", attackDamage + material.getAttackDamage(), EntityAttributeModifier.Operation.ADDITION));
|
||||
builder.put(EntityAttributes.GENERIC_ATTACK_SPEED, new EntityAttributeModifier(ATTACK_SPEED_MODIFIER_ID, "Weapon modifier", attackSpeed, EntityAttributeModifier.Operation.ADDITION));
|
||||
builder.put(EntityAttributes.GENERIC_ATTACK_KNOCKBACK, new EntityAttributeModifier(ATTACK_KNOCKBACK_MODIFIER_ID, "Weapon modifier", knockback, EntityAttributeModifier.Operation.ADDITION));
|
||||
this.attributeModifiers = builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) {
|
||||
return state.getMaterial().equals(Material.STONE) ||
|
||||
state.getMaterial().equals(Material.GLASS) ||
|
||||
state.isOf(Blocks.DIAMOND_BLOCK) ||
|
||||
state.isOf(Blocks.EMERALD_BLOCK) ||
|
||||
state.isOf(Blocks.LAPIS_BLOCK) ||
|
||||
state.isOf(Blocks.REDSTONE_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker) {
|
||||
stack.damage(1, attacker, ((entity) -> {
|
||||
entity.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND);
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postMine(ItemStack stack, World world, BlockState state, BlockPos pos, LivingEntity miner) {
|
||||
if (state.getHardness(world, pos) != 0.0F) {
|
||||
stack.damage(1, miner, ((entity) -> {
|
||||
entity.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND);
|
||||
}));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMiningSpeedMultiplier(ItemStack stack, BlockState state) {
|
||||
if (state.getMaterial().equals(Material.GLASS)) {
|
||||
return this.getMaterial().getMiningSpeedMultiplier() * 2.0F;
|
||||
}
|
||||
if (isEffectiveOn(state)) {
|
||||
float mult = 1.0F;
|
||||
if (state.isOf(Blocks.DIAMOND_BLOCK) || state.isOf(Blocks.EMERALD_BLOCK) || state.isOf(Blocks.LAPIS_BLOCK) || state.isOf(Blocks.REDSTONE_BLOCK)) {
|
||||
mult = this.getMaterial().getMiningSpeedMultiplier();
|
||||
} else {
|
||||
mult = this.getMaterial().getMiningSpeedMultiplier() / 2.0F;
|
||||
}
|
||||
return mult > 1.0F ? mult : 1.0F;
|
||||
}
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMiningSpeedMultiplier(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(EndTags.HAMMERS)) {
|
||||
return this.getMiningSpeedMultiplier(stack, state);
|
||||
}
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(EndTags.HAMMERS)) {
|
||||
return this.getMaterial().getMiningLevel();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEffectiveOn(BlockState state) {
|
||||
if (state.getMaterial().equals(Material.GLASS)) {
|
||||
return true;
|
||||
}
|
||||
if (!state.isOf(Blocks.REDSTONE_BLOCK) && !state.isOf(Blocks.DIAMOND_BLOCK) && !state.isOf(Blocks.EMERALD_BLOCK) && !state.isOf(Blocks.LAPIS_BLOCK) && !state.getMaterial().equals(Material.STONE)) {
|
||||
return false;
|
||||
}
|
||||
int level = this.getMaterial().getMiningLevel();
|
||||
if (state.isOf(Blocks.IRON_ORE) || state.isOf(Blocks.LAPIS_BLOCK) || state.isOf(Blocks.LAPIS_ORE)) {
|
||||
return level >= 1;
|
||||
}
|
||||
if (state.isOf(Blocks.DIAMOND_BLOCK) && !state.isOf(Blocks.DIAMOND_ORE) || state.isOf(Blocks.EMERALD_ORE) || state.isOf(Blocks.EMERALD_BLOCK) || state.isOf(Blocks.GOLD_ORE) || state.isOf(Blocks.REDSTONE_ORE)) {
|
||||
return level >= 2;
|
||||
}
|
||||
if (state.isOf(Blocks.OBSIDIAN) || state.isOf(Blocks.CRYING_OBSIDIAN) || state.isOf(Blocks.RESPAWN_ANCHOR) || state.isOf(Blocks.ANCIENT_DEBRIS)) {
|
||||
return level >= 3;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap<EntityAttribute, EntityAttributeModifier> getAttributeModifiers(EquipmentSlot slot) {
|
||||
return slot == EquipmentSlot.MAINHAND ? this.attributeModifiers : super.getAttributeModifiers(slot);
|
||||
}
|
||||
}
|
||||
package ru.betterend.item;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableMultimap.Builder;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.MiningToolItem;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.registry.EndTags;
|
||||
|
||||
public class EndHammer extends MiningToolItem implements DynamicAttributeTool {
|
||||
|
||||
public final static UUID ATTACK_KNOCKBACK_MODIFIER_ID = MathHelper.randomUuid(ThreadLocalRandom.current());
|
||||
|
||||
private final Multimap<EntityAttribute, EntityAttributeModifier> attributeModifiers;
|
||||
|
||||
public EndHammer(ToolMaterial material, float attackDamage, float attackSpeed, double knockback, Settings settings) {
|
||||
super(attackDamage, attackSpeed, material, Sets.newHashSet(), settings);
|
||||
|
||||
Builder<EntityAttribute, EntityAttributeModifier> builder = ImmutableMultimap.builder();
|
||||
builder.put(EntityAttributes.GENERIC_ATTACK_DAMAGE, new EntityAttributeModifier(ATTACK_DAMAGE_MODIFIER_ID, "Weapon modifier", attackDamage + material.getAttackDamage(), EntityAttributeModifier.Operation.ADDITION));
|
||||
builder.put(EntityAttributes.GENERIC_ATTACK_SPEED, new EntityAttributeModifier(ATTACK_SPEED_MODIFIER_ID, "Weapon modifier", attackSpeed, EntityAttributeModifier.Operation.ADDITION));
|
||||
builder.put(EntityAttributes.GENERIC_ATTACK_KNOCKBACK, new EntityAttributeModifier(ATTACK_KNOCKBACK_MODIFIER_ID, "Weapon modifier", knockback, EntityAttributeModifier.Operation.ADDITION));
|
||||
this.attributeModifiers = builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) {
|
||||
return state.getMaterial().equals(Material.STONE) ||
|
||||
state.getMaterial().equals(Material.GLASS) ||
|
||||
state.isOf(Blocks.DIAMOND_BLOCK) ||
|
||||
state.isOf(Blocks.EMERALD_BLOCK) ||
|
||||
state.isOf(Blocks.LAPIS_BLOCK) ||
|
||||
state.isOf(Blocks.REDSTONE_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker) {
|
||||
stack.damage(1, attacker, ((entity) -> {
|
||||
entity.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND);
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postMine(ItemStack stack, World world, BlockState state, BlockPos pos, LivingEntity miner) {
|
||||
if (state.getHardness(world, pos) != 0.0F) {
|
||||
stack.damage(1, miner, ((entity) -> {
|
||||
entity.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND);
|
||||
}));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMiningSpeedMultiplier(ItemStack stack, BlockState state) {
|
||||
if (state.getMaterial().equals(Material.GLASS)) {
|
||||
return this.getMaterial().getMiningSpeedMultiplier() * 2.0F;
|
||||
}
|
||||
if (isEffectiveOn(state)) {
|
||||
float mult = 1.0F;
|
||||
if (state.isOf(Blocks.DIAMOND_BLOCK) || state.isOf(Blocks.EMERALD_BLOCK) || state.isOf(Blocks.LAPIS_BLOCK) || state.isOf(Blocks.REDSTONE_BLOCK)) {
|
||||
mult = this.getMaterial().getMiningSpeedMultiplier();
|
||||
} else {
|
||||
mult = this.getMaterial().getMiningSpeedMultiplier() / 2.0F;
|
||||
}
|
||||
return mult > 1.0F ? mult : 1.0F;
|
||||
}
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMiningSpeedMultiplier(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(EndTags.HAMMERS)) {
|
||||
return this.getMiningSpeedMultiplier(stack, state);
|
||||
}
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(EndTags.HAMMERS)) {
|
||||
return this.getMaterial().getMiningLevel();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEffectiveOn(BlockState state) {
|
||||
if (state.getMaterial().equals(Material.GLASS)) {
|
||||
return true;
|
||||
}
|
||||
if (!state.isOf(Blocks.REDSTONE_BLOCK) && !state.isOf(Blocks.DIAMOND_BLOCK) && !state.isOf(Blocks.EMERALD_BLOCK) && !state.isOf(Blocks.LAPIS_BLOCK) && !state.getMaterial().equals(Material.STONE)) {
|
||||
return false;
|
||||
}
|
||||
int level = this.getMaterial().getMiningLevel();
|
||||
if (state.isOf(Blocks.IRON_ORE) || state.isOf(Blocks.LAPIS_BLOCK) || state.isOf(Blocks.LAPIS_ORE)) {
|
||||
return level >= 1;
|
||||
}
|
||||
if (state.isOf(Blocks.DIAMOND_BLOCK) && !state.isOf(Blocks.DIAMOND_ORE) || state.isOf(Blocks.EMERALD_ORE) || state.isOf(Blocks.EMERALD_BLOCK) || state.isOf(Blocks.GOLD_ORE) || state.isOf(Blocks.REDSTONE_ORE)) {
|
||||
return level >= 2;
|
||||
}
|
||||
if (state.isOf(Blocks.OBSIDIAN) || state.isOf(Blocks.CRYING_OBSIDIAN) || state.isOf(Blocks.RESPAWN_ANCHOR) || state.isOf(Blocks.ANCIENT_DEBRIS)) {
|
||||
return level >= 3;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap<EntityAttribute, EntityAttributeModifier> getAttributeModifiers(EquipmentSlot slot) {
|
||||
return slot == EquipmentSlot.MAINHAND ? this.attributeModifiers : super.getAttributeModifiers(slot);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.item.HoeItem;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
|
||||
public class EndHoe extends HoeItem {
|
||||
|
||||
public EndHoe(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) {
|
||||
super(material, attackDamage, attackSpeed, settings);
|
||||
}
|
||||
}
|
||||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.item.HoeItem;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
|
||||
public class EndHoe extends HoeItem {
|
||||
|
||||
public EndHoe(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) {
|
||||
super(material, attackDamage, attackSpeed, settings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.PickaxeItem;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
import net.minecraft.tag.Tag;
|
||||
|
||||
public class EndPickaxe extends PickaxeItem implements DynamicAttributeTool {
|
||||
|
||||
public EndPickaxe(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) {
|
||||
super(material, attackDamage, attackSpeed, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(FabricToolTags.PICKAXES)) {
|
||||
return this.getMaterial().getMiningLevel();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
package ru.betterend.item;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.PickaxeItem;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
import net.minecraft.tag.Tag;
|
||||
|
||||
public class EndPickaxe extends PickaxeItem implements DynamicAttributeTool {
|
||||
|
||||
public EndPickaxe(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) {
|
||||
super(material, attackDamage, attackSpeed, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
|
||||
if (tag.equals(FabricToolTags.PICKAXES)) {
|
||||
return this.getMaterial().getMiningLevel();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
public class EternalCrystal extends Item {
|
||||
|
||||
public EternalCrystal() {
|
||||
super(EndItems.makeSettings());
|
||||
}
|
||||
package ru.betterend.item;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import ru.betterend.registry.EndItems;
|
||||
|
||||
public class EternalCrystal extends Item {
|
||||
|
||||
public EternalCrystal() {
|
||||
super(EndItems.makeSettings());
|
||||
}
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
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.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.client.recipebook.ClientRecipeBook;
|
||||
import net.minecraft.client.recipebook.RecipeBookGroup;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
@Mixin(ClientRecipeBook.class)
|
||||
public abstract class ClientRecipeBookMixin {
|
||||
@Inject(method = "getGroupForRecipe", at = @At("HEAD"), cancellable = true)
|
||||
private static void getGroupForRecipe(Recipe<?> recipe, CallbackInfoReturnable<RecipeBookGroup> cinfo) {
|
||||
if (recipe instanceof AlloyingRecipe) {
|
||||
cinfo.setReturnValue(RecipeBookGroup.BLAST_FURNACE_MISC);
|
||||
cinfo.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.client.recipebook.ClientRecipeBook;
|
||||
import net.minecraft.client.recipebook.RecipeBookGroup;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import ru.betterend.recipe.builders.AlloyingRecipe;
|
||||
|
||||
@Mixin(ClientRecipeBook.class)
|
||||
public abstract class ClientRecipeBookMixin {
|
||||
@Inject(method = "getGroupForRecipe", at = @At("HEAD"), cancellable = true)
|
||||
private static void getGroupForRecipe(Recipe<?> recipe, CallbackInfoReturnable<RecipeBookGroup> cinfo) {
|
||||
if (recipe instanceof AlloyingRecipe) {
|
||||
cinfo.setReturnValue(RecipeBookGroup.BLAST_FURNACE_MISC);
|
||||
cinfo.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
package ru.betterend.mixin.client;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import net.minecraft.client.render.model.json.ModelVariantMap.DeserializationContext;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.interfaces.IdentifiedContext;
|
||||
|
||||
@Mixin(DeserializationContext.class)
|
||||
public class DeserializationContextMixin implements IdentifiedContext {
|
||||
|
||||
private Identifier contextId;
|
||||
|
||||
@Override
|
||||
public Identifier getContextId() {
|
||||
return this.contextId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContextId(Identifier id) {
|
||||
this.contextId = id;
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.client;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import net.minecraft.client.render.model.json.ModelVariantMap.DeserializationContext;
|
||||
import net.minecraft.util.Identifier;
|
||||
import ru.betterend.interfaces.IdentifiedContext;
|
||||
|
||||
@Mixin(DeserializationContext.class)
|
||||
public class DeserializationContextMixin implements IdentifiedContext {
|
||||
|
||||
private Identifier contextId;
|
||||
|
||||
@Override
|
||||
public Identifier getContextId() {
|
||||
return this.contextId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContextId(Identifier id) {
|
||||
this.contextId = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
package ru.betterend.mixin.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.resource.NamespaceResourceManager;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.interfaces.Patterned;
|
||||
|
||||
@Mixin(NamespaceResourceManager.class)
|
||||
public abstract class NamespaceResourceManagerMixin {
|
||||
|
||||
@Shadow
|
||||
public abstract Resource getResource(Identifier id);
|
||||
|
||||
@Inject(method = "getAllResources", cancellable = true, at = @At(
|
||||
value = "NEW",
|
||||
target = "java/io/FileNotFoundException",
|
||||
shift = Shift.BEFORE))
|
||||
public void getStatesPattern(Identifier id, CallbackInfoReturnable<List<Resource>> info) {
|
||||
if (id.getNamespace().contains(BetterEnd.MOD_ID)) {
|
||||
String[] data = id.getPath().split("/");
|
||||
if (data.length > 1) {
|
||||
Identifier blockId = BetterEnd.makeID(data[1].replace(".json", ""));
|
||||
Block block = Registry.BLOCK.get(blockId);
|
||||
if (block instanceof Patterned) {
|
||||
List<Resource> resources = Lists.newArrayList();
|
||||
resources.add(this.getResource(((Patterned) block).statePatternId()));
|
||||
info.setReturnValue(resources);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.resource.NamespaceResourceManager;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.interfaces.Patterned;
|
||||
|
||||
@Mixin(NamespaceResourceManager.class)
|
||||
public abstract class NamespaceResourceManagerMixin {
|
||||
|
||||
@Shadow
|
||||
public abstract Resource getResource(Identifier id);
|
||||
|
||||
@Inject(method = "getAllResources", cancellable = true, at = @At(
|
||||
value = "NEW",
|
||||
target = "java/io/FileNotFoundException",
|
||||
shift = Shift.BEFORE))
|
||||
public void getStatesPattern(Identifier id, CallbackInfoReturnable<List<Resource>> info) {
|
||||
if (id.getNamespace().contains(BetterEnd.MOD_ID)) {
|
||||
String[] data = id.getPath().split("/");
|
||||
if (data.length > 1) {
|
||||
Identifier blockId = BetterEnd.makeID(data[1].replace(".json", ""));
|
||||
Block block = Registry.BLOCK.get(blockId);
|
||||
if (block instanceof Patterned) {
|
||||
List<Resource> resources = Lists.newArrayList();
|
||||
resources.add(this.getResource(((Patterned) block).statePatternId()));
|
||||
info.setReturnValue(resources);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,51 +1,51 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.enchantment.Enchantments;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.loot.context.LootContextParameters;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import ru.betterend.item.EndHammer;
|
||||
import ru.betterend.util.MHelper;
|
||||
|
||||
@Mixin(AbstractBlock.class)
|
||||
public abstract class AbstractBlockMixin {
|
||||
|
||||
@Inject(method = "getDroppedStacks", at = @At("HEAD"), cancellable = true)
|
||||
public void getDroppedStacks(BlockState state, LootContext.Builder builder, CallbackInfoReturnable<List<ItemStack>> info) {
|
||||
if (state.isOf(Blocks.GLOWSTONE)) {
|
||||
ItemStack tool = builder.get(LootContextParameters.TOOL);
|
||||
if (tool != null && tool.getItem() instanceof EndHammer) {
|
||||
int min = 3;
|
||||
int max = 4;
|
||||
int count = 0;
|
||||
int fortune = EnchantmentHelper.getLevel(Enchantments.FORTUNE, tool);
|
||||
if (fortune > 0) {
|
||||
fortune /= Enchantments.FORTUNE.getMaxLevel();
|
||||
min = MathHelper.clamp(min + fortune, min, max);
|
||||
if (min == max) {
|
||||
info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, max)));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
count = MHelper.randRange(min, max, MHelper.RANDOM);
|
||||
info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, count)));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.enchantment.Enchantments;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.loot.context.LootContextParameters;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import ru.betterend.item.EndHammer;
|
||||
import ru.betterend.util.MHelper;
|
||||
|
||||
@Mixin(AbstractBlock.class)
|
||||
public abstract class AbstractBlockMixin {
|
||||
|
||||
@Inject(method = "getDroppedStacks", at = @At("HEAD"), cancellable = true)
|
||||
public void getDroppedStacks(BlockState state, LootContext.Builder builder, CallbackInfoReturnable<List<ItemStack>> info) {
|
||||
if (state.isOf(Blocks.GLOWSTONE)) {
|
||||
ItemStack tool = builder.get(LootContextParameters.TOOL);
|
||||
if (tool != null && tool.getItem() instanceof EndHammer) {
|
||||
int min = 3;
|
||||
int max = 4;
|
||||
int count = 0;
|
||||
int fortune = EnchantmentHelper.getLevel(Enchantments.FORTUNE, tool);
|
||||
if (fortune > 0) {
|
||||
fortune /= Enchantments.FORTUNE.getMaxLevel();
|
||||
min = MathHelper.clamp(min + fortune, min, max);
|
||||
if (min == max) {
|
||||
info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, max)));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
count = MHelper.randRange(min, max, MHelper.RANDOM);
|
||||
info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, count)));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,92 +1,92 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.block.AnvilBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.RecipeManager;
|
||||
import net.minecraft.screen.AnvilScreenHandler;
|
||||
import net.minecraft.screen.ForgingScreenHandler;
|
||||
import net.minecraft.screen.ScreenHandlerContext;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.recipe.builders.AnvilSmithingRecipe;
|
||||
|
||||
@Mixin(AnvilScreenHandler.class)
|
||||
public abstract class AnvilScreenHandlerMixin extends ForgingScreenHandler {
|
||||
|
||||
private final World world = this.player.world;
|
||||
private final RecipeManager recipeManager = this.world.getRecipeManager();
|
||||
private AnvilSmithingRecipe currentRecipe;
|
||||
|
||||
public AnvilScreenHandlerMixin(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory,
|
||||
ScreenHandlerContext context) {
|
||||
super(type, syncId, playerInventory, context);
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public abstract void updateResult();
|
||||
|
||||
@Inject(method = "canTakeOutput", at = @At("HEAD"), cancellable = true)
|
||||
protected void canTakeOutput(PlayerEntity player, boolean present, CallbackInfoReturnable<Boolean> info) {
|
||||
if (currentRecipe != null) {
|
||||
ItemStack output = this.currentRecipe.craft(input, player);
|
||||
if (!output.isEmpty()) {
|
||||
info.setReturnValue(true);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onTakeOutput", at = @At("HEAD"), cancellable = true)
|
||||
protected void onTakeOutput(PlayerEntity player, ItemStack stack, CallbackInfoReturnable<ItemStack> info) {
|
||||
if (currentRecipe != null) {
|
||||
this.input.getStack(1).decrement(1);
|
||||
this.updateResult();
|
||||
this.context.run((world, blockPos) -> {
|
||||
BlockState anvilState = world.getBlockState(blockPos);
|
||||
if (!player.abilities.creativeMode && anvilState.isIn(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) {
|
||||
BlockState landingState = AnvilBlock.getLandingState(anvilState);
|
||||
if (landingState == null) {
|
||||
world.removeBlock(blockPos, false);
|
||||
world.syncWorldEvent(1029, blockPos, 0);
|
||||
} else {
|
||||
world.setBlockState(blockPos, landingState, 2);
|
||||
world.syncWorldEvent(1030, blockPos, 0);
|
||||
}
|
||||
} else {
|
||||
world.syncWorldEvent(1030, blockPos, 0);
|
||||
}
|
||||
|
||||
});
|
||||
info.setReturnValue(stack);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "updateResult", at = @At("HEAD"), cancellable = true)
|
||||
public void updateOutput(CallbackInfo info) {
|
||||
this.currentRecipe = this.recipeManager.getFirstMatch(AnvilSmithingRecipe.TYPE, input, world).orElse(null);
|
||||
if (currentRecipe != null) {
|
||||
this.output.setStack(0, currentRecipe.craft(input));
|
||||
this.sendContentUpdates();
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "setNewItemName", at = @At("HEAD"), cancellable = true)
|
||||
public void setNewItemName(String string, CallbackInfo info) {
|
||||
if (currentRecipe != null) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.common;
|
||||
|
||||
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.block.AnvilBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.RecipeManager;
|
||||
import net.minecraft.screen.AnvilScreenHandler;
|
||||
import net.minecraft.screen.ForgingScreenHandler;
|
||||
import net.minecraft.screen.ScreenHandlerContext;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.recipe.builders.AnvilSmithingRecipe;
|
||||
|
||||
@Mixin(AnvilScreenHandler.class)
|
||||
public abstract class AnvilScreenHandlerMixin extends ForgingScreenHandler {
|
||||
|
||||
private final World world = this.player.world;
|
||||
private final RecipeManager recipeManager = this.world.getRecipeManager();
|
||||
private AnvilSmithingRecipe currentRecipe;
|
||||
|
||||
public AnvilScreenHandlerMixin(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory,
|
||||
ScreenHandlerContext context) {
|
||||
super(type, syncId, playerInventory, context);
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public abstract void updateResult();
|
||||
|
||||
@Inject(method = "canTakeOutput", at = @At("HEAD"), cancellable = true)
|
||||
protected void canTakeOutput(PlayerEntity player, boolean present, CallbackInfoReturnable<Boolean> info) {
|
||||
if (currentRecipe != null) {
|
||||
ItemStack output = this.currentRecipe.craft(input, player);
|
||||
if (!output.isEmpty()) {
|
||||
info.setReturnValue(true);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onTakeOutput", at = @At("HEAD"), cancellable = true)
|
||||
protected void onTakeOutput(PlayerEntity player, ItemStack stack, CallbackInfoReturnable<ItemStack> info) {
|
||||
if (currentRecipe != null) {
|
||||
this.input.getStack(1).decrement(1);
|
||||
this.updateResult();
|
||||
this.context.run((world, blockPos) -> {
|
||||
BlockState anvilState = world.getBlockState(blockPos);
|
||||
if (!player.abilities.creativeMode && anvilState.isIn(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) {
|
||||
BlockState landingState = AnvilBlock.getLandingState(anvilState);
|
||||
if (landingState == null) {
|
||||
world.removeBlock(blockPos, false);
|
||||
world.syncWorldEvent(1029, blockPos, 0);
|
||||
} else {
|
||||
world.setBlockState(blockPos, landingState, 2);
|
||||
world.syncWorldEvent(1030, blockPos, 0);
|
||||
}
|
||||
} else {
|
||||
world.syncWorldEvent(1030, blockPos, 0);
|
||||
}
|
||||
|
||||
});
|
||||
info.setReturnValue(stack);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "updateResult", at = @At("HEAD"), cancellable = true)
|
||||
public void updateOutput(CallbackInfo info) {
|
||||
this.currentRecipe = this.recipeManager.getFirstMatch(AnvilSmithingRecipe.TYPE, input, world).orElse(null);
|
||||
if (currentRecipe != null) {
|
||||
this.output.setStack(0, currentRecipe.craft(input));
|
||||
this.sendContentUpdates();
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "setNewItemName", at = @At("HEAD"), cancellable = true)
|
||||
public void setNewItemName(String string, CallbackInfo info) {
|
||||
if (currentRecipe != null) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.recipe.BrewingRecipeRegistry;
|
||||
|
||||
@Mixin(BrewingRecipeRegistry.class)
|
||||
public interface BrewingAccessor {
|
||||
@Invoker
|
||||
static void callRegisterPotionRecipe(Potion input, Item item, Potion output) {
|
||||
throw new AssertionError("@Invoker dummy body called");
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.common;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.recipe.BrewingRecipeRegistry;
|
||||
|
||||
@Mixin(BrewingRecipeRegistry.class)
|
||||
public interface BrewingAccessor {
|
||||
@Invoker
|
||||
static void callRegisterPotionRecipe(Potion input, Item item, Potion output) {
|
||||
throw new AssertionError("@Invoker dummy body called");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.mob.EndermanEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import ru.betterend.effects.EndEnchantments;
|
||||
import ru.betterend.effects.EndStatusEffects;
|
||||
|
||||
@Mixin(EndermanEntity.class)
|
||||
public abstract class EndermanEntityMixin {
|
||||
|
||||
@Inject(method = "isPlayerStaring", at = @At("HEAD"), cancellable = true)
|
||||
private void isPlayerStaring(PlayerEntity player, CallbackInfoReturnable<Boolean> info) {
|
||||
if (player.isCreative() || player.hasStatusEffect(EndStatusEffects.END_VEIL) ||
|
||||
EnchantmentHelper.getLevel(EndEnchantments.END_VEIL, player.getEquippedStack(EquipmentSlot.HEAD)) > 0) {
|
||||
info.setReturnValue(false);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.common;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.mob.EndermanEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import ru.betterend.effects.EndEnchantments;
|
||||
import ru.betterend.effects.EndStatusEffects;
|
||||
|
||||
@Mixin(EndermanEntity.class)
|
||||
public abstract class EndermanEntityMixin {
|
||||
|
||||
@Inject(method = "isPlayerStaring", at = @At("HEAD"), cancellable = true)
|
||||
private void isPlayerStaring(PlayerEntity player, CallbackInfoReturnable<Boolean> info) {
|
||||
if (player.isCreative() || player.hasStatusEffect(EndStatusEffects.END_VEIL) ||
|
||||
EnchantmentHelper.getLevel(EndEnchantments.END_VEIL, player.getEquippedStack(EquipmentSlot.HEAD)) > 0) {
|
||||
info.setReturnValue(false);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,116 +1,116 @@
|
|||
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.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.TeleportTarget;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.interfaces.TeleportingEntity;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin implements TeleportingEntity {
|
||||
|
||||
private BlockPos beExitPos;
|
||||
private long beCooldown;
|
||||
|
||||
@Shadow
|
||||
public float yaw;
|
||||
@Shadow
|
||||
public float pitch;
|
||||
@Shadow
|
||||
public boolean removed;
|
||||
@Shadow
|
||||
public World world;
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
public abstract void detach();
|
||||
|
||||
@Shadow
|
||||
public abstract Vec3d getVelocity();
|
||||
|
||||
@Shadow
|
||||
public abstract EntityType<?> getType();
|
||||
|
||||
@Shadow
|
||||
public abstract void copyFrom(Entity original);
|
||||
|
||||
@Shadow
|
||||
public abstract Entity moveToWorld(ServerWorld destination);
|
||||
|
||||
@Shadow
|
||||
protected abstract TeleportTarget getTeleportTarget(ServerWorld destination);
|
||||
|
||||
@Inject(method = "moveToWorld", at = @At("HEAD"), cancellable = true)
|
||||
public void moveToWorld(ServerWorld destination, CallbackInfoReturnable<Entity> info) {
|
||||
if (!removed && beExitPos != null && world instanceof ServerWorld) {
|
||||
this.detach();
|
||||
this.world.getProfiler().push("changeDimension");
|
||||
this.world.getProfiler().push("reposition");
|
||||
TeleportTarget teleportTarget = this.getTeleportTarget(destination);
|
||||
if (teleportTarget != null) {
|
||||
this.world.getProfiler().swap("reloading");
|
||||
Entity entity = this.getType().create(destination);
|
||||
if (entity != null) {
|
||||
entity.copyFrom(Entity.class.cast(this));
|
||||
entity.refreshPositionAndAngles(teleportTarget.position.x, teleportTarget.position.y, teleportTarget.position.z, teleportTarget.yaw, entity.pitch);
|
||||
entity.setVelocity(teleportTarget.velocity);
|
||||
destination.onDimensionChanged(entity);
|
||||
}
|
||||
this.removed = true;
|
||||
this.world.getProfiler().pop();
|
||||
((ServerWorld) this.world).resetIdleTimeout();
|
||||
destination.resetIdleTimeout();
|
||||
this.world.getProfiler().pop();
|
||||
this.beExitPos = null;
|
||||
info.setReturnValue(entity);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getTeleportTarget", at = @At("HEAD"), cancellable = true)
|
||||
protected void getTeleportTarget(ServerWorld destination, CallbackInfoReturnable<TeleportTarget> info) {
|
||||
if (beExitPos != null) {
|
||||
info.setReturnValue(new TeleportTarget(new Vec3d(beExitPos.getX() + 0.5D, beExitPos.getY(), beExitPos.getZ() + 0.5D), getVelocity(), yaw, pitch));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "baseTick", at = @At("TAIL"))
|
||||
public void baseTick(CallbackInfo info) {
|
||||
if (hasCooldown()) {
|
||||
this.beCooldown--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long beGetCooldown() {
|
||||
return this.beCooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetCooldown(long time) {
|
||||
this.beCooldown = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetExitPos(BlockPos pos) {
|
||||
this.beExitPos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos beGetExitPos() {
|
||||
return this.beExitPos;
|
||||
}
|
||||
}
|
||||
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.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.TeleportTarget;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.interfaces.TeleportingEntity;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin implements TeleportingEntity {
|
||||
|
||||
private BlockPos beExitPos;
|
||||
private long beCooldown;
|
||||
|
||||
@Shadow
|
||||
public float yaw;
|
||||
@Shadow
|
||||
public float pitch;
|
||||
@Shadow
|
||||
public boolean removed;
|
||||
@Shadow
|
||||
public World world;
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
public abstract void detach();
|
||||
|
||||
@Shadow
|
||||
public abstract Vec3d getVelocity();
|
||||
|
||||
@Shadow
|
||||
public abstract EntityType<?> getType();
|
||||
|
||||
@Shadow
|
||||
public abstract void copyFrom(Entity original);
|
||||
|
||||
@Shadow
|
||||
public abstract Entity moveToWorld(ServerWorld destination);
|
||||
|
||||
@Shadow
|
||||
protected abstract TeleportTarget getTeleportTarget(ServerWorld destination);
|
||||
|
||||
@Inject(method = "moveToWorld", at = @At("HEAD"), cancellable = true)
|
||||
public void moveToWorld(ServerWorld destination, CallbackInfoReturnable<Entity> info) {
|
||||
if (!removed && beExitPos != null && world instanceof ServerWorld) {
|
||||
this.detach();
|
||||
this.world.getProfiler().push("changeDimension");
|
||||
this.world.getProfiler().push("reposition");
|
||||
TeleportTarget teleportTarget = this.getTeleportTarget(destination);
|
||||
if (teleportTarget != null) {
|
||||
this.world.getProfiler().swap("reloading");
|
||||
Entity entity = this.getType().create(destination);
|
||||
if (entity != null) {
|
||||
entity.copyFrom(Entity.class.cast(this));
|
||||
entity.refreshPositionAndAngles(teleportTarget.position.x, teleportTarget.position.y, teleportTarget.position.z, teleportTarget.yaw, entity.pitch);
|
||||
entity.setVelocity(teleportTarget.velocity);
|
||||
destination.onDimensionChanged(entity);
|
||||
}
|
||||
this.removed = true;
|
||||
this.world.getProfiler().pop();
|
||||
((ServerWorld) this.world).resetIdleTimeout();
|
||||
destination.resetIdleTimeout();
|
||||
this.world.getProfiler().pop();
|
||||
this.beExitPos = null;
|
||||
info.setReturnValue(entity);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getTeleportTarget", at = @At("HEAD"), cancellable = true)
|
||||
protected void getTeleportTarget(ServerWorld destination, CallbackInfoReturnable<TeleportTarget> info) {
|
||||
if (beExitPos != null) {
|
||||
info.setReturnValue(new TeleportTarget(new Vec3d(beExitPos.getX() + 0.5D, beExitPos.getY(), beExitPos.getZ() + 0.5D), getVelocity(), yaw, pitch));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "baseTick", at = @At("TAIL"))
|
||||
public void baseTick(CallbackInfo info) {
|
||||
if (hasCooldown()) {
|
||||
this.beCooldown--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long beGetCooldown() {
|
||||
return this.beCooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetCooldown(long time) {
|
||||
this.beCooldown = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetExitPos(BlockPos pos) {
|
||||
this.beExitPos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos beGetExitPos() {
|
||||
return this.beExitPos;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
|
||||
import ru.betterend.interfaces.CompoundSerializer;
|
||||
|
||||
@Mixin(Ingredient.class)
|
||||
public abstract class IngredientMixin implements CompoundSerializer<Ingredient> {
|
||||
|
||||
@Shadow
|
||||
private ItemStack[] matchingStacks;
|
||||
|
||||
@Shadow
|
||||
protected abstract void cacheMatchingStacks();
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
this.cacheMatchingStacks();
|
||||
int i = 0;
|
||||
tag.putInt("length", matchingStacks.length);
|
||||
for (ItemStack stack : matchingStacks) {
|
||||
String key = Integer.toString(i);
|
||||
tag.put(key, stack.toTag(new CompoundTag()));
|
||||
i++;
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ingredient fromTag(CompoundTag tag) {
|
||||
int length = tag.getInt("length");
|
||||
ItemStack[] stacks = new ItemStack[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
String key = Integer.toString(i);
|
||||
stacks[i] = ItemStack.fromTag(tag.getCompound(key));
|
||||
}
|
||||
return Ingredient.ofStacks(Arrays.stream(stacks));
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
|
||||
import ru.betterend.interfaces.CompoundSerializer;
|
||||
|
||||
@Mixin(Ingredient.class)
|
||||
public abstract class IngredientMixin implements CompoundSerializer<Ingredient> {
|
||||
|
||||
@Shadow
|
||||
private ItemStack[] matchingStacks;
|
||||
|
||||
@Shadow
|
||||
protected abstract void cacheMatchingStacks();
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
this.cacheMatchingStacks();
|
||||
int i = 0;
|
||||
tag.putInt("length", matchingStacks.length);
|
||||
for (ItemStack stack : matchingStacks) {
|
||||
String key = Integer.toString(i);
|
||||
tag.put(key, stack.toTag(new CompoundTag()));
|
||||
i++;
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ingredient fromTag(CompoundTag tag) {
|
||||
int length = tag.getInt("length");
|
||||
ItemStack[] stacks = new ItemStack[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
String key = Integer.toString(i);
|
||||
stacks[i] = ItemStack.fromTag(tag.getCompound(key));
|
||||
}
|
||||
return Ingredient.ofStacks(Arrays.stream(stacks));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public abstract class LivingEntityMixin {
|
||||
|
||||
private Entity lastAttacker;
|
||||
|
||||
@Inject(method = "damage", at = @At("HEAD"))
|
||||
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
|
||||
this.lastAttacker = source.getAttacker();
|
||||
}
|
||||
|
||||
@ModifyArg(method = "damage", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;takeKnockback(FDD)V"))
|
||||
private float increaseKnockback(float value, double x, double z) {
|
||||
if (lastAttacker != null && lastAttacker instanceof LivingEntity) {
|
||||
LivingEntity attacker = (LivingEntity) lastAttacker;
|
||||
value += this.getKnockback(attacker.getMainHandStack().getItem());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private double getKnockback(Item tool) {
|
||||
if (tool == null) return 0.0D;
|
||||
Collection<EntityAttributeModifier> modifiers = tool.getAttributeModifiers(EquipmentSlot.MAINHAND)
|
||||
.get(EntityAttributes.GENERIC_ATTACK_KNOCKBACK);
|
||||
if (modifiers.size() > 0) {
|
||||
return modifiers.iterator().next().getValue();
|
||||
}
|
||||
return 0.0D;
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public abstract class LivingEntityMixin {
|
||||
|
||||
private Entity lastAttacker;
|
||||
|
||||
@Inject(method = "damage", at = @At("HEAD"))
|
||||
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
|
||||
this.lastAttacker = source.getAttacker();
|
||||
}
|
||||
|
||||
@ModifyArg(method = "damage", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;takeKnockback(FDD)V"))
|
||||
private float increaseKnockback(float value, double x, double z) {
|
||||
if (lastAttacker != null && lastAttacker instanceof LivingEntity) {
|
||||
LivingEntity attacker = (LivingEntity) lastAttacker;
|
||||
value += this.getKnockback(attacker.getMainHandStack().getItem());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private double getKnockback(Item tool) {
|
||||
if (tool == null) return 0.0D;
|
||||
Collection<EntityAttributeModifier> modifiers = tool.getAttributeModifiers(EquipmentSlot.MAINHAND)
|
||||
.get(EntityAttributes.GENERIC_ATTACK_KNOCKBACK);
|
||||
if (modifiers.size() > 0) {
|
||||
return modifiers.iterator().next().getValue();
|
||||
}
|
||||
return 0.0D;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
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.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import ru.betterend.interfaces.TeleportingEntity;
|
||||
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
public abstract class ServerPlayerEntityMixin implements TeleportingEntity {
|
||||
|
||||
private long beCooldown;
|
||||
|
||||
@Inject(method = "tick", at = @At("TAIL"))
|
||||
public void baseTick(CallbackInfo info) {
|
||||
if (hasCooldown()) {
|
||||
this.beCooldown--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long beGetCooldown() {
|
||||
return this.beCooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetCooldown(long time) {
|
||||
this.beCooldown = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetExitPos(BlockPos pos) {}
|
||||
|
||||
@Override
|
||||
public BlockPos beGetExitPos() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package ru.betterend.mixin.common;
|
||||
|
||||
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.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import ru.betterend.interfaces.TeleportingEntity;
|
||||
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
public abstract class ServerPlayerEntityMixin implements TeleportingEntity {
|
||||
|
||||
private long beCooldown;
|
||||
|
||||
@Inject(method = "tick", at = @At("TAIL"))
|
||||
public void baseTick(CallbackInfo info) {
|
||||
if (hasCooldown()) {
|
||||
this.beCooldown--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long beGetCooldown() {
|
||||
return this.beCooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetCooldown(long time) {
|
||||
this.beCooldown = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beSetExitPos(BlockPos pos) {}
|
||||
|
||||
@Override
|
||||
public BlockPos beGetExitPos() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,76 +1,76 @@
|
|||
package ru.betterend.particle;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.particle.AnimatedParticle;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.particle.ParticleFactory;
|
||||
import net.minecraft.client.particle.SpriteProvider;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.particle.DefaultParticleType;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import ru.betterend.util.MHelper;
|
||||
|
||||
public class PaticlePortalSphere extends AnimatedParticle {
|
||||
private int ticks;
|
||||
private double preVX;
|
||||
private double preVY;
|
||||
private double preVZ;
|
||||
private double nextVX;
|
||||
private double nextVY;
|
||||
private double nextVZ;
|
||||
|
||||
public PaticlePortalSphere(ClientWorld world, double x, double y, double z, SpriteProvider spriteProvider) {
|
||||
super(world, x, y, z, spriteProvider, 0);
|
||||
setSprite(spriteProvider.getSprite(random));
|
||||
this.maxAge = MHelper.randRange(20, 80, random);
|
||||
this.scale = MHelper.randRange(0.05F, 0.15F, random);
|
||||
this.setColor(0xFEBBD5);
|
||||
this.setTargetColor(0xBBFEE4);
|
||||
this.setSpriteForAge(spriteProvider);
|
||||
|
||||
preVX = random.nextGaussian() * 0.02;
|
||||
preVY = random.nextGaussian() * 0.02;
|
||||
preVZ = random.nextGaussian() * 0.02;
|
||||
|
||||
nextVX = random.nextGaussian() * 0.02;
|
||||
nextVY = random.nextGaussian() * 0.02;
|
||||
nextVZ = random.nextGaussian() * 0.02;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
ticks++;
|
||||
if (ticks > 30) {
|
||||
preVX = nextVX;
|
||||
preVY = nextVY;
|
||||
preVZ = nextVZ;
|
||||
nextVX = random.nextGaussian() * 0.02;
|
||||
nextVY = random.nextGaussian() * 0.02;
|
||||
nextVZ = random.nextGaussian() * 0.02;
|
||||
ticks = 0;
|
||||
}
|
||||
double delta = (double) ticks / 30.0;
|
||||
|
||||
this.velocityX = MathHelper.lerp(delta, preVX, nextVX);
|
||||
this.velocityY = MathHelper.lerp(delta, preVY, nextVY);
|
||||
this.velocityZ = MathHelper.lerp(delta, preVZ, nextVZ);
|
||||
|
||||
super.tick();
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static class FactoryPortalSphere implements ParticleFactory<DefaultParticleType> {
|
||||
|
||||
private final SpriteProvider sprites;
|
||||
|
||||
public FactoryPortalSphere(SpriteProvider sprites) {
|
||||
this.sprites = sprites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Particle createParticle(DefaultParticleType type, ClientWorld world, double x, double y, double z, double vX, double vY, double vZ) {
|
||||
return new PaticlePortalSphere(world, x, y, z, sprites);
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.particle;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.particle.AnimatedParticle;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.particle.ParticleFactory;
|
||||
import net.minecraft.client.particle.SpriteProvider;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.particle.DefaultParticleType;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import ru.betterend.util.MHelper;
|
||||
|
||||
public class PaticlePortalSphere extends AnimatedParticle {
|
||||
private int ticks;
|
||||
private double preVX;
|
||||
private double preVY;
|
||||
private double preVZ;
|
||||
private double nextVX;
|
||||
private double nextVY;
|
||||
private double nextVZ;
|
||||
|
||||
public PaticlePortalSphere(ClientWorld world, double x, double y, double z, SpriteProvider spriteProvider) {
|
||||
super(world, x, y, z, spriteProvider, 0);
|
||||
setSprite(spriteProvider.getSprite(random));
|
||||
this.maxAge = MHelper.randRange(20, 80, random);
|
||||
this.scale = MHelper.randRange(0.05F, 0.15F, random);
|
||||
this.setColor(0xFEBBD5);
|
||||
this.setTargetColor(0xBBFEE4);
|
||||
this.setSpriteForAge(spriteProvider);
|
||||
|
||||
preVX = random.nextGaussian() * 0.02;
|
||||
preVY = random.nextGaussian() * 0.02;
|
||||
preVZ = random.nextGaussian() * 0.02;
|
||||
|
||||
nextVX = random.nextGaussian() * 0.02;
|
||||
nextVY = random.nextGaussian() * 0.02;
|
||||
nextVZ = random.nextGaussian() * 0.02;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
ticks++;
|
||||
if (ticks > 30) {
|
||||
preVX = nextVX;
|
||||
preVY = nextVY;
|
||||
preVZ = nextVZ;
|
||||
nextVX = random.nextGaussian() * 0.02;
|
||||
nextVY = random.nextGaussian() * 0.02;
|
||||
nextVZ = random.nextGaussian() * 0.02;
|
||||
ticks = 0;
|
||||
}
|
||||
double delta = (double) ticks / 30.0;
|
||||
|
||||
this.velocityX = MathHelper.lerp(delta, preVX, nextVX);
|
||||
this.velocityY = MathHelper.lerp(delta, preVY, nextVY);
|
||||
this.velocityZ = MathHelper.lerp(delta, preVZ, nextVZ);
|
||||
|
||||
super.tick();
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static class FactoryPortalSphere implements ParticleFactory<DefaultParticleType> {
|
||||
|
||||
private final SpriteProvider sprites;
|
||||
|
||||
public FactoryPortalSphere(SpriteProvider sprites) {
|
||||
this.sprites = sprites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Particle createParticle(DefaultParticleType type, ClientWorld world, double x, double y, double z, double vX, double vY, double vZ) {
|
||||
return new PaticlePortalSphere(world, x, y, z, sprites);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,273 +1,273 @@
|
|||
package ru.betterend.recipe.builders;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.recipe.EndRecipeManager;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.util.RecipeHelper;
|
||||
|
||||
public class AlloyingRecipe implements Recipe<Inventory> {
|
||||
|
||||
public final static String GROUP = "alloying";
|
||||
public final static RecipeType<AlloyingRecipe> TYPE = EndRecipeManager.registerType(GROUP);
|
||||
public final static Serializer SERIALIZER = EndRecipeManager.registerSerializer(GROUP, new Serializer());
|
||||
public final static Identifier ID = BetterEnd.makeID(GROUP);
|
||||
|
||||
protected final RecipeType<?> type;
|
||||
protected final Identifier id;
|
||||
protected final Ingredient primaryInput;
|
||||
protected final Ingredient secondaryInput;
|
||||
protected final ItemStack output;
|
||||
protected final String group;
|
||||
protected final float experience;
|
||||
protected final int smeltTime;
|
||||
|
||||
public AlloyingRecipe(Identifier id, String group, Ingredient primaryInput, Ingredient secondaryInput, ItemStack output, float experience, int smeltTime) {
|
||||
this.group = group;
|
||||
this.id = id;
|
||||
this.primaryInput = primaryInput;
|
||||
this.secondaryInput = secondaryInput;
|
||||
this.output = output;
|
||||
this.experience = experience;
|
||||
this.smeltTime = smeltTime;
|
||||
this.type = TYPE;
|
||||
}
|
||||
|
||||
public float getExperience() {
|
||||
return this.experience;
|
||||
}
|
||||
|
||||
public int getSmeltTime() {
|
||||
return this.smeltTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultedList<Ingredient> getPreviewInputs() {
|
||||
DefaultedList<Ingredient> defaultedList = DefaultedList.of();
|
||||
defaultedList.add(primaryInput);
|
||||
defaultedList.add(secondaryInput);
|
||||
|
||||
return defaultedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Inventory inv, World world) {
|
||||
return this.primaryInput.test(inv.getStack(0)) && this.secondaryInput.test(inv.getStack(1)) ||
|
||||
this.primaryInput.test(inv.getStack(1)) && this.secondaryInput.test(inv.getStack(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(Inventory inv) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public String getGroup() {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public ItemStack getRecipeKindIcon() {
|
||||
return new ItemStack(EndBlocks.END_STONE_SMELTER);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
|
||||
public static Builder create(Identifier id) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.group = String.format("%s_%s", GROUP, id);
|
||||
INSTANCE.primaryInput = null;
|
||||
INSTANCE.secondaryInput = null;
|
||||
INSTANCE.output = null;
|
||||
INSTANCE.experience = 0.0F;
|
||||
INSTANCE.smeltTime = 350;
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static Builder create(String id) {
|
||||
return create(BetterEnd.makeID(id));
|
||||
}
|
||||
|
||||
private Identifier id;
|
||||
private Ingredient primaryInput;
|
||||
private Ingredient secondaryInput;
|
||||
private ItemStack output;
|
||||
private String group;
|
||||
private float experience;
|
||||
private int smeltTime;
|
||||
private boolean alright = true;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
public Builder setGroup(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrimaryInput(ItemConvertible... inputs) {
|
||||
for (ItemConvertible item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.primaryInput = Ingredient.ofItems(inputs);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSecondaryInput(ItemConvertible... inputs) {
|
||||
for (ItemConvertible item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.secondaryInput = Ingredient.ofItems(inputs);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrimaryInput(Tag<Item> input) {
|
||||
this.primaryInput = Ingredient.fromTag(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSecondaryInput(Tag<Item> input) {
|
||||
this.secondaryInput = Ingredient.fromTag(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(ItemConvertible primaryInput, ItemConvertible secondaryInput) {
|
||||
this.setPrimaryInput(primaryInput);
|
||||
this.setSecondaryInput(secondaryInput);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Tag<Item> primaryInput, Tag<Item> secondaryInput) {
|
||||
this.setPrimaryInput(primaryInput);
|
||||
this.setSecondaryInput(secondaryInput);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemConvertible output, int amount) {
|
||||
this.alright &= RecipeHelper.exists(output);
|
||||
this.output = new ItemStack(output, amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setExpiriense(float amount) {
|
||||
this.experience = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSmeltTime(int time) {
|
||||
this.smeltTime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (primaryInput == null) {
|
||||
BetterEnd.LOGGER.warning("Primary input for Alloying recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if(secondaryInput == null) {
|
||||
BetterEnd.LOGGER.warning("Secondary input for Alloying can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if(output == null) {
|
||||
BetterEnd.LOGGER.warning("Output for Alloying can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (EndRecipeManager.getRecipe(TYPE, id) != null) {
|
||||
BetterEnd.LOGGER.warning("Can't add Alloying recipe! Id {} already exists!", id);
|
||||
return;
|
||||
}
|
||||
if (!alright) {
|
||||
BetterEnd.LOGGER.debug("Can't add Alloying recipe {}! Ingeredient or output not exists.", id);
|
||||
return;
|
||||
}
|
||||
EndRecipeManager.addRecipe(TYPE, new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<AlloyingRecipe> {
|
||||
@Override
|
||||
public AlloyingRecipe read(Identifier id, JsonObject json) {
|
||||
JsonArray ingredients = JsonHelper.getArray(json, "ingredients");
|
||||
Ingredient primaryInput = Ingredient.fromJson(ingredients.get(0));
|
||||
Ingredient secondaryInput = Ingredient.fromJson(ingredients.get(1));
|
||||
String resultStr = JsonHelper.getString(json, "result");
|
||||
String group = JsonHelper.getString(json, "group", "");
|
||||
Identifier resultId = new Identifier(resultStr);
|
||||
ItemStack output = new ItemStack(Registry.ITEM.getOrEmpty(resultId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Item: " + resultStr + " does not exists!");
|
||||
}));
|
||||
float experience = JsonHelper.getFloat(json, "experience", 0.0F);
|
||||
int smeltTime = JsonHelper.getInt(json, "smelttime", 350);
|
||||
|
||||
return new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlloyingRecipe read(Identifier id, PacketByteBuf packetBuffer) {
|
||||
String group = packetBuffer.readString(32767);
|
||||
Ingredient primary = Ingredient.fromPacket(packetBuffer);
|
||||
Ingredient secondary = Ingredient.fromPacket(packetBuffer);
|
||||
ItemStack output = packetBuffer.readItemStack();
|
||||
float experience = packetBuffer.readFloat();
|
||||
int smeltTime = packetBuffer.readVarInt();
|
||||
|
||||
return new AlloyingRecipe(id, group, primary, secondary, output, experience, smeltTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf packetBuffer, AlloyingRecipe recipe) {
|
||||
packetBuffer.writeString(recipe.group);
|
||||
recipe.primaryInput.write(packetBuffer);
|
||||
recipe.secondaryInput.write(packetBuffer);
|
||||
packetBuffer.writeItemStack(recipe.output);
|
||||
packetBuffer.writeFloat(recipe.experience);
|
||||
packetBuffer.writeVarInt(recipe.smeltTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.recipe.builders;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.recipe.EndRecipeManager;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.util.RecipeHelper;
|
||||
|
||||
public class AlloyingRecipe implements Recipe<Inventory> {
|
||||
|
||||
public final static String GROUP = "alloying";
|
||||
public final static RecipeType<AlloyingRecipe> TYPE = EndRecipeManager.registerType(GROUP);
|
||||
public final static Serializer SERIALIZER = EndRecipeManager.registerSerializer(GROUP, new Serializer());
|
||||
public final static Identifier ID = BetterEnd.makeID(GROUP);
|
||||
|
||||
protected final RecipeType<?> type;
|
||||
protected final Identifier id;
|
||||
protected final Ingredient primaryInput;
|
||||
protected final Ingredient secondaryInput;
|
||||
protected final ItemStack output;
|
||||
protected final String group;
|
||||
protected final float experience;
|
||||
protected final int smeltTime;
|
||||
|
||||
public AlloyingRecipe(Identifier id, String group, Ingredient primaryInput, Ingredient secondaryInput, ItemStack output, float experience, int smeltTime) {
|
||||
this.group = group;
|
||||
this.id = id;
|
||||
this.primaryInput = primaryInput;
|
||||
this.secondaryInput = secondaryInput;
|
||||
this.output = output;
|
||||
this.experience = experience;
|
||||
this.smeltTime = smeltTime;
|
||||
this.type = TYPE;
|
||||
}
|
||||
|
||||
public float getExperience() {
|
||||
return this.experience;
|
||||
}
|
||||
|
||||
public int getSmeltTime() {
|
||||
return this.smeltTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultedList<Ingredient> getPreviewInputs() {
|
||||
DefaultedList<Ingredient> defaultedList = DefaultedList.of();
|
||||
defaultedList.add(primaryInput);
|
||||
defaultedList.add(secondaryInput);
|
||||
|
||||
return defaultedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Inventory inv, World world) {
|
||||
return this.primaryInput.test(inv.getStack(0)) && this.secondaryInput.test(inv.getStack(1)) ||
|
||||
this.primaryInput.test(inv.getStack(1)) && this.secondaryInput.test(inv.getStack(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(Inventory inv) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public String getGroup() {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public ItemStack getRecipeKindIcon() {
|
||||
return new ItemStack(EndBlocks.END_STONE_SMELTER);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
|
||||
public static Builder create(Identifier id) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.group = String.format("%s_%s", GROUP, id);
|
||||
INSTANCE.primaryInput = null;
|
||||
INSTANCE.secondaryInput = null;
|
||||
INSTANCE.output = null;
|
||||
INSTANCE.experience = 0.0F;
|
||||
INSTANCE.smeltTime = 350;
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static Builder create(String id) {
|
||||
return create(BetterEnd.makeID(id));
|
||||
}
|
||||
|
||||
private Identifier id;
|
||||
private Ingredient primaryInput;
|
||||
private Ingredient secondaryInput;
|
||||
private ItemStack output;
|
||||
private String group;
|
||||
private float experience;
|
||||
private int smeltTime;
|
||||
private boolean alright = true;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
public Builder setGroup(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrimaryInput(ItemConvertible... inputs) {
|
||||
for (ItemConvertible item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.primaryInput = Ingredient.ofItems(inputs);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSecondaryInput(ItemConvertible... inputs) {
|
||||
for (ItemConvertible item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.secondaryInput = Ingredient.ofItems(inputs);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrimaryInput(Tag<Item> input) {
|
||||
this.primaryInput = Ingredient.fromTag(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSecondaryInput(Tag<Item> input) {
|
||||
this.secondaryInput = Ingredient.fromTag(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(ItemConvertible primaryInput, ItemConvertible secondaryInput) {
|
||||
this.setPrimaryInput(primaryInput);
|
||||
this.setSecondaryInput(secondaryInput);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Tag<Item> primaryInput, Tag<Item> secondaryInput) {
|
||||
this.setPrimaryInput(primaryInput);
|
||||
this.setSecondaryInput(secondaryInput);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemConvertible output, int amount) {
|
||||
this.alright &= RecipeHelper.exists(output);
|
||||
this.output = new ItemStack(output, amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setExpiriense(float amount) {
|
||||
this.experience = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSmeltTime(int time) {
|
||||
this.smeltTime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (primaryInput == null) {
|
||||
BetterEnd.LOGGER.warning("Primary input for Alloying recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if(secondaryInput == null) {
|
||||
BetterEnd.LOGGER.warning("Secondary input for Alloying can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if(output == null) {
|
||||
BetterEnd.LOGGER.warning("Output for Alloying can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (EndRecipeManager.getRecipe(TYPE, id) != null) {
|
||||
BetterEnd.LOGGER.warning("Can't add Alloying recipe! Id {} already exists!", id);
|
||||
return;
|
||||
}
|
||||
if (!alright) {
|
||||
BetterEnd.LOGGER.debug("Can't add Alloying recipe {}! Ingeredient or output not exists.", id);
|
||||
return;
|
||||
}
|
||||
EndRecipeManager.addRecipe(TYPE, new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<AlloyingRecipe> {
|
||||
@Override
|
||||
public AlloyingRecipe read(Identifier id, JsonObject json) {
|
||||
JsonArray ingredients = JsonHelper.getArray(json, "ingredients");
|
||||
Ingredient primaryInput = Ingredient.fromJson(ingredients.get(0));
|
||||
Ingredient secondaryInput = Ingredient.fromJson(ingredients.get(1));
|
||||
String resultStr = JsonHelper.getString(json, "result");
|
||||
String group = JsonHelper.getString(json, "group", "");
|
||||
Identifier resultId = new Identifier(resultStr);
|
||||
ItemStack output = new ItemStack(Registry.ITEM.getOrEmpty(resultId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Item: " + resultStr + " does not exists!");
|
||||
}));
|
||||
float experience = JsonHelper.getFloat(json, "experience", 0.0F);
|
||||
int smeltTime = JsonHelper.getInt(json, "smelttime", 350);
|
||||
|
||||
return new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlloyingRecipe read(Identifier id, PacketByteBuf packetBuffer) {
|
||||
String group = packetBuffer.readString(32767);
|
||||
Ingredient primary = Ingredient.fromPacket(packetBuffer);
|
||||
Ingredient secondary = Ingredient.fromPacket(packetBuffer);
|
||||
ItemStack output = packetBuffer.readItemStack();
|
||||
float experience = packetBuffer.readFloat();
|
||||
int smeltTime = packetBuffer.readVarInt();
|
||||
|
||||
return new AlloyingRecipe(id, group, primary, secondary, output, experience, smeltTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf packetBuffer, AlloyingRecipe recipe) {
|
||||
packetBuffer.writeString(recipe.group);
|
||||
recipe.primaryInput.write(packetBuffer);
|
||||
recipe.secondaryInput.write(packetBuffer);
|
||||
packetBuffer.writeItemStack(recipe.output);
|
||||
packetBuffer.writeFloat(recipe.experience);
|
||||
packetBuffer.writeVarInt(recipe.smeltTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,241 +1,241 @@
|
|||
package ru.betterend.recipe.builders;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ToolItem;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.recipe.EndRecipeManager;
|
||||
import ru.betterend.registry.EndTags;
|
||||
import ru.betterend.util.RecipeHelper;
|
||||
|
||||
public class AnvilSmithingRecipe implements Recipe<Inventory> {
|
||||
|
||||
public final static String GROUP = "smithing";
|
||||
public final static RecipeType<AnvilSmithingRecipe> TYPE = EndRecipeManager.registerType(GROUP);
|
||||
public final static Serializer SERIALIZER = EndRecipeManager.registerSerializer(GROUP, new Serializer());
|
||||
public final static Identifier ID = BetterEnd.makeID(GROUP);
|
||||
|
||||
private final Identifier id;
|
||||
private final Ingredient input;
|
||||
private final ItemStack output;
|
||||
private final int damage;
|
||||
private final int level;
|
||||
|
||||
public AnvilSmithingRecipe(Identifier identifier, Ingredient input, ItemStack output, int level, int damage) {
|
||||
this.id = identifier;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.level = level;
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Inventory craftingInventory, World world) {
|
||||
return this.matches(craftingInventory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(Inventory craftingInventory) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
public ItemStack craft(Inventory craftingInventory, PlayerEntity player) {
|
||||
if (!player.isCreative()) {
|
||||
ItemStack hammer = craftingInventory.getStack(0);
|
||||
int damage = hammer.getDamage() + this.damage;
|
||||
if (damage >= hammer.getMaxDamage()) return ItemStack.EMPTY;
|
||||
hammer.damage(this.damage, player, entity -> {
|
||||
entity.sendEquipmentBreakStatus(null);
|
||||
});
|
||||
}
|
||||
return this.craft(craftingInventory);
|
||||
}
|
||||
|
||||
public boolean matches(Inventory craftingInventory) {
|
||||
ItemStack hammer = craftingInventory.getStack(0);
|
||||
if (hammer.isEmpty() || !EndTags.HAMMERS.contains(hammer.getItem())) {
|
||||
return false;
|
||||
}
|
||||
int level = ((ToolItem) hammer.getItem()).getMaterial().getMiningLevel();
|
||||
return level >= this.level && this.input.test(craftingInventory.getStack(1));
|
||||
}
|
||||
|
||||
public int getDamage() {
|
||||
return this.damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultedList<Ingredient> getPreviewInputs() {
|
||||
DefaultedList<Ingredient> defaultedList = DefaultedList.of();
|
||||
defaultedList.add(Ingredient.ofStacks(EndTags.HAMMERS.values().stream().filter(hammer -> {
|
||||
return ((ToolItem) hammer).getMaterial().getMiningLevel() >= level;
|
||||
}).map(ItemStack::new)));
|
||||
defaultedList.add(input);
|
||||
|
||||
return defaultedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public boolean fits(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoredInRecipeBook() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
|
||||
public static Builder create(String id) {
|
||||
return create(BetterEnd.makeID(id));
|
||||
}
|
||||
|
||||
public static Builder create(Identifier id) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.input = null;
|
||||
INSTANCE.output = null;
|
||||
INSTANCE.level = 1;
|
||||
INSTANCE.damage = 1;
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private Identifier id;
|
||||
private Ingredient input;
|
||||
private ItemStack output;
|
||||
private int level = 1;
|
||||
private int damage = 1;
|
||||
private boolean alright = true;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
public Builder setInput(ItemConvertible... inputItems) {
|
||||
for (ItemConvertible item : inputItems) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.setInput(Ingredient.ofItems(inputItems));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Tag<Item> inputTag) {
|
||||
this.setInput(Ingredient.fromTag(inputTag));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Ingredient ingredient) {
|
||||
this.input = ingredient;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemConvertible output, int amount) {
|
||||
this.alright &= RecipeHelper.exists(output);
|
||||
this.output = new ItemStack(output, amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLevel(int level) {
|
||||
this.level = level;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDamage(int damage) {
|
||||
this.damage = damage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (input == null) {
|
||||
BetterEnd.LOGGER.warning("Input for Smithing recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if(output == null) {
|
||||
BetterEnd.LOGGER.warning("Output for Smithing recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (EndRecipeManager.getRecipe(TYPE, id) != null) {
|
||||
BetterEnd.LOGGER.warning("Can't add Smithing recipe! Id {} already exists!", id);
|
||||
return;
|
||||
}
|
||||
if (!alright) {
|
||||
BetterEnd.LOGGER.debug("Can't add Smithing recipe {}! Ingeredient or output not exists.", id);
|
||||
return;
|
||||
}
|
||||
EndRecipeManager.addRecipe(TYPE, new AnvilSmithingRecipe(id, input, output, level, damage));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<AnvilSmithingRecipe> {
|
||||
@Override
|
||||
public AnvilSmithingRecipe read(Identifier id, JsonObject json) {
|
||||
Ingredient input = Ingredient.fromJson(JsonHelper.getObject(json, "input"));
|
||||
String resultStr = JsonHelper.getString(json, "result");
|
||||
Identifier resultId = new Identifier(resultStr);
|
||||
ItemStack output = new ItemStack(Registry.ITEM.getOrEmpty(resultId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Item: " + resultStr + " does not exists!");
|
||||
}));
|
||||
int level = JsonHelper.getInt(json, "level", 1);
|
||||
int damage = JsonHelper.getInt(json, "damage", 1);
|
||||
|
||||
return new AnvilSmithingRecipe(id, input, output, level, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnvilSmithingRecipe read(Identifier id, PacketByteBuf packetBuffer) {
|
||||
Ingredient input = Ingredient.fromPacket(packetBuffer);
|
||||
ItemStack output = packetBuffer.readItemStack();
|
||||
int level = packetBuffer.readVarInt();
|
||||
int damage = packetBuffer.readVarInt();
|
||||
|
||||
return new AnvilSmithingRecipe(id, input, output, level, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf packetBuffer, AnvilSmithingRecipe recipe) {
|
||||
recipe.input.write(packetBuffer);
|
||||
packetBuffer.writeItemStack(recipe.output);
|
||||
packetBuffer.writeVarInt(recipe.level);
|
||||
packetBuffer.writeVarInt(recipe.damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.recipe.builders;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ToolItem;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.recipe.EndRecipeManager;
|
||||
import ru.betterend.registry.EndTags;
|
||||
import ru.betterend.util.RecipeHelper;
|
||||
|
||||
public class AnvilSmithingRecipe implements Recipe<Inventory> {
|
||||
|
||||
public final static String GROUP = "smithing";
|
||||
public final static RecipeType<AnvilSmithingRecipe> TYPE = EndRecipeManager.registerType(GROUP);
|
||||
public final static Serializer SERIALIZER = EndRecipeManager.registerSerializer(GROUP, new Serializer());
|
||||
public final static Identifier ID = BetterEnd.makeID(GROUP);
|
||||
|
||||
private final Identifier id;
|
||||
private final Ingredient input;
|
||||
private final ItemStack output;
|
||||
private final int damage;
|
||||
private final int level;
|
||||
|
||||
public AnvilSmithingRecipe(Identifier identifier, Ingredient input, ItemStack output, int level, int damage) {
|
||||
this.id = identifier;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.level = level;
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Inventory craftingInventory, World world) {
|
||||
return this.matches(craftingInventory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(Inventory craftingInventory) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
public ItemStack craft(Inventory craftingInventory, PlayerEntity player) {
|
||||
if (!player.isCreative()) {
|
||||
ItemStack hammer = craftingInventory.getStack(0);
|
||||
int damage = hammer.getDamage() + this.damage;
|
||||
if (damage >= hammer.getMaxDamage()) return ItemStack.EMPTY;
|
||||
hammer.damage(this.damage, player, entity -> {
|
||||
entity.sendEquipmentBreakStatus(null);
|
||||
});
|
||||
}
|
||||
return this.craft(craftingInventory);
|
||||
}
|
||||
|
||||
public boolean matches(Inventory craftingInventory) {
|
||||
ItemStack hammer = craftingInventory.getStack(0);
|
||||
if (hammer.isEmpty() || !EndTags.HAMMERS.contains(hammer.getItem())) {
|
||||
return false;
|
||||
}
|
||||
int level = ((ToolItem) hammer.getItem()).getMaterial().getMiningLevel();
|
||||
return level >= this.level && this.input.test(craftingInventory.getStack(1));
|
||||
}
|
||||
|
||||
public int getDamage() {
|
||||
return this.damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultedList<Ingredient> getPreviewInputs() {
|
||||
DefaultedList<Ingredient> defaultedList = DefaultedList.of();
|
||||
defaultedList.add(Ingredient.ofStacks(EndTags.HAMMERS.values().stream().filter(hammer -> {
|
||||
return ((ToolItem) hammer).getMaterial().getMiningLevel() >= level;
|
||||
}).map(ItemStack::new)));
|
||||
defaultedList.add(input);
|
||||
|
||||
return defaultedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public boolean fits(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoredInRecipeBook() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
|
||||
public static Builder create(String id) {
|
||||
return create(BetterEnd.makeID(id));
|
||||
}
|
||||
|
||||
public static Builder create(Identifier id) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.input = null;
|
||||
INSTANCE.output = null;
|
||||
INSTANCE.level = 1;
|
||||
INSTANCE.damage = 1;
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private Identifier id;
|
||||
private Ingredient input;
|
||||
private ItemStack output;
|
||||
private int level = 1;
|
||||
private int damage = 1;
|
||||
private boolean alright = true;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
public Builder setInput(ItemConvertible... inputItems) {
|
||||
for (ItemConvertible item : inputItems) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.setInput(Ingredient.ofItems(inputItems));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Tag<Item> inputTag) {
|
||||
this.setInput(Ingredient.fromTag(inputTag));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setInput(Ingredient ingredient) {
|
||||
this.input = ingredient;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemConvertible output, int amount) {
|
||||
this.alright &= RecipeHelper.exists(output);
|
||||
this.output = new ItemStack(output, amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLevel(int level) {
|
||||
this.level = level;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDamage(int damage) {
|
||||
this.damage = damage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (input == null) {
|
||||
BetterEnd.LOGGER.warning("Input for Smithing recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if(output == null) {
|
||||
BetterEnd.LOGGER.warning("Output for Smithing recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (EndRecipeManager.getRecipe(TYPE, id) != null) {
|
||||
BetterEnd.LOGGER.warning("Can't add Smithing recipe! Id {} already exists!", id);
|
||||
return;
|
||||
}
|
||||
if (!alright) {
|
||||
BetterEnd.LOGGER.debug("Can't add Smithing recipe {}! Ingeredient or output not exists.", id);
|
||||
return;
|
||||
}
|
||||
EndRecipeManager.addRecipe(TYPE, new AnvilSmithingRecipe(id, input, output, level, damage));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<AnvilSmithingRecipe> {
|
||||
@Override
|
||||
public AnvilSmithingRecipe read(Identifier id, JsonObject json) {
|
||||
Ingredient input = Ingredient.fromJson(JsonHelper.getObject(json, "input"));
|
||||
String resultStr = JsonHelper.getString(json, "result");
|
||||
Identifier resultId = new Identifier(resultStr);
|
||||
ItemStack output = new ItemStack(Registry.ITEM.getOrEmpty(resultId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Item: " + resultStr + " does not exists!");
|
||||
}));
|
||||
int level = JsonHelper.getInt(json, "level", 1);
|
||||
int damage = JsonHelper.getInt(json, "damage", 1);
|
||||
|
||||
return new AnvilSmithingRecipe(id, input, output, level, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnvilSmithingRecipe read(Identifier id, PacketByteBuf packetBuffer) {
|
||||
Ingredient input = Ingredient.fromPacket(packetBuffer);
|
||||
ItemStack output = packetBuffer.readItemStack();
|
||||
int level = packetBuffer.readVarInt();
|
||||
int damage = packetBuffer.readVarInt();
|
||||
|
||||
return new AnvilSmithingRecipe(id, input, output, level, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf packetBuffer, AnvilSmithingRecipe recipe) {
|
||||
recipe.input.write(packetBuffer);
|
||||
packetBuffer.writeItemStack(recipe.output);
|
||||
packetBuffer.writeVarInt(recipe.level);
|
||||
packetBuffer.writeVarInt(recipe.damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,253 +1,253 @@
|
|||
package ru.betterend.recipe.builders;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.interfaces.CompoundSerializer;
|
||||
import ru.betterend.recipe.EndRecipeManager;
|
||||
import ru.betterend.rituals.InfusionRitual;
|
||||
|
||||
public class InfusionRecipe implements Recipe<InfusionRitual> {
|
||||
|
||||
public final static String GROUP = "infusion";
|
||||
public final static RecipeType<InfusionRecipe> TYPE = EndRecipeManager.registerType(GROUP);
|
||||
public final static Serializer SERIALIZER = EndRecipeManager.registerSerializer(GROUP, new Serializer());
|
||||
public final static Identifier ID = BetterEnd.makeID(GROUP);
|
||||
|
||||
private final Identifier id;
|
||||
private Ingredient input;
|
||||
private ItemStack output;
|
||||
private int time = 1;
|
||||
private Ingredient[] catalysts = new Ingredient[8];
|
||||
|
||||
private InfusionRecipe(Identifier id) {
|
||||
this(id, null, null);
|
||||
}
|
||||
|
||||
private InfusionRecipe(Identifier id, Ingredient input, ItemStack output) {
|
||||
this.id = id;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
Arrays.fill(catalysts, Ingredient.EMPTY);
|
||||
}
|
||||
|
||||
public int getInfusionTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(InfusionRitual inv, World world) {
|
||||
boolean valid = this.input.test(inv.getStack(0));
|
||||
if (!valid) return false;
|
||||
for (int i = 1; i < 9; i++) {
|
||||
valid &= this.catalysts[i].test(inv.getStack(i));
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(InfusionRitual ritual) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public InfusionRecipe fromTag(CompoundTag tag) {
|
||||
return SERIALIZER.fromTag(tag);
|
||||
}
|
||||
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
return SERIALIZER.toTag(this, tag);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
|
||||
public static Builder create(String id) {
|
||||
return create(BetterEnd.makeID(id));
|
||||
}
|
||||
|
||||
public static Builder create(Identifier id) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.input = null;
|
||||
INSTANCE.output = null;
|
||||
INSTANCE.time = 1;
|
||||
|
||||
Arrays.fill(INSTANCE.catalysts, Ingredient.EMPTY);
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private Identifier id;
|
||||
private Ingredient input;
|
||||
private ItemStack output;
|
||||
private int time = 1;
|
||||
private Ingredient[] catalysts = new Ingredient[8];
|
||||
|
||||
private Builder() {
|
||||
Arrays.fill(catalysts, Ingredient.EMPTY);
|
||||
}
|
||||
|
||||
public Builder setInput(ItemConvertible input) {
|
||||
this.input = Ingredient.ofItems(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemStack output) {
|
||||
this.output = output;
|
||||
this.output.setCount(1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTime(int time) {
|
||||
this.time = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addCatalyst(int slot, ItemConvertible item) {
|
||||
if (slot > 7) return this;
|
||||
this.catalysts[slot] = Ingredient.ofItems(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (input == null) {
|
||||
BetterEnd.LOGGER.warning("Input for Infusion recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (output == null) {
|
||||
BetterEnd.LOGGER.warning("Output for Infusion recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
InfusionRecipe recipe = new InfusionRecipe(id, input, output);
|
||||
recipe.time = time;
|
||||
int empty = 0;
|
||||
for (int i = 0; i < catalysts.length; i++) {
|
||||
if (catalysts[i].isEmpty()) empty++;
|
||||
else recipe.catalysts[i] = catalysts[i];
|
||||
}
|
||||
if (empty == catalysts.length) {
|
||||
BetterEnd.LOGGER.warning("At least one catalyst must be non empty, recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
EndRecipeManager.addRecipe(TYPE, recipe);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<InfusionRecipe> {
|
||||
@Override
|
||||
public InfusionRecipe read(Identifier id, JsonObject json) {
|
||||
InfusionRecipe recipe = new InfusionRecipe(id);
|
||||
recipe.input = Ingredient.fromJson(json.get("input"));
|
||||
Identifier outId = new Identifier(JsonHelper.getString(json, "output"));
|
||||
recipe.output = new ItemStack(Registry.ITEM.getOrEmpty(outId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Item: " + outId + " does not exists!");
|
||||
}));
|
||||
recipe.time = JsonHelper.getInt(json, "time", 1);
|
||||
JsonArray catalysts = JsonHelper.asArray(json, "catalysts");
|
||||
for (int i = 0; i < catalysts.size(); i++) {
|
||||
ItemStack stack = new ItemStack(Registry.ITEM.getOrEmpty(outId).orElse(null));
|
||||
recipe.catalysts[i] = Ingredient.ofStacks(
|
||||
Arrays.stream(new ItemStack[] { stack }));
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfusionRecipe read(Identifier id, PacketByteBuf buffer) {
|
||||
InfusionRecipe recipe = new InfusionRecipe(id);
|
||||
recipe.input = Ingredient.fromPacket(buffer);
|
||||
recipe.output = buffer.readItemStack();
|
||||
recipe.time = buffer.readVarInt();
|
||||
for (int i = 0; i < 9; i++) {
|
||||
recipe.catalysts[i] = Ingredient.fromPacket(buffer);
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf buffer, InfusionRecipe recipe) {
|
||||
recipe.input.write(buffer);
|
||||
buffer.writeItemStack(recipe.output);
|
||||
buffer.writeVarInt(recipe.time);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
recipe.catalysts[i].write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public InfusionRecipe fromTag(CompoundTag tag) {
|
||||
Identifier id = new Identifier(tag.getString("id"));
|
||||
InfusionRecipe recipe = new InfusionRecipe(id);
|
||||
CompoundSerializer<Ingredient> inputSerializer = this.toSerializer(recipe.input);
|
||||
recipe.input = inputSerializer.fromTag(tag.getCompound("input"));
|
||||
recipe.output = ItemStack.fromTag(tag.getCompound("output"));
|
||||
recipe.time = tag.getInt("time");
|
||||
CompoundTag catalysts = tag.getCompound("catalysts");
|
||||
for(int i = 0; i < recipe.catalysts.length; i++) {
|
||||
String key = Integer.toString(i);
|
||||
CompoundSerializer<Ingredient> cataSerializer = this.toSerializer(recipe.catalysts[i]);
|
||||
recipe.catalysts[i] = cataSerializer.fromTag(catalysts.getCompound(key));
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
|
||||
public CompoundTag toTag(InfusionRecipe recipe, CompoundTag tag) {
|
||||
CompoundSerializer<?> inputSerializer = this.toSerializer(recipe.input);
|
||||
tag.put("input", inputSerializer.toTag(new CompoundTag()));
|
||||
tag.put("output", recipe.output.toTag(new CompoundTag()));
|
||||
tag.putInt("time", recipe.time);
|
||||
CompoundTag catalysts = new CompoundTag();
|
||||
for(int i = 0; i < recipe.catalysts.length; i++) {
|
||||
String key = Integer.toString(i);
|
||||
CompoundSerializer<?> cataSerializer = this.toSerializer(recipe.catalysts[i]);
|
||||
catalysts.put(key, cataSerializer.toTag(new CompoundTag()));
|
||||
}
|
||||
tag.put("catalysts", catalysts);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CompoundSerializer<Ingredient> toSerializer(Ingredient ingredient) {
|
||||
return CompoundSerializer.class.cast(ingredient);
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.recipe.builders;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.interfaces.CompoundSerializer;
|
||||
import ru.betterend.recipe.EndRecipeManager;
|
||||
import ru.betterend.rituals.InfusionRitual;
|
||||
|
||||
public class InfusionRecipe implements Recipe<InfusionRitual> {
|
||||
|
||||
public final static String GROUP = "infusion";
|
||||
public final static RecipeType<InfusionRecipe> TYPE = EndRecipeManager.registerType(GROUP);
|
||||
public final static Serializer SERIALIZER = EndRecipeManager.registerSerializer(GROUP, new Serializer());
|
||||
public final static Identifier ID = BetterEnd.makeID(GROUP);
|
||||
|
||||
private final Identifier id;
|
||||
private Ingredient input;
|
||||
private ItemStack output;
|
||||
private int time = 1;
|
||||
private Ingredient[] catalysts = new Ingredient[8];
|
||||
|
||||
private InfusionRecipe(Identifier id) {
|
||||
this(id, null, null);
|
||||
}
|
||||
|
||||
private InfusionRecipe(Identifier id, Ingredient input, ItemStack output) {
|
||||
this.id = id;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
Arrays.fill(catalysts, Ingredient.EMPTY);
|
||||
}
|
||||
|
||||
public int getInfusionTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(InfusionRitual inv, World world) {
|
||||
boolean valid = this.input.test(inv.getStack(0));
|
||||
if (!valid) return false;
|
||||
for (int i = 1; i < 9; i++) {
|
||||
valid &= this.catalysts[i].test(inv.getStack(i));
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(InfusionRitual ritual) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public InfusionRecipe fromTag(CompoundTag tag) {
|
||||
return SERIALIZER.fromTag(tag);
|
||||
}
|
||||
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
return SERIALIZER.toTag(this, tag);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
|
||||
public static Builder create(String id) {
|
||||
return create(BetterEnd.makeID(id));
|
||||
}
|
||||
|
||||
public static Builder create(Identifier id) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.input = null;
|
||||
INSTANCE.output = null;
|
||||
INSTANCE.time = 1;
|
||||
|
||||
Arrays.fill(INSTANCE.catalysts, Ingredient.EMPTY);
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private Identifier id;
|
||||
private Ingredient input;
|
||||
private ItemStack output;
|
||||
private int time = 1;
|
||||
private Ingredient[] catalysts = new Ingredient[8];
|
||||
|
||||
private Builder() {
|
||||
Arrays.fill(catalysts, Ingredient.EMPTY);
|
||||
}
|
||||
|
||||
public Builder setInput(ItemConvertible input) {
|
||||
this.input = Ingredient.ofItems(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutput(ItemStack output) {
|
||||
this.output = output;
|
||||
this.output.setCount(1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTime(int time) {
|
||||
this.time = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addCatalyst(int slot, ItemConvertible item) {
|
||||
if (slot > 7) return this;
|
||||
this.catalysts[slot] = Ingredient.ofItems(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (input == null) {
|
||||
BetterEnd.LOGGER.warning("Input for Infusion recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (output == null) {
|
||||
BetterEnd.LOGGER.warning("Output for Infusion recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
InfusionRecipe recipe = new InfusionRecipe(id, input, output);
|
||||
recipe.time = time;
|
||||
int empty = 0;
|
||||
for (int i = 0; i < catalysts.length; i++) {
|
||||
if (catalysts[i].isEmpty()) empty++;
|
||||
else recipe.catalysts[i] = catalysts[i];
|
||||
}
|
||||
if (empty == catalysts.length) {
|
||||
BetterEnd.LOGGER.warning("At least one catalyst must be non empty, recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
EndRecipeManager.addRecipe(TYPE, recipe);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<InfusionRecipe> {
|
||||
@Override
|
||||
public InfusionRecipe read(Identifier id, JsonObject json) {
|
||||
InfusionRecipe recipe = new InfusionRecipe(id);
|
||||
recipe.input = Ingredient.fromJson(json.get("input"));
|
||||
Identifier outId = new Identifier(JsonHelper.getString(json, "output"));
|
||||
recipe.output = new ItemStack(Registry.ITEM.getOrEmpty(outId).orElseThrow(() -> {
|
||||
return new IllegalStateException("Item: " + outId + " does not exists!");
|
||||
}));
|
||||
recipe.time = JsonHelper.getInt(json, "time", 1);
|
||||
JsonArray catalysts = JsonHelper.asArray(json, "catalysts");
|
||||
for (int i = 0; i < catalysts.size(); i++) {
|
||||
ItemStack stack = new ItemStack(Registry.ITEM.getOrEmpty(outId).orElse(null));
|
||||
recipe.catalysts[i] = Ingredient.ofStacks(
|
||||
Arrays.stream(new ItemStack[] { stack }));
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfusionRecipe read(Identifier id, PacketByteBuf buffer) {
|
||||
InfusionRecipe recipe = new InfusionRecipe(id);
|
||||
recipe.input = Ingredient.fromPacket(buffer);
|
||||
recipe.output = buffer.readItemStack();
|
||||
recipe.time = buffer.readVarInt();
|
||||
for (int i = 0; i < 9; i++) {
|
||||
recipe.catalysts[i] = Ingredient.fromPacket(buffer);
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf buffer, InfusionRecipe recipe) {
|
||||
recipe.input.write(buffer);
|
||||
buffer.writeItemStack(recipe.output);
|
||||
buffer.writeVarInt(recipe.time);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
recipe.catalysts[i].write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public InfusionRecipe fromTag(CompoundTag tag) {
|
||||
Identifier id = new Identifier(tag.getString("id"));
|
||||
InfusionRecipe recipe = new InfusionRecipe(id);
|
||||
CompoundSerializer<Ingredient> inputSerializer = this.toSerializer(recipe.input);
|
||||
recipe.input = inputSerializer.fromTag(tag.getCompound("input"));
|
||||
recipe.output = ItemStack.fromTag(tag.getCompound("output"));
|
||||
recipe.time = tag.getInt("time");
|
||||
CompoundTag catalysts = tag.getCompound("catalysts");
|
||||
for(int i = 0; i < recipe.catalysts.length; i++) {
|
||||
String key = Integer.toString(i);
|
||||
CompoundSerializer<Ingredient> cataSerializer = this.toSerializer(recipe.catalysts[i]);
|
||||
recipe.catalysts[i] = cataSerializer.fromTag(catalysts.getCompound(key));
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
|
||||
public CompoundTag toTag(InfusionRecipe recipe, CompoundTag tag) {
|
||||
CompoundSerializer<?> inputSerializer = this.toSerializer(recipe.input);
|
||||
tag.put("input", inputSerializer.toTag(new CompoundTag()));
|
||||
tag.put("output", recipe.output.toTag(new CompoundTag()));
|
||||
tag.putInt("time", recipe.time);
|
||||
CompoundTag catalysts = new CompoundTag();
|
||||
for(int i = 0; i < recipe.catalysts.length; i++) {
|
||||
String key = Integer.toString(i);
|
||||
CompoundSerializer<?> cataSerializer = this.toSerializer(recipe.catalysts[i]);
|
||||
catalysts.put(key, cataSerializer.toTag(new CompoundTag()));
|
||||
}
|
||||
tag.put("catalysts", catalysts);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CompoundSerializer<Ingredient> toSerializer(Ingredient ingredient) {
|
||||
return CompoundSerializer.class.cast(ingredient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,479 +1,479 @@
|
|||
package ru.betterend.rituals;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.particle.BlockStateParticleEffect;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeatures;
|
||||
import ru.betterend.blocks.BlockProperties;
|
||||
import ru.betterend.blocks.EndPortalBlock;
|
||||
import ru.betterend.blocks.RunedFlavolite;
|
||||
import ru.betterend.blocks.entities.EternalPedestalEntity;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndTags;
|
||||
|
||||
public class EternalRitual {
|
||||
private final static Set<Point> STRUCTURE_MAP = Sets.newHashSet(
|
||||
new Point(-4, -5), new Point(-4, 5), new Point(-6, 0),
|
||||
new Point(4, -5), new Point(4, 5), new Point(6, 0));
|
||||
private final static Set<Point> FRAME_MAP = Sets.newHashSet(
|
||||
new Point(0, 0), new Point(0, 6), new Point(1, 0),
|
||||
new Point(1, 6), new Point(2, 1), new Point(2, 5),
|
||||
new Point(3, 2), new Point(3, 3), new Point(3, 4));
|
||||
private final static Set<Point> PORTAL_MAP = Sets.newHashSet(
|
||||
new Point(0, 0), new Point(0, 1), new Point(0, 2),
|
||||
new Point(0, 3), new Point(0, 4), new Point(1, 0),
|
||||
new Point(1, 1), new Point(1, 2), new Point(1, 3),
|
||||
new Point(1, 4), new Point(2, 1), new Point(2, 2),
|
||||
new Point(2, 3));
|
||||
private final static Set<Point> BASE_MAP = Sets.newHashSet(
|
||||
new Point(3, 0), new Point(2, 0), new Point(2, 1), new Point(1, 1),
|
||||
new Point(1, 2), new Point(0, 1), new Point(0, 2));
|
||||
|
||||
private final static Block BASE = EndBlocks.FLAVOLITE.tiles;
|
||||
private final static Block PEDESTAL = EndBlocks.ETERNAL_PEDESTAL;
|
||||
private final static Block FRAME = EndBlocks.FLAVOLITE_RUNED_ETERNAL;
|
||||
private final static Block PORTAL = EndBlocks.END_PORTAL_BLOCK;
|
||||
private final static BooleanProperty ACTIVE = BlockProperties.ACTIVATED;
|
||||
|
||||
private World world;
|
||||
private Direction.Axis axis;
|
||||
private BlockPos center;
|
||||
private BlockPos exit;
|
||||
private boolean active = false;
|
||||
|
||||
public EternalRitual(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public EternalRitual(World world, BlockPos initial) {
|
||||
this(world);
|
||||
this.configure(initial);
|
||||
}
|
||||
|
||||
public boolean hasWorld() {
|
||||
return this.world != null;
|
||||
}
|
||||
|
||||
public void setWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
private boolean isValid() {
|
||||
return world != null && !world.isClient() &&
|
||||
center != null && axis != null &&
|
||||
world.getRegistryKey() != World.NETHER;
|
||||
}
|
||||
|
||||
public void checkStructure() {
|
||||
if (!isValid()) return;
|
||||
Direction moveX, moveY;
|
||||
if (Direction.Axis.X == axis) {
|
||||
moveX = Direction.EAST;
|
||||
moveY = Direction.NORTH;
|
||||
} else {
|
||||
moveX = Direction.SOUTH;
|
||||
moveY = Direction.EAST;
|
||||
}
|
||||
boolean valid = this.checkFrame();
|
||||
for (Point pos : STRUCTURE_MAP) {
|
||||
BlockPos.Mutable checkPos = center.mutableCopy();
|
||||
checkPos.move(moveX, pos.x).move(moveY, pos.y);
|
||||
valid &= this.isActive(checkPos);
|
||||
}
|
||||
if (valid) {
|
||||
this.activatePortal();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkFrame() {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
boolean valid = true;
|
||||
for (Point point : FRAME_MAP) {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
valid &= state.getBlock() instanceof RunedFlavolite;
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
state = world.getBlockState(pos);
|
||||
valid &= state.getBlock() instanceof RunedFlavolite;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
private void activatePortal() {
|
||||
if (active) return;
|
||||
this.activatePortal(world, center);
|
||||
this.doEffects((ServerWorld) world, center);
|
||||
if (exit == null) {
|
||||
this.exit = this.findPortalPos();
|
||||
} else {
|
||||
World targetWorld = this.getTargetWorld();
|
||||
this.activatePortal(targetWorld, exit);
|
||||
}
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
private void doEffects(ServerWorld serverWorld, BlockPos center) {
|
||||
Direction moveX, moveY;
|
||||
if (Direction.Axis.X == axis) {
|
||||
moveX = Direction.EAST;
|
||||
moveY = Direction.NORTH;
|
||||
} else {
|
||||
moveX = Direction.SOUTH;
|
||||
moveY = Direction.EAST;
|
||||
}
|
||||
for (Point pos : STRUCTURE_MAP) {
|
||||
BlockPos.Mutable p = center.mutableCopy();
|
||||
p.move(moveX, pos.x).move(moveY, pos.y);
|
||||
serverWorld.spawnParticles(ParticleTypes.PORTAL, p.getX() + 0.5, p.getY() + 1.5, p.getZ() + 0.5, 20, 0, 0, 0, 1);
|
||||
serverWorld.spawnParticles(ParticleTypes.REVERSE_PORTAL, p.getX() + 0.5, p.getY() + 1.5, p.getZ() + 0.5, 20, 0, 0, 0, 0.3);
|
||||
}
|
||||
serverWorld.playSound(null, center, SoundEvents.BLOCK_END_PORTAL_SPAWN, SoundCategory.NEUTRAL, 16, 1);
|
||||
}
|
||||
|
||||
private void activatePortal(World world, BlockPos center) {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
BlockState frame = FRAME.getDefaultState().with(ACTIVE, true);
|
||||
FRAME_MAP.forEach(point -> {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (state.contains(ACTIVE) && !state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, frame);
|
||||
}
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
state = world.getBlockState(pos);
|
||||
if (state.contains(ACTIVE) && !state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, frame);
|
||||
}
|
||||
});
|
||||
Direction.Axis portalAxis = Direction.Axis.X == axis ? Direction.Axis.Z : Direction.Axis.X;
|
||||
BlockState portal = PORTAL.getDefaultState().with(EndPortalBlock.AXIS, portalAxis);
|
||||
ParticleEffect effect = new BlockStateParticleEffect(ParticleTypes.BLOCK, portal);
|
||||
ServerWorld serverWorld = (ServerWorld) world;
|
||||
|
||||
PORTAL_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.setBlockState(pos, portal);
|
||||
serverWorld.spawnParticles(effect, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.1);
|
||||
serverWorld.spawnParticles(ParticleTypes.REVERSE_PORTAL, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.3);
|
||||
}
|
||||
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.setBlockState(pos, portal);
|
||||
serverWorld.spawnParticles(effect, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.1);
|
||||
serverWorld.spawnParticles(ParticleTypes.REVERSE_PORTAL, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.3);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void removePortal() {
|
||||
if (!active || !isValid()) return;
|
||||
World targetWorld = this.getTargetWorld();
|
||||
this.removePortal(world, center);
|
||||
this.removePortal(targetWorld, exit);
|
||||
}
|
||||
|
||||
private void removePortal(World world, BlockPos center) {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
FRAME_MAP.forEach(point -> {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (state.isOf(FRAME) && state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, state.with(ACTIVE, false));
|
||||
}
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
state = world.getBlockState(pos);
|
||||
if (state.isOf(FRAME) && state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, state.with(ACTIVE, false));
|
||||
}
|
||||
});
|
||||
PORTAL_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
if (world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
if (world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
});
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
private BlockPos findPortalPos() {
|
||||
MinecraftServer server = world.getServer();
|
||||
ServerWorld targetWorld = (ServerWorld) this.getTargetWorld();
|
||||
Registry<DimensionType> registry = server.getRegistryManager().getDimensionTypes();
|
||||
double mult = registry.get(DimensionType.THE_END_ID).getCoordinateScale();
|
||||
BlockPos.Mutable basePos = center.mutableCopy().set(center.getX() / mult, center.getY(), center.getZ() / mult);
|
||||
Direction.Axis portalAxis = Direction.Axis.X == axis ? Direction.Axis.Z : Direction.Axis.X;
|
||||
if (checkIsAreaValid(targetWorld, basePos, portalAxis)) {
|
||||
EternalRitual.generatePortal(targetWorld, basePos, portalAxis);
|
||||
if (portalAxis.equals(Direction.Axis.X)) {
|
||||
return basePos.toImmutable();
|
||||
} else {
|
||||
return basePos.toImmutable();
|
||||
}
|
||||
} else {
|
||||
Direction direction = Direction.EAST;
|
||||
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
||||
for (int step = 1; step < 64; step++) {
|
||||
for (int i = 0; i < step; i++) {
|
||||
checkPos.setY(5);
|
||||
while(checkPos.getY() < world.getHeight()) {
|
||||
if(checkIsAreaValid(targetWorld, checkPos, portalAxis)) {
|
||||
EternalRitual.generatePortal(targetWorld, checkPos, portalAxis);
|
||||
if (portalAxis.equals(Direction.Axis.X)) {
|
||||
return checkPos.toImmutable();
|
||||
} else {
|
||||
return checkPos.toImmutable();
|
||||
}
|
||||
}
|
||||
checkPos.move(Direction.UP);
|
||||
}
|
||||
checkPos.move(direction);
|
||||
}
|
||||
direction = direction.rotateYClockwise();
|
||||
}
|
||||
}
|
||||
if (targetWorld.getRegistryKey() == World.END) {
|
||||
ConfiguredFeatures.END_ISLAND.generate(targetWorld, targetWorld.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos.down());
|
||||
} else {
|
||||
basePos.setY(targetWorld.getChunk(basePos).sampleHeightmap(Heightmap.Type.WORLD_SURFACE, basePos.getX(), basePos.getZ()) + 1);
|
||||
}
|
||||
EternalRitual.generatePortal(targetWorld, basePos, portalAxis);
|
||||
if (portalAxis.equals(Direction.Axis.X)) {
|
||||
return basePos.toImmutable();
|
||||
} else {
|
||||
return basePos.toImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
private World getTargetWorld() {
|
||||
RegistryKey<World> target = world.getRegistryKey() == World.END ? World.OVERWORLD : World.END;
|
||||
return world.getServer().getWorld(target);
|
||||
}
|
||||
|
||||
private boolean checkIsAreaValid(World world, BlockPos pos, Direction.Axis axis) {
|
||||
if (!isBaseValid(world, pos, axis)) return false;
|
||||
return EternalRitual.checkArea(world, pos, axis);
|
||||
}
|
||||
|
||||
private boolean isBaseValid(World world, BlockPos pos, Direction.Axis axis) {
|
||||
boolean solid = true;
|
||||
if (axis.equals(Direction.Axis.X)) {
|
||||
pos = pos.down().add(0, 0, -3);
|
||||
for (int i = 0; i < 7; i++) {
|
||||
BlockPos checkPos = pos.add(0, 0, i);
|
||||
BlockState state = world.getBlockState(checkPos);
|
||||
solid &= this.validBlock(world, checkPos, state);
|
||||
}
|
||||
} else {
|
||||
pos = pos.down().add(-3, 0, 0);
|
||||
for (int i = 0; i < 7; i++) {
|
||||
BlockPos checkPos = pos.add(i, 0, 0);
|
||||
BlockState state = world.getBlockState(checkPos);
|
||||
solid &= this.validBlock(world, checkPos, state);
|
||||
}
|
||||
}
|
||||
return solid;
|
||||
}
|
||||
|
||||
private boolean validBlock(World world, BlockPos pos, BlockState state) {
|
||||
BlockState surfaceBlock = world.getBiome(pos).getGenerationSettings().getSurfaceConfig().getTopMaterial();
|
||||
return state.isSolidBlock(world, pos) &&
|
||||
(EndTags.validGenBlock(state) ||
|
||||
state.isOf(surfaceBlock.getBlock()) ||
|
||||
state.isOf(Blocks.STONE) ||
|
||||
state.isOf(Blocks.SAND) ||
|
||||
state.isOf(Blocks.GRAVEL));
|
||||
}
|
||||
|
||||
public static void generatePortal(World world, BlockPos center, Direction.Axis axis) {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.EAST: Direction.NORTH;
|
||||
BlockState frame = FRAME.getDefaultState().with(ACTIVE, true);
|
||||
FRAME_MAP.forEach(point -> {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, frame);
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, frame);
|
||||
});
|
||||
BlockState portal = PORTAL.getDefaultState().with(EndPortalBlock.AXIS, axis);
|
||||
PORTAL_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, portal);
|
||||
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, portal);
|
||||
});
|
||||
generateBase(world, framePos, moveDir);
|
||||
}
|
||||
|
||||
private static void generateBase(World world, BlockPos center, Direction moveX) {
|
||||
BlockState base = BASE.getDefaultState();
|
||||
Direction moveY = moveX.rotateYClockwise();
|
||||
BASE_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveX, point.x).move(moveY, point.y);
|
||||
world.setBlockState(pos, base);
|
||||
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, point.y);
|
||||
world.setBlockState(pos, base);
|
||||
pos = center.mutableCopy().move(moveX, point.x).move(moveY, -point.y);
|
||||
world.setBlockState(pos, base);
|
||||
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, -point.y);
|
||||
world.setBlockState(pos, base);
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean checkArea(World world, BlockPos center, Direction.Axis axis) {
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
for (BlockPos checkPos : BlockPos.iterate(center.offset(moveDir.rotateYClockwise()), center.offset(moveDir.rotateYCounterclockwise()))) {
|
||||
for (Point point : PORTAL_MAP) {
|
||||
BlockPos pos = checkPos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isAir()) return false;
|
||||
pos = checkPos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isAir()) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void configure(BlockPos initial) {
|
||||
BlockPos checkPos = initial.east(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
this.center = initial.east(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.west(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
this.center = initial.west(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.south(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
this.center = initial.south(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.north(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
this.center = initial.north(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.north(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
checkPos = checkPos.east(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.north(5).east(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.north(5).west(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkPos = initial.south(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
checkPos = checkPos.east(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.south(5).east(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.south(5).west(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkPos = initial.east(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
checkPos = checkPos.south(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.east(5).south(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.east(5).north(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkPos = initial.west(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
checkPos = checkPos.south(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.west(5).south(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.west(5).north(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasPedestal(BlockPos pos) {
|
||||
return world.getBlockState(pos).isOf(PEDESTAL);
|
||||
}
|
||||
|
||||
private boolean isActive(BlockPos pos) {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (state.isOf(PEDESTAL)) {
|
||||
EternalPedestalEntity pedestal = (EternalPedestalEntity) world.getBlockEntity(pos);
|
||||
if (!pedestal.hasRitual()) {
|
||||
pedestal.linkRitual(this);
|
||||
}
|
||||
return state.get(ACTIVE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
tag.put("center", NbtHelper.fromBlockPos(center));
|
||||
if (exit != null) {
|
||||
tag.put("exit", NbtHelper.fromBlockPos(exit));
|
||||
}
|
||||
tag.putString("axis", axis.getName());
|
||||
tag.putBoolean("active", active);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void fromTag(CompoundTag tag) {
|
||||
this.axis = Direction.Axis.fromName(tag.getString("axis"));
|
||||
this.center = NbtHelper.toBlockPos(tag.getCompound("center"));
|
||||
this.active = tag.getBoolean("active");
|
||||
if (tag.contains("exit")) {
|
||||
this.exit = NbtHelper.toBlockPos(tag.getCompound("exit"));
|
||||
}
|
||||
}
|
||||
}
|
||||
package ru.betterend.rituals;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.particle.BlockStateParticleEffect;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeatures;
|
||||
import ru.betterend.blocks.BlockProperties;
|
||||
import ru.betterend.blocks.EndPortalBlock;
|
||||
import ru.betterend.blocks.RunedFlavolite;
|
||||
import ru.betterend.blocks.entities.EternalPedestalEntity;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.registry.EndTags;
|
||||
|
||||
public class EternalRitual {
|
||||
private final static Set<Point> STRUCTURE_MAP = Sets.newHashSet(
|
||||
new Point(-4, -5), new Point(-4, 5), new Point(-6, 0),
|
||||
new Point(4, -5), new Point(4, 5), new Point(6, 0));
|
||||
private final static Set<Point> FRAME_MAP = Sets.newHashSet(
|
||||
new Point(0, 0), new Point(0, 6), new Point(1, 0),
|
||||
new Point(1, 6), new Point(2, 1), new Point(2, 5),
|
||||
new Point(3, 2), new Point(3, 3), new Point(3, 4));
|
||||
private final static Set<Point> PORTAL_MAP = Sets.newHashSet(
|
||||
new Point(0, 0), new Point(0, 1), new Point(0, 2),
|
||||
new Point(0, 3), new Point(0, 4), new Point(1, 0),
|
||||
new Point(1, 1), new Point(1, 2), new Point(1, 3),
|
||||
new Point(1, 4), new Point(2, 1), new Point(2, 2),
|
||||
new Point(2, 3));
|
||||
private final static Set<Point> BASE_MAP = Sets.newHashSet(
|
||||
new Point(3, 0), new Point(2, 0), new Point(2, 1), new Point(1, 1),
|
||||
new Point(1, 2), new Point(0, 1), new Point(0, 2));
|
||||
|
||||
private final static Block BASE = EndBlocks.FLAVOLITE.tiles;
|
||||
private final static Block PEDESTAL = EndBlocks.ETERNAL_PEDESTAL;
|
||||
private final static Block FRAME = EndBlocks.FLAVOLITE_RUNED_ETERNAL;
|
||||
private final static Block PORTAL = EndBlocks.END_PORTAL_BLOCK;
|
||||
private final static BooleanProperty ACTIVE = BlockProperties.ACTIVATED;
|
||||
|
||||
private World world;
|
||||
private Direction.Axis axis;
|
||||
private BlockPos center;
|
||||
private BlockPos exit;
|
||||
private boolean active = false;
|
||||
|
||||
public EternalRitual(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public EternalRitual(World world, BlockPos initial) {
|
||||
this(world);
|
||||
this.configure(initial);
|
||||
}
|
||||
|
||||
public boolean hasWorld() {
|
||||
return this.world != null;
|
||||
}
|
||||
|
||||
public void setWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
private boolean isValid() {
|
||||
return world != null && !world.isClient() &&
|
||||
center != null && axis != null &&
|
||||
world.getRegistryKey() != World.NETHER;
|
||||
}
|
||||
|
||||
public void checkStructure() {
|
||||
if (!isValid()) return;
|
||||
Direction moveX, moveY;
|
||||
if (Direction.Axis.X == axis) {
|
||||
moveX = Direction.EAST;
|
||||
moveY = Direction.NORTH;
|
||||
} else {
|
||||
moveX = Direction.SOUTH;
|
||||
moveY = Direction.EAST;
|
||||
}
|
||||
boolean valid = this.checkFrame();
|
||||
for (Point pos : STRUCTURE_MAP) {
|
||||
BlockPos.Mutable checkPos = center.mutableCopy();
|
||||
checkPos.move(moveX, pos.x).move(moveY, pos.y);
|
||||
valid &= this.isActive(checkPos);
|
||||
}
|
||||
if (valid) {
|
||||
this.activatePortal();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkFrame() {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
boolean valid = true;
|
||||
for (Point point : FRAME_MAP) {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
valid &= state.getBlock() instanceof RunedFlavolite;
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
state = world.getBlockState(pos);
|
||||
valid &= state.getBlock() instanceof RunedFlavolite;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
private void activatePortal() {
|
||||
if (active) return;
|
||||
this.activatePortal(world, center);
|
||||
this.doEffects((ServerWorld) world, center);
|
||||
if (exit == null) {
|
||||
this.exit = this.findPortalPos();
|
||||
} else {
|
||||
World targetWorld = this.getTargetWorld();
|
||||
this.activatePortal(targetWorld, exit);
|
||||
}
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
private void doEffects(ServerWorld serverWorld, BlockPos center) {
|
||||
Direction moveX, moveY;
|
||||
if (Direction.Axis.X == axis) {
|
||||
moveX = Direction.EAST;
|
||||
moveY = Direction.NORTH;
|
||||
} else {
|
||||
moveX = Direction.SOUTH;
|
||||
moveY = Direction.EAST;
|
||||
}
|
||||
for (Point pos : STRUCTURE_MAP) {
|
||||
BlockPos.Mutable p = center.mutableCopy();
|
||||
p.move(moveX, pos.x).move(moveY, pos.y);
|
||||
serverWorld.spawnParticles(ParticleTypes.PORTAL, p.getX() + 0.5, p.getY() + 1.5, p.getZ() + 0.5, 20, 0, 0, 0, 1);
|
||||
serverWorld.spawnParticles(ParticleTypes.REVERSE_PORTAL, p.getX() + 0.5, p.getY() + 1.5, p.getZ() + 0.5, 20, 0, 0, 0, 0.3);
|
||||
}
|
||||
serverWorld.playSound(null, center, SoundEvents.BLOCK_END_PORTAL_SPAWN, SoundCategory.NEUTRAL, 16, 1);
|
||||
}
|
||||
|
||||
private void activatePortal(World world, BlockPos center) {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
BlockState frame = FRAME.getDefaultState().with(ACTIVE, true);
|
||||
FRAME_MAP.forEach(point -> {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (state.contains(ACTIVE) && !state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, frame);
|
||||
}
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
state = world.getBlockState(pos);
|
||||
if (state.contains(ACTIVE) && !state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, frame);
|
||||
}
|
||||
});
|
||||
Direction.Axis portalAxis = Direction.Axis.X == axis ? Direction.Axis.Z : Direction.Axis.X;
|
||||
BlockState portal = PORTAL.getDefaultState().with(EndPortalBlock.AXIS, portalAxis);
|
||||
ParticleEffect effect = new BlockStateParticleEffect(ParticleTypes.BLOCK, portal);
|
||||
ServerWorld serverWorld = (ServerWorld) world;
|
||||
|
||||
PORTAL_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.setBlockState(pos, portal);
|
||||
serverWorld.spawnParticles(effect, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.1);
|
||||
serverWorld.spawnParticles(ParticleTypes.REVERSE_PORTAL, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.3);
|
||||
}
|
||||
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.setBlockState(pos, portal);
|
||||
serverWorld.spawnParticles(effect, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.1);
|
||||
serverWorld.spawnParticles(ParticleTypes.REVERSE_PORTAL, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.5, 0.5, 0.5, 0.3);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void removePortal() {
|
||||
if (!active || !isValid()) return;
|
||||
World targetWorld = this.getTargetWorld();
|
||||
this.removePortal(world, center);
|
||||
this.removePortal(targetWorld, exit);
|
||||
}
|
||||
|
||||
private void removePortal(World world, BlockPos center) {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
FRAME_MAP.forEach(point -> {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (state.isOf(FRAME) && state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, state.with(ACTIVE, false));
|
||||
}
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
state = world.getBlockState(pos);
|
||||
if (state.isOf(FRAME) && state.get(ACTIVE)) {
|
||||
world.setBlockState(pos, state.with(ACTIVE, false));
|
||||
}
|
||||
});
|
||||
PORTAL_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
if (world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
if (world.getBlockState(pos).isOf(PORTAL)) {
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
});
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
private BlockPos findPortalPos() {
|
||||
MinecraftServer server = world.getServer();
|
||||
ServerWorld targetWorld = (ServerWorld) this.getTargetWorld();
|
||||
Registry<DimensionType> registry = server.getRegistryManager().getDimensionTypes();
|
||||
double mult = registry.get(DimensionType.THE_END_ID).getCoordinateScale();
|
||||
BlockPos.Mutable basePos = center.mutableCopy().set(center.getX() / mult, center.getY(), center.getZ() / mult);
|
||||
Direction.Axis portalAxis = Direction.Axis.X == axis ? Direction.Axis.Z : Direction.Axis.X;
|
||||
if (checkIsAreaValid(targetWorld, basePos, portalAxis)) {
|
||||
EternalRitual.generatePortal(targetWorld, basePos, portalAxis);
|
||||
if (portalAxis.equals(Direction.Axis.X)) {
|
||||
return basePos.toImmutable();
|
||||
} else {
|
||||
return basePos.toImmutable();
|
||||
}
|
||||
} else {
|
||||
Direction direction = Direction.EAST;
|
||||
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
||||
for (int step = 1; step < 64; step++) {
|
||||
for (int i = 0; i < step; i++) {
|
||||
checkPos.setY(5);
|
||||
while(checkPos.getY() < world.getHeight()) {
|
||||
if(checkIsAreaValid(targetWorld, checkPos, portalAxis)) {
|
||||
EternalRitual.generatePortal(targetWorld, checkPos, portalAxis);
|
||||
if (portalAxis.equals(Direction.Axis.X)) {
|
||||
return checkPos.toImmutable();
|
||||
} else {
|
||||
return checkPos.toImmutable();
|
||||
}
|
||||
}
|
||||
checkPos.move(Direction.UP);
|
||||
}
|
||||
checkPos.move(direction);
|
||||
}
|
||||
direction = direction.rotateYClockwise();
|
||||
}
|
||||
}
|
||||
if (targetWorld.getRegistryKey() == World.END) {
|
||||
ConfiguredFeatures.END_ISLAND.generate(targetWorld, targetWorld.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos.down());
|
||||
} else {
|
||||
basePos.setY(targetWorld.getChunk(basePos).sampleHeightmap(Heightmap.Type.WORLD_SURFACE, basePos.getX(), basePos.getZ()) + 1);
|
||||
}
|
||||
EternalRitual.generatePortal(targetWorld, basePos, portalAxis);
|
||||
if (portalAxis.equals(Direction.Axis.X)) {
|
||||
return basePos.toImmutable();
|
||||
} else {
|
||||
return basePos.toImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
private World getTargetWorld() {
|
||||
RegistryKey<World> target = world.getRegistryKey() == World.END ? World.OVERWORLD : World.END;
|
||||
return world.getServer().getWorld(target);
|
||||
}
|
||||
|
||||
private boolean checkIsAreaValid(World world, BlockPos pos, Direction.Axis axis) {
|
||||
if (!isBaseValid(world, pos, axis)) return false;
|
||||
return EternalRitual.checkArea(world, pos, axis);
|
||||
}
|
||||
|
||||
private boolean isBaseValid(World world, BlockPos pos, Direction.Axis axis) {
|
||||
boolean solid = true;
|
||||
if (axis.equals(Direction.Axis.X)) {
|
||||
pos = pos.down().add(0, 0, -3);
|
||||
for (int i = 0; i < 7; i++) {
|
||||
BlockPos checkPos = pos.add(0, 0, i);
|
||||
BlockState state = world.getBlockState(checkPos);
|
||||
solid &= this.validBlock(world, checkPos, state);
|
||||
}
|
||||
} else {
|
||||
pos = pos.down().add(-3, 0, 0);
|
||||
for (int i = 0; i < 7; i++) {
|
||||
BlockPos checkPos = pos.add(i, 0, 0);
|
||||
BlockState state = world.getBlockState(checkPos);
|
||||
solid &= this.validBlock(world, checkPos, state);
|
||||
}
|
||||
}
|
||||
return solid;
|
||||
}
|
||||
|
||||
private boolean validBlock(World world, BlockPos pos, BlockState state) {
|
||||
BlockState surfaceBlock = world.getBiome(pos).getGenerationSettings().getSurfaceConfig().getTopMaterial();
|
||||
return state.isSolidBlock(world, pos) &&
|
||||
(EndTags.validGenBlock(state) ||
|
||||
state.isOf(surfaceBlock.getBlock()) ||
|
||||
state.isOf(Blocks.STONE) ||
|
||||
state.isOf(Blocks.SAND) ||
|
||||
state.isOf(Blocks.GRAVEL));
|
||||
}
|
||||
|
||||
public static void generatePortal(World world, BlockPos center, Direction.Axis axis) {
|
||||
BlockPos framePos = center.down();
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.EAST: Direction.NORTH;
|
||||
BlockState frame = FRAME.getDefaultState().with(ACTIVE, true);
|
||||
FRAME_MAP.forEach(point -> {
|
||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, frame);
|
||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, frame);
|
||||
});
|
||||
BlockState portal = PORTAL.getDefaultState().with(EndPortalBlock.AXIS, axis);
|
||||
PORTAL_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, portal);
|
||||
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
world.setBlockState(pos, portal);
|
||||
});
|
||||
generateBase(world, framePos, moveDir);
|
||||
}
|
||||
|
||||
private static void generateBase(World world, BlockPos center, Direction moveX) {
|
||||
BlockState base = BASE.getDefaultState();
|
||||
Direction moveY = moveX.rotateYClockwise();
|
||||
BASE_MAP.forEach(point -> {
|
||||
BlockPos pos = center.mutableCopy().move(moveX, point.x).move(moveY, point.y);
|
||||
world.setBlockState(pos, base);
|
||||
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, point.y);
|
||||
world.setBlockState(pos, base);
|
||||
pos = center.mutableCopy().move(moveX, point.x).move(moveY, -point.y);
|
||||
world.setBlockState(pos, base);
|
||||
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, -point.y);
|
||||
world.setBlockState(pos, base);
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean checkArea(World world, BlockPos center, Direction.Axis axis) {
|
||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH: Direction.EAST;
|
||||
for (BlockPos checkPos : BlockPos.iterate(center.offset(moveDir.rotateYClockwise()), center.offset(moveDir.rotateYCounterclockwise()))) {
|
||||
for (Point point : PORTAL_MAP) {
|
||||
BlockPos pos = checkPos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isAir()) return false;
|
||||
pos = checkPos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||
if (!world.getBlockState(pos).isAir()) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void configure(BlockPos initial) {
|
||||
BlockPos checkPos = initial.east(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
this.center = initial.east(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.west(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
this.center = initial.west(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.south(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
this.center = initial.south(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.north(12);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
this.center = initial.north(6);
|
||||
return;
|
||||
}
|
||||
checkPos = initial.north(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
checkPos = checkPos.east(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.north(5).east(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.north(5).west(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkPos = initial.south(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.X;
|
||||
checkPos = checkPos.east(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.south(5).east(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.south(5).west(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkPos = initial.east(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
checkPos = checkPos.south(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.east(5).south(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.east(5).north(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkPos = initial.west(10);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.axis = Direction.Axis.Z;
|
||||
checkPos = checkPos.south(8);
|
||||
if (this.hasPedestal(checkPos)) {
|
||||
this.center = initial.west(5).south(4);
|
||||
return;
|
||||
} else {
|
||||
this.center = initial.west(5).north(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasPedestal(BlockPos pos) {
|
||||
return world.getBlockState(pos).isOf(PEDESTAL);
|
||||
}
|
||||
|
||||
private boolean isActive(BlockPos pos) {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (state.isOf(PEDESTAL)) {
|
||||
EternalPedestalEntity pedestal = (EternalPedestalEntity) world.getBlockEntity(pos);
|
||||
if (!pedestal.hasRitual()) {
|
||||
pedestal.linkRitual(this);
|
||||
}
|
||||
return state.get(ACTIVE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
tag.put("center", NbtHelper.fromBlockPos(center));
|
||||
if (exit != null) {
|
||||
tag.put("exit", NbtHelper.fromBlockPos(exit));
|
||||
}
|
||||
tag.putString("axis", axis.getName());
|
||||
tag.putBoolean("active", active);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void fromTag(CompoundTag tag) {
|
||||
this.axis = Direction.Axis.fromName(tag.getString("axis"));
|
||||
this.center = NbtHelper.toBlockPos(tag.getCompound("center"));
|
||||
this.active = tag.getBoolean("active");
|
||||
if (tag.contains("exit")) {
|
||||
this.exit = NbtHelper.toBlockPos(tag.getCompound("exit"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,88 +1,88 @@
|
|||
package ru.betterend.rituals;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.recipe.builders.InfusionRecipe;
|
||||
|
||||
public class InfusionRitual implements Inventory {
|
||||
|
||||
private final World world;
|
||||
private final BlockPos worldPos;
|
||||
private InfusionRecipe activeRecipe;
|
||||
private int progress = 0;
|
||||
private int time = 0;
|
||||
|
||||
public InfusionRitual(World world, BlockPos pos) {
|
||||
this.world = world;
|
||||
this.worldPos = pos;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (!hasRecipe()) return;
|
||||
this.progress++;
|
||||
if (progress == time) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasRecipe() {
|
||||
return this.activeRecipe != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStack(int slot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot, int amount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(int slot, ItemStack stack) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayerUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void fromTag(CompoundTag tag) {
|
||||
}
|
||||
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
package ru.betterend.rituals;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import ru.betterend.recipe.builders.InfusionRecipe;
|
||||
|
||||
public class InfusionRitual implements Inventory {
|
||||
|
||||
private final World world;
|
||||
private final BlockPos worldPos;
|
||||
private InfusionRecipe activeRecipe;
|
||||
private int progress = 0;
|
||||
private int time = 0;
|
||||
|
||||
public InfusionRitual(World world, BlockPos pos) {
|
||||
this.world = world;
|
||||
this.worldPos = pos;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (!hasRecipe()) return;
|
||||
this.progress++;
|
||||
if (progress == time) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasRecipe() {
|
||||
return this.activeRecipe != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStack(int slot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot, int amount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(int slot, ItemStack stack) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayerUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void fromTag(CompoundTag tag) {
|
||||
}
|
||||
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
package ru.betterend.util;
|
||||
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
|
||||
public class LangUtil {
|
||||
public final static String CONFIG_ELEMENT = "configuration";
|
||||
|
||||
private String element;
|
||||
|
||||
public LangUtil(String element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
public void setElement(String key) {
|
||||
this.element = key;
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
return getString(element, key);
|
||||
}
|
||||
|
||||
public TranslatableText getText(String key) {
|
||||
return getText(element, key);
|
||||
}
|
||||
|
||||
public static String translate(String key) {
|
||||
return I18n.translate(key);
|
||||
}
|
||||
|
||||
public static String getString(String element, String key) {
|
||||
return translate(String.format("%s.%s", element, key));
|
||||
}
|
||||
|
||||
public static TranslatableText getText(String element, String key) {
|
||||
return new TranslatableText(getString(element, key));
|
||||
}
|
||||
}
|
||||
package ru.betterend.util;
|
||||
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
|
||||
public class LangUtil {
|
||||
public final static String CONFIG_ELEMENT = "configuration";
|
||||
|
||||
private String element;
|
||||
|
||||
public LangUtil(String element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
public void setElement(String key) {
|
||||
this.element = key;
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
return getString(element, key);
|
||||
}
|
||||
|
||||
public TranslatableText getText(String key) {
|
||||
return getText(element, key);
|
||||
}
|
||||
|
||||
public static String translate(String key) {
|
||||
return I18n.translate(key);
|
||||
}
|
||||
|
||||
public static String getString(String element, String key) {
|
||||
return translate(String.format("%s.%s", element, key));
|
||||
}
|
||||
|
||||
public static TranslatableText getText(String element, String key) {
|
||||
return new TranslatableText(getString(element, key));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
package ru.betterend.util;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import ru.betterend.BetterEnd;
|
||||
|
||||
public final class Logger {
|
||||
|
||||
private static final org.apache.logging.log4j.Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private String modPref = "[" + BetterEnd.MOD_ID + "] ";
|
||||
|
||||
private Logger() {}
|
||||
|
||||
public static Logger get() {
|
||||
return new Logger();
|
||||
}
|
||||
|
||||
public void log(Level level, String message) {
|
||||
LOGGER.log(level, modPref + message);
|
||||
}
|
||||
|
||||
public void log(Level level, String message, Object... params) {
|
||||
LOGGER.log(level, modPref + message, params);
|
||||
}
|
||||
|
||||
public void debug(Object message) {
|
||||
this.log(Level.DEBUG, message.toString());
|
||||
}
|
||||
|
||||
public void debug(Object message, Object... params) {
|
||||
this.log(Level.DEBUG, message.toString(), params);
|
||||
}
|
||||
|
||||
public void catching(Throwable ex) {
|
||||
this.error(ex.getLocalizedMessage());
|
||||
LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
public void info(String message) {
|
||||
this.log(Level.INFO, message);
|
||||
}
|
||||
|
||||
public void info(String message, Object... params) {
|
||||
this.log(Level.INFO, message, params);
|
||||
}
|
||||
|
||||
public void warning(String message, Object... params) {
|
||||
this.log(Level.WARN, message, params);
|
||||
}
|
||||
|
||||
public void warning(String message, Object obj, Exception ex) {
|
||||
LOGGER.warn(modPref + message, obj, ex);
|
||||
}
|
||||
|
||||
public void error(String message) {
|
||||
this.log(Level.ERROR, message);
|
||||
}
|
||||
|
||||
public void error(String message, Object obj, Exception ex) {
|
||||
LOGGER.error(modPref + message, obj, ex);
|
||||
}
|
||||
|
||||
public void error(String message, Exception ex) {
|
||||
LOGGER.error(modPref + message, ex);
|
||||
}
|
||||
}
|
||||
package ru.betterend.util;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import ru.betterend.BetterEnd;
|
||||
|
||||
public final class Logger {
|
||||
|
||||
private static final org.apache.logging.log4j.Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private String modPref = "[" + BetterEnd.MOD_ID + "] ";
|
||||
|
||||
private Logger() {}
|
||||
|
||||
public static Logger get() {
|
||||
return new Logger();
|
||||
}
|
||||
|
||||
public void log(Level level, String message) {
|
||||
LOGGER.log(level, modPref + message);
|
||||
}
|
||||
|
||||
public void log(Level level, String message, Object... params) {
|
||||
LOGGER.log(level, modPref + message, params);
|
||||
}
|
||||
|
||||
public void debug(Object message) {
|
||||
this.log(Level.DEBUG, message.toString());
|
||||
}
|
||||
|
||||
public void debug(Object message, Object... params) {
|
||||
this.log(Level.DEBUG, message.toString(), params);
|
||||
}
|
||||
|
||||
public void catching(Throwable ex) {
|
||||
this.error(ex.getLocalizedMessage());
|
||||
LOGGER.catching(ex);
|
||||
}
|
||||
|
||||
public void info(String message) {
|
||||
this.log(Level.INFO, message);
|
||||
}
|
||||
|
||||
public void info(String message, Object... params) {
|
||||
this.log(Level.INFO, message, params);
|
||||
}
|
||||
|
||||
public void warning(String message, Object... params) {
|
||||
this.log(Level.WARN, message, params);
|
||||
}
|
||||
|
||||
public void warning(String message, Object obj, Exception ex) {
|
||||
LOGGER.warn(modPref + message, obj, ex);
|
||||
}
|
||||
|
||||
public void error(String message) {
|
||||
this.log(Level.ERROR, message);
|
||||
}
|
||||
|
||||
public void error(String message, Object obj, Exception ex) {
|
||||
LOGGER.error(modPref + message, obj, ex);
|
||||
}
|
||||
|
||||
public void error(String message, Exception ex) {
|
||||
LOGGER.error(modPref + message, ex);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue