Eternal Crystal item & model
This commit is contained in:
parent
7192df49d1
commit
3b31532fea
10 changed files with 225 additions and 19 deletions
|
@ -8,6 +8,7 @@ public class BlockProperties {
|
||||||
public static final EnumProperty<TripleShape> TRIPLE_SHAPE = EnumProperty.of("shape", TripleShape.class);
|
public static final EnumProperty<TripleShape> TRIPLE_SHAPE = EnumProperty.of("shape", TripleShape.class);
|
||||||
public final static EnumProperty<PedestalState> PEDESTAL_STATE = EnumProperty.of("state", PedestalState.class);
|
public final static EnumProperty<PedestalState> PEDESTAL_STATE = EnumProperty.of("state", PedestalState.class);
|
||||||
public static final BooleanProperty HAS_ITEM = BooleanProperty.of("has_item");
|
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 final BooleanProperty ACTIVATED = BooleanProperty.of("active");
|
||||||
|
|
||||||
public static enum TripleShape implements StringIdentifiable {
|
public static enum TripleShape implements StringIdentifiable {
|
||||||
|
|
|
@ -46,6 +46,7 @@ import ru.betterend.util.BlocksHelper;
|
||||||
public class BlockPedestal extends BlockBaseNotFull implements BlockEntityProvider {
|
public class BlockPedestal extends BlockBaseNotFull implements BlockEntityProvider {
|
||||||
public final static EnumProperty<PedestalState> STATE = BlockProperties.PEDESTAL_STATE;
|
public final static EnumProperty<PedestalState> STATE = BlockProperties.PEDESTAL_STATE;
|
||||||
public static final BooleanProperty HAS_ITEM = BlockProperties.HAS_ITEM;
|
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_DEFAULT;
|
||||||
private static final VoxelShape SHAPE_COLUMN;
|
private static final VoxelShape SHAPE_COLUMN;
|
||||||
|
@ -82,8 +83,10 @@ public class BlockPedestal extends BlockBaseNotFull implements BlockEntityProvid
|
||||||
protected float height = 1.0F;
|
protected float height = 1.0F;
|
||||||
|
|
||||||
public BlockPedestal(Block parent) {
|
public BlockPedestal(Block parent) {
|
||||||
super(FabricBlockSettings.copyOf(parent));
|
super(FabricBlockSettings.copyOf(parent).luminance(state -> {
|
||||||
this.setDefaultState(stateManager.getDefaultState().with(STATE, PedestalState.DEFAULT).with(HAS_ITEM, false));
|
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;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +297,7 @@ public class BlockPedestal extends BlockBaseNotFull implements BlockEntityProvid
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
||||||
stateManager.add(STATE, HAS_ITEM);
|
stateManager.add(STATE, HAS_ITEM, HAS_LIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -12,6 +12,7 @@ import net.minecraft.util.Tickable;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import ru.betterend.blocks.basis.BlockPedestal;
|
import ru.betterend.blocks.basis.BlockPedestal;
|
||||||
import ru.betterend.registry.EndBlockEntities;
|
import ru.betterend.registry.EndBlockEntities;
|
||||||
|
import ru.betterend.registry.EndItems;
|
||||||
|
|
||||||
public class PedestalBlockEntity extends BlockEntity implements Inventory, Tickable {
|
public class PedestalBlockEntity extends BlockEntity implements Inventory, Tickable {
|
||||||
private ItemStack activeItem = ItemStack.EMPTY;
|
private ItemStack activeItem = ItemStack.EMPTY;
|
||||||
|
@ -70,7 +71,8 @@ public class PedestalBlockEntity extends BlockEntity implements Inventory, Ticka
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeStack(World world, BlockState state) {
|
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);
|
this.removeStack(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +84,11 @@ public class PedestalBlockEntity extends BlockEntity implements Inventory, Ticka
|
||||||
|
|
||||||
public void setStack(World world, BlockState state, ItemStack stack) {
|
public void setStack(World world, BlockState state, ItemStack stack) {
|
||||||
world.setBlockState(pos, state.with(BlockPedestal.HAS_ITEM, true));
|
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);
|
this.setStack(0, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.DyeColor;
|
import net.minecraft.util.DyeColor;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
import ru.betterend.blocks.EternalPedestal;
|
import ru.betterend.blocks.EternalPedestal;
|
||||||
import ru.betterend.blocks.basis.BlockPedestal;
|
import ru.betterend.blocks.basis.BlockPedestal;
|
||||||
import ru.betterend.blocks.entities.PedestalBlockEntity;
|
import ru.betterend.blocks.entities.PedestalBlockEntity;
|
||||||
|
|
|
@ -9,31 +9,56 @@ import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.client.util.math.Vector3f;
|
import net.minecraft.client.util.math.Vector3f;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
|
||||||
import ru.betterend.BetterEnd;
|
import ru.betterend.BetterEnd;
|
||||||
|
import ru.betterend.blocks.AuroraCrystalBlock;
|
||||||
|
import ru.betterend.util.ColorUtil;
|
||||||
|
import ru.betterend.util.MHelper;
|
||||||
|
|
||||||
public class EternalCrystalRenderer {
|
public class EternalCrystalRenderer {
|
||||||
private static final Identifier CRYSTAL_TEXTURE = BetterEnd.makeID("textures/entity/eternal_crystal.png");
|
private static final Identifier CRYSTAL_TEXTURE = BetterEnd.makeID("textures/entity/eternal_crystal.png");
|
||||||
private static final RenderLayer RENDER_LAYER;
|
private static final RenderLayer RENDER_LAYER;
|
||||||
|
private static final ModelPart SHARDS;
|
||||||
private static final ModelPart CORE;
|
private static final ModelPart CORE;
|
||||||
|
|
||||||
public static void render(int age, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumerProvider, int light) {
|
public static void render(int age, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumerProvider, int light) {
|
||||||
VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RENDER_LAYER);
|
VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RENDER_LAYER);
|
||||||
|
float[] colors = colors(age);
|
||||||
float rotation = (age + tickDelta) / 25.0F + 6.0F;
|
float rotation = (age + tickDelta) / 25.0F + 6.0F;
|
||||||
float altitude = MathHelper.sin((age + tickDelta) / 10.0F) * 0.1F + 0.1F;
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.scale(0.6F, 0.6F, 0.6F);
|
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.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion(rotation));
|
||||||
matrices.push();
|
CORE.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, colors[0], colors[1], colors[2], colors[3]);
|
||||||
matrices.translate(-0.125D, -0.1D, -0.125D);
|
SHARDS.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, colors[0], colors[1], colors[2], colors[3]);
|
||||||
CORE.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
|
|
||||||
matrices.pop();
|
|
||||||
matrices.pop();
|
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 {
|
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 = 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
package ru.betterend.item;
|
package ru.betterend.item;
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
import ru.betterend.patterns.Patterned;
|
||||||
|
import ru.betterend.patterns.Patterns;
|
||||||
import ru.betterend.registry.EndItems;
|
import ru.betterend.registry.EndItems;
|
||||||
|
|
||||||
public class EternalCrystal extends Item {
|
public class EternalCrystal extends Item implements Patterned {
|
||||||
|
|
||||||
public EternalCrystal() {
|
public EternalCrystal() {
|
||||||
super(EndItems.makeSettings());
|
super(EndItems.makeSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModelPattern(String name) {
|
||||||
|
return Patterns.createJson(Patterns.ITEM_GENERATED, name);
|
||||||
|
}
|
||||||
}
|
}
|
168
src/main/java/ru/betterend/util/ColorUtil.java
Normal file
168
src/main/java/ru/betterend/util/ColorUtil.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent": "item/generated",
|
|
||||||
"textures": {
|
|
||||||
"layer0": "betterend:item/crystal_shards"
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 415 B |
Binary file not shown.
After Width: | Height: | Size: 528 B |
Loading…
Add table
Add a link
Reference in a new issue