Initial model and graphics for Internet GateWay block

This commit is contained in:
Nikita Tomashevich
2022-04-08 21:07:04 +03:00
committed by logan
parent d37406244e
commit 1f55c8f174
9 changed files with 345 additions and 13 deletions

View File

@@ -38,6 +38,7 @@ public final class ClientSetup {
BlockEntityRenderers.register(BlockEntities.DISK_DRIVE.get(), DiskDriveRenderer::new);
BlockEntityRenderers.register(BlockEntities.CHARGER.get(), ChargerRenderer::new);
BlockEntityRenderers.register(BlockEntities.PROJECTOR.get(), ProjectorRenderer::new);
BlockEntityRenderers.register(BlockEntities.INTERNET_GATEWAY.get(), InternetGateWayRenderer::new);
event.enqueueWork(() -> {
CustomItemModelProperties.initialize();

View File

@@ -41,6 +41,20 @@ public abstract class ModRenderType extends RenderType {
.setCullState(NO_CULL)
.createCompositeState(false));
private static final RenderType GATEWAY_PARTICLE = create(
API.MOD_ID + "/gateway_particle",
DefaultVertexFormat.POSITION_COLOR,
VertexFormat.Mode.QUADS,
256,
false,
true,
CompositeState.builder()
.setShaderState(RENDERTYPE_LIGHTNING_SHADER)
.setTransparencyState(LIGHTNING_TRANSPARENCY)
.setWriteMaskState(COLOR_WRITE)
.setCullState(CULL)
.createCompositeState(false));
///////////////////////////////////////////////////////////////////
public static RenderType getNetworkCable() {
@@ -87,6 +101,10 @@ public abstract class ModRenderType extends RenderType {
state);
}
public static RenderType getGateWayParticle() {
return GATEWAY_PARTICLE;
}
///////////////////////////////////////////////////////////////////
private ModRenderType(final String name, final VertexFormat format, final VertexFormat.Mode drawMode, final int bufferSize, final boolean useDelegate, final boolean needsSorting, final Runnable setupTask, final Runnable clearTask) {

View File

@@ -0,0 +1,113 @@
package li.cil.oc2.client.renderer.blockentity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import li.cil.oc2.client.renderer.ModRenderType;
import li.cil.oc2.common.blockentity.InternetGateWayBlockEntity;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
public class InternetGateWayRenderer implements BlockEntityRenderer<InternetGateWayBlockEntity> {
private static final float BLOCK_HEIGHT = 14f/16f;
private static final float PORTAL_POSITION = 0.4f;
private static final float EMITTER_POSITION = -3f/16f;
private static final float EMITTER_SIZE = 6f/16f;
private static final float EMITTER_PIXEL_SIZE = EMITTER_SIZE / 9f;
private static final int[] SCRAMBLER = {1, 2, 0, 3, 13, 5, 15, 12, 6, 14, 10, 11, 7, 8, 9, 4};
public InternetGateWayRenderer(final BlockEntityRendererProvider.Context context) {
//this.renderer = context.getBlockEntityRenderDispatcher();
}
@Override
public void render(InternetGateWayBlockEntity gateWay, final float partialTicks, final PoseStack stack, final MultiBufferSource bufferSource, final int light, final int overlay) {
stack.pushPose();
stack.translate(0.5f, BLOCK_HEIGHT, 0.5f);
stack.pushPose();
long time = System.currentTimeMillis();
long dt = time - gateWay.lastRender;
gateWay.lastRender = time;
if (dt > 1000) {
//Catch up if rendering stopped
gateWay.handledInboundCount = gateWay.inboundCount;
gateWay.handledOutboundCount = gateWay.outboundCount;
}
double phase = ((double)time)/1000d;
stack.translate(0f, PORTAL_POSITION+Math.sin(phase/2)*0.03f, 0f);
//stack.mulPose(Vector3f.XN.rotationDegrees((float)Math.sin(phase)*5));
//stack.mulPose(Vector3f.ZN.rotationDegrees((float)Math.sin(phase+2)*5));
VertexConsumer portal = bufferSource.getBuffer(RenderType.endPortal());
Matrix4f matrix = stack.last().pose();
float halfSide = 0.2f;
renderCube(portal, matrix, halfSide, 0, 0, 0, false);
stack.popPose();
stack.translate(0, EMITTER_POSITION, 0);
matrix = stack.last().pose();
VertexConsumer packet = bufferSource.getBuffer(ModRenderType.getGateWayParticle());
for (int x=0;x<InternetGateWayBlockEntity.EMITTER_SIDE_PIXELS;x++) {
for (int z=0;z<InternetGateWayBlockEntity.EMITTER_SIDE_PIXELS;z++) {
int flatPos = x * InternetGateWayBlockEntity.EMITTER_SIDE_PIXELS + z;
if (gateWay.animProgress[flatPos] < 1f) {
float animPos = gateWay.animProgress[flatPos];
gateWay.animProgress[flatPos] += dt/1000f;
if (gateWay.animReversed[flatPos]) {
animPos = 1 - animPos;
}
renderCube(packet, matrix, EMITTER_PIXEL_SIZE/2, (x*2-3f)*EMITTER_PIXEL_SIZE, animPos*(PORTAL_POSITION-EMITTER_POSITION), (z*2-3f)*EMITTER_PIXEL_SIZE, true);
}
}
}
while (gateWay.handledInboundCount<gateWay.inboundCount || gateWay.handledOutboundCount<gateWay.outboundCount) {
int scrambledPointer = SCRAMBLER[gateWay.pointer];
if (gateWay.animProgress[scrambledPointer]>=1f) {
gateWay.pointer += 1;
if (gateWay.pointer>=InternetGateWayBlockEntity.EMITTER_SIDE_PIXELS*InternetGateWayBlockEntity.EMITTER_SIDE_PIXELS) {
gateWay.pointer = 0;
}
gateWay.animProgress[scrambledPointer] = 0f;
if (gateWay.handledInboundCount<gateWay.inboundCount) {
gateWay.animReversed[scrambledPointer] = false;
gateWay.handledInboundCount += 1;
} else {
gateWay.animReversed[scrambledPointer] = true;
gateWay.handledOutboundCount += 1;
}
} else {
break;
}
}
stack.popPose();
}
private void renderCube(VertexConsumer vertices, Matrix4f matrix, float halfSide, float x, float y, float z, boolean enColor) {
//X axis
renderCubeFace(vertices, matrix, +halfSide+x, 0+y, 0+z, halfSide, 5, 1, 0, enColor);
renderCubeFace(vertices, matrix, -halfSide+x, 0+y, 0+z, halfSide, 5, 0, 1, enColor);
//Y axis
renderCubeFace(vertices, matrix, 0+x, +halfSide+y, 0+z, halfSide, 0, 5, 1, enColor);
renderCubeFace(vertices, matrix, 0+x, -halfSide+y, 0+z, halfSide, 1, 5, 0, enColor);
//Z axis
renderCubeFace(vertices, matrix, 0+x, 0+y, -halfSide+z, halfSide, 0, 1, 5, enColor);
renderCubeFace(vertices, matrix, 0+x, 0+y, +halfSide+z, halfSide, 1, 0, 5, enColor);
}
private void renderCubeFace(VertexConsumer vertices, Matrix4f matrix, float x, float y, float z, float halfSideSize, int signShiftX, int signShiftY, int signShiftZ, boolean enColor) {
float signs[] = {-1f, -1f, 1f, 1f, -1f, 0f, 0f, 0f, 0f};
for (int i=0;i<4;i++) {
vertices.vertex(matrix, x+halfSideSize*signs[i+signShiftX], y+halfSideSize*signs[i+signShiftY], z+halfSideSize*signs[i+signShiftZ]);
if (enColor) {
vertices.color(1f, 1f, 1f, 1f);
}
vertices.endVertex();
}
}
}

View File

@@ -2,14 +2,17 @@ package li.cil.oc2.common.block;
import li.cil.oc2.common.blockentity.BlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.HalfTransparentBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class InternetGatewayBlock extends Block implements EntityBlock {
public class InternetGatewayBlock extends HalfTransparentBlock implements EntityBlock {
public InternetGatewayBlock() {
super(Properties.of(Material.METAL).sound(SoundType.METAL).strength(1.5f, 6.0f));

View File

@@ -1,10 +1,7 @@
package li.cil.oc2.common.blockentity;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nullable;
@@ -16,11 +13,19 @@ import li.cil.oc2.common.energy.FixedEnergyStorage;
import li.cil.oc2.common.inet.InternetAdapter;
import li.cil.oc2.common.inet.InternetConnection;
import li.cil.oc2.common.inet.InternetManagerImpl;
import li.cil.oc2.common.util.ChunkUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.Connection;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -32,16 +37,29 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
private final Deque<byte[]> outboundQueue;
private InternetConnection internetConnection;
private static final String STATE_TAG = "internet_adapter";
private Tag internetState;
private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.gatewayEnergyStorage);
// Animation stuff
public static final int EMITTER_SIDE_PIXELS = 4;
public float animProgress[];
public boolean animReversed[];
public int inboundCount = 0;
public int outboundCount = 0;
public int handledInboundCount = 0;
public int handledOutboundCount = 0;
public long lastRender = 0;
public int pointer = 0;
protected InternetGateWayBlockEntity(final BlockPos pos, final BlockState state) {
super(BlockEntities.INTERNET_GATEWAY.get(), pos, state);
inboundQueue = new ArrayDeque<>();
outboundQueue = new ArrayDeque<>();
internetState = null;
animProgress = new float[EMITTER_SIDE_PIXELS*EMITTER_SIDE_PIXELS];
animReversed = new boolean[EMITTER_SIDE_PIXELS*EMITTER_SIDE_PIXELS];
internetState = EndTag.INSTANCE;
setNeedsLevelUnloadEvent();
}
@@ -60,7 +78,37 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
.ifPresent(adapterState -> tag.put(Constants.INTERNET_ADAPTER_TAG_NAME, adapterState));
}
tag.put(Constants.ENERGY_TAG_NAME, energy.serializeNBT());
LOGGER.info("State saved");
LOGGER.trace("State saved");
}
@Override
public CompoundTag getUpdateTag() {
final CompoundTag tag = super.getUpdateTag();
tag.putInt("inbound_count", inboundCount);
tag.putInt("outbound_count", outboundCount);
return tag;
}
@Override
public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt)
{
CompoundTag compoundtag = pkt.getTag();
if (compoundtag != null) {
handleUpdateTag(compoundtag);
}
}
@Override
public void handleUpdateTag(final CompoundTag tag) {
inboundCount = tag.getInt("inbound_count");
outboundCount = tag.getInt("outbound_count");
handledInboundCount = Math.max(handledInboundCount, inboundCount-128);
handledOutboundCount = Math.max(handledOutboundCount, outboundCount-128);
}
@Override
public Packet<ClientGamePacketListener> getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
}
@Override
@@ -68,16 +116,16 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
InternetManagerImpl.getInstance()
.ifPresent(internetManager -> internetConnection = internetManager.connect(this, internetState));
if (internetConnection != null) {
LOGGER.info("Connected to the internet");
LOGGER.trace("Connected to the internet");
} else {
LOGGER.info("Not connected to the internet");
LOGGER.trace("Not connected to the internet");
}
}
protected void unloadServer(final boolean isRemove) {
if (internetConnection != null) {
internetConnection.stop();
LOGGER.info("Connection stopped");
LOGGER.trace("Connection stopped");
}
}
@@ -96,15 +144,30 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
boolean hasEnough = energy.getEnergyStored() >= Config.gatewayEnergyPerPacket;
if (hasEnough) {
energy.extractEnergy(Config.gatewayEnergyPerPacket, false);
Level level = getLevel();
if (level != null) {
ChunkUtils.setLazyUnsaved(level, getBlockPos());
}
}
return hasEnough;
}
private void notifyPlayers() {
Level level = getLevel();
if (level != null) {
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 2);
//setChanged();
LOGGER.info("Notified clients");
}
}
@Override
public void sendEthernetFrame(byte[] frame) {
LOGGER.info("Got inbound packet");
LOGGER.trace("Got inbound packet");
if (inboundQueue.size() < QUEUE_MAX) {
if (tryUseEnergy()) {
inboundCount += 1;
notifyPlayers();
inboundQueue.addLast(frame);
}
}
@@ -117,12 +180,22 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
@Override
public void writeEthernetFrame(NetworkInterface source, byte[] frame, int timeToLive) {
LOGGER.info("Got outbound packet");
LOGGER.trace("Got outbound packet");
if (outboundQueue.size() < QUEUE_MAX) {
if (tryUseEnergy()) {
outboundCount += 1;
notifyPlayers();
outboundQueue.addLast(frame);
}
}
}
@Override
public AABB getRenderBoundingBox() {
return new AABB(
getBlockPos(),
getBlockPos().offset(1, 2, 1)
);
}
}

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "oc2:block/internet_gateway"
}
}
}

