Мир: остров, дороги-дамбы, биомы; LOD ступенями; консоль сервера; баны; постобработка

This commit is contained in:
sasheg dev
2026-10-22 21:38:23 +03:00
parent d98cd83fe5
commit 07ed4ce02d
19 changed files with 2257 additions and 122 deletions
+38 -1
View File
@@ -1337,4 +1337,41 @@ import org.lwjgl.opengl.ContextCapabilities;
--- AFTER
this.mc.profiler.endStartSection("terrain_setup");
net.rustnotmc.client.RsxLod.render(this.mc);
renderglobal.setupTerrain(entity, (double) f, frustum, this.frameCount++, this.mc.player.isSpectator());
renderglobal.setupTerrain(entity, (double) f, frustum, this.frameCount++, this.mc.player.isSpectator());
# The post effects read the projection the world was drawn with.
=== FILE net/minecraft/client/renderer/EntityRenderer.java
--- BEFORE
if (this.mc.gameSettings.viewBobbing) {
this.applyBobbing(f);
}
}
}
public void disableLightmap() {
--- AFTER
if (this.mc.gameSettings.viewBobbing) {
this.applyBobbing(f);
}
net.rustnotmc.client.RsxPostPipeline.captureProjection();
}
}
public void disableLightmap() {
# The post effects run on what the world drew, before the hand and the
# interface come over it.
=== FILE net/minecraft/client/renderer/EntityRenderer.java
--- BEFORE
this.mc.profiler.endStartSection("hand");
if (this.renderHand) {
--- AFTER
this.mc.profiler.endStartSection("rsxpost");
if (i == 2 && !this.mc.gameSettings.anaglyph) {
net.rustnotmc.client.RsxPostPipeline.apply(this.mc);
}
this.mc.profiler.endStartSection("hand");
if (this.renderHand) {
@@ -127,6 +127,9 @@ public final class RsxBootstrap {
}
// our own commands come first: they are not mod commands, and a mod
// should not be able to take a name that the game itself uses
if (net.rustnotmc.client.RsxPostPipeline.command(line)) {
return true;
}
if (RsxHitboxDebug.command(line)) {
return true;
}
@@ -139,9 +139,14 @@ public final class RsxLod {
+ (mc.getRenderViewEntity().posZ - mc.getRenderViewEntity().lastTickPosZ)
* (double) mc.getRenderPartialTicks();
// the colour the far view fades into: the colour of the sky
float fogStart = (float) (mc.gameSettings.renderDistanceChunks * 16.0D * 0.75D);
float fogEnd = (float) (mc.gameSettings.renderDistanceChunks * 16.0D);
// the colour the far view fades into: the colour of the sky. The far
// view reaches further than the chunks do, so its fog sits at the
// edge of the far view and not at the edge of the chunks; the two
// kinds of ground fade into the same sky where they meet.
float chunkEdge = (float) (mc.gameSettings.renderDistanceChunks * 16.0D);
float farEdge = 1600.0F;
float fogStart = Math.max(chunkEdge * 0.8F, 128.0F);
float fogEnd = chunkEdge + farEdge;
float fogRed = 0.47F;
float fogGreen = 0.65F;
float fogBlue = 1.0F;
@@ -193,6 +198,12 @@ public final class RsxLod {
int vertices = cells * 6;
ByteBuffer data = ByteBuffer.allocateDirect(vertices * 16).order(ByteOrder.nativeOrder());
// the sun of the far view: the same direction from the north-west
// and above, so that the far ground is not flat colour
float sunX = -0.4629F;
float sunY = 0.8165F;
float sunZ = -0.3492F;
for (int z = 0; z < size - 1; z++) {
for (int x = 0; x < size - 1; x++) {
int at = z * size + x;
@@ -211,14 +222,27 @@ public final class RsxLod {
float g = (region.colors[c + 1] & 0xFF) / 255.0F;
float b = (region.colors[c + 2] & 0xFF) / 255.0F;
// the slope of the cell: the client works out its own light
// here, because the far view has no blocks for the game to
// light, only the shape of the ground it has already got
float dx = (h10 + h11 - h00 - h01) / (2.0F * step);
float dz = (h01 + h11 - h00 - h10) / (2.0F * step);
float length = (float) Math.sqrt(dx * dx + dz * dz + 1.0F);
float facing = (-dx * sunX + sunY - dz * sunZ) / length;
float light = Math.max(0.42F, (facing - 0.35F) * 0.95F + 0.72F);
float lr = Math.min(1.0F, r * light);
float lg = Math.min(1.0F, g * light);
float lb = Math.min(1.0F, b * light);
// two triangles: the first one along the diagonal, the second
// one the other way, so that the ground is never torn
vertex(data, x0, h00, z0, r, g, b);
vertex(data, x1, h10, z0, r, g, b);
vertex(data, x1, h11, z1, r, g, b);
vertex(data, x0, h00, z0, r, g, b);
vertex(data, x1, h11, z1, r, g, b);
vertex(data, x0, h01, z1, r, g, b);
vertex(data, x0, h00, z0, lr, lg, lb);
vertex(data, x1, h10, z0, lr, lg, lb);
vertex(data, x1, h11, z1, lr, lg, lb);
vertex(data, x0, h00, z0, lr, lg, lb);
vertex(data, x1, h11, z1, lr, lg, lb);
vertex(data, x0, h01, z1, lr, lg, lb);
}
}
data.flip();
File diff suppressed because it is too large Load Diff
@@ -24,9 +24,13 @@ public final class RsxBlockMap {
*
* A chunk has sixteen thousand blocks in it and a client may be given a
* hundred chunks at a time, so this is looked up sixty times a second per
* chunk instead of a million.
* chunk instead of a million. The room is (the highest legal id + 1) and
* a slot left null draws as air, so a block the client joined late on no
* longer sneaks past the end of the array as it did when the roads came
* off the wire as nothing at all.
*/
private static final IBlockState[] STATES = new IBlockState[8];
private static final IBlockState[] STATES =
new IBlockState[net.rustnotmc.protocol.Blocks.MAX + 1];
static {
STATES[net.rustnotmc.protocol.Blocks.AIR] = Blocks.AIR.getDefaultState();
@@ -37,6 +41,13 @@ public final class RsxBlockMap {
STATES[net.rustnotmc.protocol.Blocks.WATER] = Blocks.WATER.getDefaultState();
STATES[net.rustnotmc.protocol.Blocks.WOOD] = Blocks.LOG.getDefaultState();
STATES[net.rustnotmc.protocol.Blocks.LEAVES] = Blocks.LEAVES.getDefaultState();
// the game has no asphalt of its own; grey is the road's color
STATES[net.rustnotmc.protocol.Blocks.ASPHALT] =
Blocks.CONCRETE.getDefaultState().withProperty(
net.minecraft.block.BlockColored.COLOR,
net.minecraft.item.EnumDyeColor.GRAY);
STATES[net.rustnotmc.protocol.Blocks.SNOW] =
Blocks.SNOW.getDefaultState();
}
private RsxBlockMap() {
@@ -96,6 +96,20 @@ public final class RsxWorldBridge {
throws java.io.IOException {
boolean skyLight = world.provider.hasSkyLight();
int[] heights = new int[256];
for (int column = 0; column < 256; column++) {
int x = column & 15;
int z = column >> 4;
int top = 0;
for (int y = 255; y >= 0; y--) {
if (blocks[ChunkFormat.index(x, y, z)] != net.rustnotmc.protocol.Blocks.AIR) {
top = y;
break;
}
}
heights[column] = top;
}
PacketBuffer sections = new PacketBuffer(Unpooled.buffer(128 * 1024));
int mask = 0;
@@ -124,9 +138,9 @@ public final class RsxWorldBridge {
}
mask |= 1 << section;
container.write(sections);
sections.writeBytes(LIGHT);
sections.writeBytes(UNLIT);
if (skyLight) {
sections.writeBytes(LIGHT);
sections.writeBytes(skyLight(section * 16, heights));
}
}
@@ -150,14 +164,47 @@ public final class RsxWorldBridge {
return packet;
}
/** A section's light, all of it on. */
private static final byte[] LIGHT = new byte[2048];
/** The light of a block that is its own source. */
private static final byte[] UNLIT = new byte[2048];
/**
* The light of one section, worked out from the chunk's heightmap.
*
* The server does not compute light yet, and it also has no business
* doing so: a client that owns the blocks is the one that knows where the
* sky is. Columns above the surface read as full sky, and everything below
* the top of its column sinks two light steps for every block of ground
* it is buried in. Buildings get their shade, tunnels their darkness, and
* the gradient runs in one block increments so the vertex interpolation
* the game already does turns it into a smooth ramp instead of a ledge.
*/
private static byte[] skyLight(int baseY, int[] heights) {
byte[] data = new byte[2048];
for (int column = 0; column < 256; column++) {
int x = column & 15;
int z = column >> 4;
int top = heights[column];
for (int y = 0; y < 16; y++) {
int global = baseY + y;
int light = global > top ? 15 : 15 - 2 * (top - global);
if (light <= 0) {
continue;
}
int coordinate = (y << 8) | (z << 4) | x;
if ((coordinate & 1) == 0) {
data[coordinate >> 1] |= (byte) light;
} else {
data[coordinate >> 1] |= (byte) (light << 4);
}
}
}
return data;
}
/** The biomes of a chunk: one byte per column. */
private static final byte[] BIOMES = new byte[256];
static {
java.util.Arrays.fill(LIGHT, (byte) 0xFF);
java.util.Arrays.fill(BIOMES, (byte) 1); // plains
}