diff --git a/src/main/java/ru/betterend/blocks/BlockProperties.java b/src/main/java/ru/betterend/blocks/BlockProperties.java index 26cecf72..5c9af96b 100644 --- a/src/main/java/ru/betterend/blocks/BlockProperties.java +++ b/src/main/java/ru/betterend/blocks/BlockProperties.java @@ -8,6 +8,7 @@ public class BlockProperties { public static final EnumProperty TRIPLE_SHAPE = EnumProperty.of("shape", TripleShape.class); public final static EnumProperty PEDESTAL_STATE = EnumProperty.of("state", PedestalState.class); public static final BooleanProperty HAS_ITEM = BooleanProperty.of("has_item"); + public static final BooleanProperty HAS_LIGHT = BooleanProperty.of("has_light"); public static final BooleanProperty ACTIVATED = BooleanProperty.of("active"); public static enum TripleShape implements StringIdentifiable { diff --git a/src/main/java/ru/betterend/blocks/basis/BlockPedestal.java b/src/main/java/ru/betterend/blocks/basis/BlockPedestal.java index 118d8a49..51587fe0 100644 --- a/src/main/java/ru/betterend/blocks/basis/BlockPedestal.java +++ b/src/main/java/ru/betterend/blocks/basis/BlockPedestal.java @@ -46,6 +46,7 @@ import ru.betterend.util.BlocksHelper; public class BlockPedestal extends BlockBaseNotFull implements BlockEntityProvider { public final static EnumProperty STATE = BlockProperties.PEDESTAL_STATE; public static final BooleanProperty HAS_ITEM = BlockProperties.HAS_ITEM; + public static final BooleanProperty HAS_LIGHT = BlockProperties.HAS_LIGHT; private static final VoxelShape SHAPE_DEFAULT; private static final VoxelShape SHAPE_COLUMN; @@ -82,8 +83,10 @@ public class BlockPedestal extends BlockBaseNotFull implements BlockEntityProvid protected float height = 1.0F; public BlockPedestal(Block parent) { - super(FabricBlockSettings.copyOf(parent)); - this.setDefaultState(stateManager.getDefaultState().with(STATE, PedestalState.DEFAULT).with(HAS_ITEM, false)); + super(FabricBlockSettings.copyOf(parent).luminance(state -> { + return state.get(HAS_LIGHT) ? 12 : 0; + })); + this.setDefaultState(stateManager.getDefaultState().with(STATE, PedestalState.DEFAULT).with(HAS_ITEM, false).with(HAS_LIGHT, false)); this.parent = parent; } @@ -294,7 +297,7 @@ public class BlockPedestal extends BlockBaseNotFull implements BlockEntityProvid @Override protected void appendProperties(StateManager.Builder stateManager) { - stateManager.add(STATE, HAS_ITEM); + stateManager.add(STATE, HAS_ITEM, HAS_LIGHT); } @Override diff --git a/src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java b/src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java index 2e581671..86fd7126 100644 --- a/src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java +++ b/src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java @@ -12,6 +12,7 @@ import net.minecraft.util.Tickable; import net.minecraft.world.World; import ru.betterend.blocks.basis.BlockPedestal; import ru.betterend.registry.EndBlockEntities; +import ru.betterend.registry.EndItems; public class PedestalBlockEntity extends BlockEntity implements Inventory, Tickable { private ItemStack activeItem = ItemStack.EMPTY; @@ -70,7 +71,8 @@ public class PedestalBlockEntity extends BlockEntity implements Inventory, Ticka } public void removeStack(World world, BlockState state) { - world.setBlockState(pos, state.with(BlockPedestal.HAS_ITEM, false)); + world.setBlockState(pos, state.with(BlockPedestal.HAS_ITEM, false) + .with(BlockPedestal.HAS_LIGHT, false)); this.removeStack(0); } @@ -82,6 +84,11 @@ public class PedestalBlockEntity extends BlockEntity implements Inventory, Ticka public void setStack(World world, BlockState state, ItemStack stack) { world.setBlockState(pos, state.with(BlockPedestal.HAS_ITEM, true)); + if (stack.getItem() == EndItems.ETERNAL_CRYSTAL) { + world.setBlockState(pos, state.with(BlockPedestal.HAS_LIGHT, true)); + } else { + world.setBlockState(pos, state.with(BlockPedestal.HAS_LIGHT, false)); + } this.setStack(0, stack); } diff --git a/src/main/java/ru/betterend/blocks/entities/render/PedestalItemRenderer.java b/src/main/java/ru/betterend/blocks/entities/render/PedestalItemRenderer.java index 962de810..f86817c6 100644 --- a/src/main/java/ru/betterend/blocks/entities/render/PedestalItemRenderer.java +++ b/src/main/java/ru/betterend/blocks/entities/render/PedestalItemRenderer.java @@ -19,6 +19,7 @@ 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; diff --git a/src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java b/src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java index 7330f27e..f9cba339 100644 --- a/src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java +++ b/src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java @@ -9,31 +9,56 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.Vector3f; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3i; + import ru.betterend.BetterEnd; +import ru.betterend.blocks.AuroraCrystalBlock; +import ru.betterend.util.ColorUtil; +import ru.betterend.util.MHelper; public class EternalCrystalRenderer { private static final Identifier CRYSTAL_TEXTURE = BetterEnd.makeID("textures/entity/eternal_crystal.png"); private static final RenderLayer RENDER_LAYER; + private static final ModelPart SHARDS; private static final ModelPart CORE; public static void render(int age, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumerProvider, int light) { VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RENDER_LAYER); + float[] colors = colors(age); float rotation = (age + tickDelta) / 25.0F + 6.0F; - float altitude = MathHelper.sin((age + tickDelta) / 10.0F) * 0.1F + 0.1F; matrices.push(); matrices.scale(0.6F, 0.6F, 0.6F); - matrices.translate(0.0D, altitude / 2.0D, 0.0D); matrices.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion(rotation)); - matrices.push(); - matrices.translate(-0.125D, -0.1D, -0.125D); - CORE.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV); - matrices.pop(); + CORE.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, colors[0], colors[1], colors[2], colors[3]); + SHARDS.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, colors[0], colors[1], colors[2], colors[3]); matrices.pop(); } + private static float[] colors(int age) { + double delta = age * 0.01; + int index = MHelper.floor(delta); + int index2 = (index + 1) & 3; + delta -= index; + index &= 3; + + Vec3i color1 = AuroraCrystalBlock.COLORS[index]; + Vec3i color2 = AuroraCrystalBlock.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 ColorUtil.toFloatArray(MHelper.color(r, g, b)); + } + static { - RENDER_LAYER = RenderLayer.getEntityTranslucent(CRYSTAL_TEXTURE); + RENDER_LAYER = RenderLayer.getBeaconBeam(CRYSTAL_TEXTURE, true); + SHARDS = new ModelPart(16, 16, 2, 4); + SHARDS.addCuboid(-5.0F, 1.0F, -3.0F, 2.0F, 8.0F, 2.0F); + SHARDS.addCuboid(3.0F, -1.0F, -1.0F, 2.0F, 8.0F, 2.0F); + SHARDS.addCuboid(-1.0F, 0.0F, -5.0F, 2.0F, 4.0F, 2.0F); + SHARDS.addCuboid(0.0F, 3.0F, 4.0F, 2.0F, 6.0F, 2.0F); CORE = new ModelPart(16, 16, 0, 0); - CORE.addCuboid(0.0F, 0.0F, 0.0F, 4.0F, 12.0F, 4.0F); + CORE.addCuboid(-2.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F); } } diff --git a/src/main/java/ru/betterend/item/EternalCrystal.java b/src/main/java/ru/betterend/item/EternalCrystal.java index acf3b7ff..9d2cf07b 100644 --- a/src/main/java/ru/betterend/item/EternalCrystal.java +++ b/src/main/java/ru/betterend/item/EternalCrystal.java @@ -1,11 +1,18 @@ package ru.betterend.item; import net.minecraft.item.Item; +import ru.betterend.patterns.Patterned; +import ru.betterend.patterns.Patterns; import ru.betterend.registry.EndItems; -public class EternalCrystal extends Item { +public class EternalCrystal extends Item implements Patterned { public EternalCrystal() { super(EndItems.makeSettings()); } + + @Override + public String getModelPattern(String name) { + return Patterns.createJson(Patterns.ITEM_GENERATED, name); + } } \ No newline at end of file diff --git a/src/main/java/ru/betterend/util/ColorUtil.java b/src/main/java/ru/betterend/util/ColorUtil.java new file mode 100644 index 00000000..2cb6e80a --- /dev/null +++ b/src/main/java/ru/betterend/util/ColorUtil.java @@ -0,0 +1,168 @@ +package ru.betterend.util; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper; +import net.minecraft.util.math.MathHelper; + +import ru.betterend.BetterEnd; + +@Environment(EnvType.CLIENT) +public class ColorUtil { + + private static float[] floatBuffer = new float[4]; + + public static int[] toIntArray(int color) { + return new int[] { + (color >> 24) & 255, + (color >> 16) & 255, + (color >> 8) & 255, + color & 255 + }; + } + + public static float[] toFloatArray(int color) { + floatBuffer[0] = ((color >> 16 & 255) / 255.0F); + floatBuffer[1] = ((color >> 8 & 255) / 255.0F); + floatBuffer[2] = ((color & 255) / 255.0F); + floatBuffer[3] = ((color >> 24 & 255) / 255.0F); + + return floatBuffer; + } + + public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) { + float hue, saturation, brightness; + if (hsbvals == null) { + hsbvals = floatBuffer; + } + int cmax = (r > g) ? r : g; + if (b > cmax) cmax = b; + int cmin = (r < g) ? r : g; + if (b < cmin) cmin = b; + + brightness = ((float) cmax) / 255.0F; + if (cmax != 0) + saturation = ((float) (cmax - cmin)) / ((float) cmax); + else + saturation = 0; + if (saturation == 0) + hue = 0; + else { + float redc = ((float) (cmax - r)) / ((float) (cmax - cmin)); + float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin)); + float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin)); + if (r == cmax) + hue = bluec - greenc; + else if (g == cmax) + hue = 2.0F + redc - bluec; + else + hue = 4.0F + greenc - redc; + hue = hue / 6.0F; + if (hue < 0) + hue = hue + 1.0F; + } + hsbvals[0] = hue; + hsbvals[1] = saturation; + hsbvals[2] = brightness; + return hsbvals; + } + + public static int HSBtoRGB(float hue, float saturation, float brightness) { + int r = 0, g = 0, b = 0; + if (saturation == 0) { + r = g = b = (int) (brightness * 255.0F + 0.5F); + } else { + float h = (hue - (float)Math.floor(hue)) * 6.0F; + float f = h - (float)java.lang.Math.floor(h); + float p = brightness * (1.0F - saturation); + float q = brightness * (1.0F - saturation * f); + float t = brightness * (1.0F - (saturation * (1.0F - f))); + switch ((int) h) { + case 0: + r = (int) (brightness * 255.0F + 0.5F); + g = (int) (t * 255.0F + 0.5F); + b = (int) (p * 255.0F + 0.5F); + break; + case 1: + r = (int) (q * 255.0F + 0.5F); + g = (int) (brightness * 255.0F + 0.5F); + b = (int) (p * 255.0F + 0.5F); + break; + case 2: + r = (int) (p * 255.0F + 0.5F); + g = (int) (brightness * 255.0F + 0.5F); + b = (int) (t * 255.0F + 0.5F); + break; + case 3: + r = (int) (p * 255.0F + 0.5F); + g = (int) (q * 255.0F + 0.5F); + b = (int) (brightness * 255.0F + 0.5F); + break; + case 4: + r = (int) (t * 255.0F + 0.5F); + g = (int) (p * 255.0F + 0.5F); + b = (int) (brightness * 255.0F + 0.5F); + break; + case 5: + r = (int) (brightness * 255.0F + 0.5F); + g = (int) (p * 255.0F + 0.5F); + b = (int) (q * 255.0F + 0.5F); + break; + } + } + return 0xFF000000 | (r << 16) | (g << 8) | (b << 0); + } + + public static int parseHex(String hexColor) { + int len = hexColor.length(); + if (len < 6 || len > 8 || len % 2 > 0) { + return -1; + } + + int color, shift; + if(len == 6) { + color = 0xFF000000; shift = 16; + } else { + color = 0; shift = 24; + } + + try { + String[] splited = hexColor.split("(?<=\\G.{2})"); + for (String digit : splited) { + color |= Integer.valueOf(digit, 16) << shift; + shift -= 8; + } + } catch(NumberFormatException ex) { + BetterEnd.LOGGER.catching(ex); + return -1; + } + + return color; + } + + public static int toABGR(int color) { + int r = (color >> 16) & 255; + int g = (color >> 8) & 255; + int b = color & 255; + return 0xFF000000 | b << 16 | g << 8 | r; + } + + public static int ABGRtoARGB(int color) { + int a = (color >> 24) & 255; + int b = (color >> 16) & 255; + int g = (color >> 8) & 255; + int r = color & 255; + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colorBrigtness(int color, float val) { + RGBtoHSB((color >> 16) & 255, (color >> 8) & 255, color & 255, floatBuffer); + floatBuffer[2] += val / 10.0F; + floatBuffer[2] = MathHelper.clamp(floatBuffer[2], 0.0F, 1.0F); + return HSBtoRGB(floatBuffer[0], floatBuffer[1], floatBuffer[2]); + } + + public static int applyTint(int color, int tint) { + return colorBrigtness(ColorHelper.multiplyColor(color, tint), 1.5F); + } +} \ No newline at end of file diff --git a/src/main/resources/assets/betterend/models/item/eternal_crystal.json b/src/main/resources/assets/betterend/models/item/eternal_crystal.json deleted file mode 100644 index 1cd311d7..00000000 --- a/src/main/resources/assets/betterend/models/item/eternal_crystal.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "betterend:item/crystal_shards" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/betterend/textures/entity/eternal_crystal.png b/src/main/resources/assets/betterend/textures/entity/eternal_crystal.png index 9bb3824e..8c8a70aa 100644 Binary files a/src/main/resources/assets/betterend/textures/entity/eternal_crystal.png and b/src/main/resources/assets/betterend/textures/entity/eternal_crystal.png differ diff --git a/src/main/resources/assets/betterend/textures/item/eternal_crystal.png b/src/main/resources/assets/betterend/textures/item/eternal_crystal.png new file mode 100644 index 00000000..39a5ed95 Binary files /dev/null and b/src/main/resources/assets/betterend/textures/item/eternal_crystal.png differ