View File

@@ -0,0 +1,114 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"texture_size": [32, 32],
"textures": {
"0": "oc2:block/internet_gateway/internet_gateway_atlas0",
"particle": "oc2:block/internet_gateway/internet_gateway_atlas0"
},
"elements": [
{
"from": [3, 0, 3],
"to": [13, 10, 13],
"faces": {
"north": {"uv": [0, 0, 5, 5], "texture": "#0"},
"east": {"uv": [0, 0, 5, 5], "texture": "#0"},
"south": {"uv": [0, 0, 5, 5], "texture": "#0"},
"west": {"uv": [1.5, 1.5, 6.5, 6.5], "texture": "#0"},
"up": {"uv": [1.5, 1.5, 6.5, 6.5], "texture": "#0"},
"down": {"uv": [1.5, 1.5, 6.5, 6.5], "texture": "#0"}
}
},
{
"from": [0, 0, 0],
"to": [16, 13, 3],
"faces": {
"north": {"uv": [8, 0, 16, 6.5], "texture": "#0"},
"east": {"uv": [14.5, 0, 16, 6.5], "texture": "#0"},
"south": {"uv": [0, 0, 8, 6.5], "texture": "#0"},
"west": {"uv": [8, 0, 9.5, 6.5], "texture": "#0"},
"up": {"uv": [0, 8, 8, 9.5], "texture": "#0"},
"down": {"uv": [0, 6.5, 8, 8], "texture": "#0"}
}
},
{
"from": [0, 0, 13],
"to": [16, 13, 16],
"faces": {
"north": {"uv": [0, 0, 8, 6.5], "texture": "#0"},
"east": {"uv": [8, 0, 9.5, 6.5], "texture": "#0"},
"south": {"uv": [8, 0, 16, 6.5], "texture": "#0"},
"west": {"uv": [14.5, 0, 16, 6.5], "texture": "#0"},
"up": {"uv": [0, 14.5, 8, 16], "texture": "#0"},
"down": {"uv": [0, 0, 8, 1.5], "texture": "#0"}
}
},
{
"from": [0, 0, 3],
"to": [3, 13, 13],
"faces": {
"north": {"uv": [0, 0, 1.5, 6.5], "texture": "#0"},
"east": {"uv": [1.5, 0, 6.5, 6.5], "texture": "#0"},
"south": {"uv": [0, 0, 1.5, 6.5], "texture": "#0"},
"west": {"uv": [9.5, 0, 14.5, 6.5], "texture": "#0"},
"up": {"uv": [0, 9.5, 1.5, 14.5], "texture": "#0"},
"down": {"uv": [0, 1.5, 1.5, 6.5], "texture": "#0"}
}
},
{
"from": [13, 0, 3],
"to": [16, 13, 13],
"faces": {
"north": {"uv": [0, 0, 1.5, 6.5], "texture": "#0"},
"east": {"uv": [9.5, 0, 14.5, 6.5], "texture": "#0"},
"south": {"uv": [0, 0, 1.5, 6.5], "texture": "#0"},
"west": {"uv": [1.5, 0, 6.5, 6.5], "texture": "#0"},
"up": {"uv": [6.5, 9.5, 8, 14.5], "texture": "#0"},
"down": {"uv": [6.5, 1.5, 8, 6.5], "texture": "#0"}
}
},
{
"from": [5, 10, 5],
"to": [11, 11, 11],
"faces": {
"north": {"uv": [3, 0, 6, 0.5], "texture": "#0"},
"east": {"uv": [3, 0.5, 6, 1], "texture": "#0"},
"south": {"uv": [3, 1, 6, 1.5], "texture": "#0"},
"west": {"uv": [3, 1.5, 6, 2], "texture": "#0"},
"up": {"uv": [16, 11, 11.5, 6.5], "texture": "#0"},
"down": {"uv": [3, 3, 0, 6], "texture": "#0"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "oc2:block/internet_gateway"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B