Skip to content

Commit

Permalink
Merge for 0.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Rainyaphthyl committed Aug 27, 2023
2 parents a6405eb + dba3b5b commit 2784eca
Show file tree
Hide file tree
Showing 56 changed files with 3,375 additions and 20 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

### Features and Functions

- [ChangeLog](ChangeLog.md)
1. Press `K + C` to open the config screen.
2. [ChangeLog](ChangeLog.md).

## Development

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ litemod {
displayName = modName
version = modVersion
mcversion = mcVersion
description = "Potato's Technical Kit"
description = "A development kit for Vanilla Technical Minecraft, also with some plain features and fixes."
author = project.author
mixinConfigs += "mixins.potteckit.json"
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ modId=potato_tech_kit
modName=Potato Tech Kit
# lowercase, without hyphens
modPureName=potteckit
modVersion=undefined
modVersion=0.0.0

malilibVersion=0.54.0

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.github.rainyaphthyl.potteckit.chunkphase.chunkgraph;

import net.minecraft.util.text.TextFormatting;

public enum ChunkEvent {
GENERATING("Generating", "is generated", TextFormatting.LIGHT_PURPLE, false),
LOADING("Loading", "is loaded", TextFormatting.AQUA, false),
CANCEL_UNLOAD("Cancel Unload", "cancels unloading", TextFormatting.DARK_GREEN, true),
QUEUE_UNLOAD("Queue Unload", "queues unloading", TextFormatting.GOLD, true),
UNLOADING("Unloading", "is unloaded", TextFormatting.RED, false);
public final String name;
public final String description;
public final TextFormatting color;
public final boolean silent;

ChunkEvent(String name, String description, TextFormatting color, boolean silent) {
this.name = name;
this.description = description;
this.color = color;
this.silent = silent;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package io.github.rainyaphthyl.potteckit.chunkphase.chunkgraph;

import io.github.rainyaphthyl.potteckit.chunkphase.phaseclock.PhaseRecord;
import io.github.rainyaphthyl.potteckit.chunkphase.phaseclock.TickRecord;
import io.github.rainyaphthyl.potteckit.util.NetworkGraph;
import io.netty.buffer.Unpooled;
import net.minecraft.network.play.server.SPacketCustomPayload;
import net.minecraft.server.management.PlayerList;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.DimensionType;

import javax.annotation.Nonnull;
import java.util.ConcurrentModificationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ChunkLoadCaptor {
public static final boolean debugDetail = true;
public static final String CHANNEL_EVENT = "PK|ChEvent";
private static final ConcurrentMap<Thread, ChunkLoadSource> threadReasonCache = new ConcurrentHashMap<>();
private final NetworkGraph<ChunkPos, ChunkLoadReason> graph = new NetworkGraph<>(ChunkPos.class, ChunkLoadReason.class);

public static void pushThreadSource(int chunkX, int chunkZ, ChunkLoadReason reason) {
ChunkLoadSource source = new ChunkLoadSource(chunkX, chunkZ, reason);
pushThreadSource(source);
}

public static void pushThreadSource(ChunkLoadSource source) {
Thread thread = Thread.currentThread();
ChunkLoadSource previous = threadReasonCache.putIfAbsent(thread, source);
if (previous != null) {
throw new ConcurrentModificationException("Chunk loader thread " + thread + " is interrupted!");
}
}

/**
* Fetch and <b>remove</b>
*/
public static ChunkLoadSource popThreadSource() {
Thread thread = Thread.currentThread();
return threadReasonCache.remove(thread);
}

public static void removeThreadSource() {
Thread thread = Thread.currentThread();
threadReasonCache.remove(thread);
}

public static void debugOnChat(int tickCount, PhaseRecord record, ChunkPos currPos, @Nonnull DimensionType dimensionType, @Nonnull ChunkEvent event, ChunkLoadSource source, PlayerList playerList) {
if (debugDetail) {
return;
}
ITextComponent component = new TextComponentString(
"[" + tickCount + ':' + record + ']'
).setStyle(new Style().setColor(TextFormatting.WHITE));
StringBuilder msgBuilder = new StringBuilder(" Chunk ");
msgBuilder.append(currPos).append(' ');
switch (event) {
case LOADING:
msgBuilder.append("is loaded");
break;
case CANCEL_UNLOAD:
msgBuilder.append("cancels unloading");
break;
case QUEUE_UNLOAD:
msgBuilder.append("queues for unloading");
break;
case UNLOADING:
msgBuilder.append("is unloaded");
break;
case GENERATING:
msgBuilder.append("is generated");
break;
default:
msgBuilder.append("has undefined behaviors");
}
ITextComponent body = new TextComponentString(msgBuilder.toString());
TextFormatting color;
switch (dimensionType) {
case OVERWORLD:
color = TextFormatting.GREEN;
break;
case NETHER:
color = TextFormatting.RED;
break;
case THE_END:
color = TextFormatting.LIGHT_PURPLE;
break;
default:
color = TextFormatting.GRAY;
}
body.setStyle(new Style().setColor(color));
if (source != null) {
ChunkPos priorPos = source.chunkPos;
ChunkLoadReason reason = source.reason;
ITextComponent tail = new TextComponentString(" from " + priorPos + " (" + reason + ')');
tail.setStyle(new Style().setColor(TextFormatting.GRAY));
body.appendSibling(tail);
}
component.appendSibling(body);
playerList.sendMessage(component);
}

public static void debugChunkTickStamp(TickRecord record, int chunkX, int chunkZ, DimensionType dimensionType, ChunkEvent event, @SuppressWarnings("unused") ChunkLoadSource source, @Nonnull PlayerList playerList) {
ChunkPacketBuffer buffer = new ChunkPacketBuffer(Unpooled.buffer());
SPacketCustomPayload packet = new SPacketCustomPayload(CHANNEL_EVENT, buffer);
buffer.writeTickRecord(record).writeSignedVarInt(chunkX).writeSignedVarInt(chunkZ);
buffer.writeEnumValue(dimensionType).writeEnumValue(event);
playerList.sendPacketToAllPlayers(packet);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.github.rainyaphthyl.potteckit.chunkphase.chunkgraph;

import io.github.rainyaphthyl.potteckit.chunkphase.phaseclock.TickRecord;
import io.github.rainyaphthyl.potteckit.config.Configs;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.SPacketChat;
import net.minecraft.network.play.server.SPacketCustomPayload;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.DimensionType;

import javax.annotation.Nonnull;

public class ChunkLoadGraph {
public static void receiveChunkEventPacket(@Nonnull SPacketCustomPayload packetIn) {
if (Configs.chunkLoadingGraphReceiver.getBooleanValue() && Configs.enablePotteckit.getBooleanValue()) {
PacketBuffer rawBuffer = packetIn.getBufferData();
ChunkPacketBuffer buffer = rawBuffer instanceof ChunkPacketBuffer ? (ChunkPacketBuffer) rawBuffer : new ChunkPacketBuffer(rawBuffer);
TickRecord tickRecord = buffer.readTickRecord();
int targetCX = buffer.readSignedVarInt();
int targetCZ = buffer.readSignedVarInt();
DimensionType targetDim = buffer.readEnumValue(DimensionType.class);
ChunkEvent event = buffer.readEnumValue(ChunkEvent.class);
Minecraft client = Minecraft.getMinecraft();
client.addScheduledTask(() -> {
StringBuilder builder = new StringBuilder();
builder.append(tickRecord).append(' ');
ITextComponent component = new TextComponentString(builder.toString());
component.setStyle(new Style().setColor(TextFormatting.GRAY));
builder.setLength(0);
builder.append(TickRecord.getDimensionChar(targetDim));
builder.append(":[").append(targetCX).append(", ").append(targetCZ).append("]");
ITextComponent appendix = new TextComponentString(builder.toString());
appendix.setStyle(new Style().setColor(TextFormatting.WHITE));
component.appendSibling(appendix);
builder.setLength(0);
builder.append(' ').append(event.description);
appendix = new TextComponentString(builder.toString());
appendix.setStyle(new Style().setColor(event.color));
component.appendSibling(appendix);
NetHandlerPlayClient connection = client.getConnection();
if (connection != null) {
connection.handleChat(new SPacketChat(component));
}
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.github.rainyaphthyl.potteckit.chunkphase.chunkgraph;

public enum ChunkLoadReason {
HOPPER_POINTING("Hopper Pointing Out");
private final String description;

ChunkLoadReason(String description) {
this.description = description;
}

@Override
public String toString() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.github.rainyaphthyl.potteckit.chunkphase.chunkgraph;

import net.minecraft.util.math.ChunkPos;

import java.util.Arrays;
import java.util.Objects;

public class ChunkLoadSource {
public final ChunkPos chunkPos;
public final ChunkLoadReason reason;
public final Object[] otherArgs;

public ChunkLoadSource(int chunkX, int chunkZ, ChunkLoadReason reason, Object... otherArgs) {
this(new ChunkPos(chunkX, chunkZ), reason, otherArgs);
}

public ChunkLoadSource(ChunkPos chunkPos, ChunkLoadReason reason, Object... otherArgs) {
this.chunkPos = chunkPos;
this.reason = reason;
this.otherArgs = otherArgs;
}

@Override
public String toString() {
return "{" + chunkPos + ':' + reason + ':' + Arrays.deepToString(otherArgs) + '}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ChunkLoadSource)) return false;
ChunkLoadSource source = (ChunkLoadSource) o;
if (!Objects.equals(chunkPos, source.chunkPos)) return false;
if (reason != source.reason) return false;
return Arrays.deepEquals(otherArgs, source.otherArgs);
}

@Override
public int hashCode() {
int result = chunkPos != null ? chunkPos.hashCode() : 0;
result = 31 * result + (reason != null ? reason.hashCode() : 0);
result = 31 * result + Arrays.deepHashCode(otherArgs);
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package io.github.rainyaphthyl.potteckit.chunkphase.chunkgraph;

import io.github.rainyaphthyl.potteckit.chunkphase.phaseclock.GamePhase;
import io.github.rainyaphthyl.potteckit.chunkphase.phaseclock.TickRecord;
import io.github.rainyaphthyl.potteckit.chunkphase.phaseclock.subphase.SubPhase;
import io.netty.buffer.ByteBuf;
import net.minecraft.network.PacketBuffer;
import net.minecraft.world.DimensionType;

public class ChunkPacketBuffer extends PacketBuffer {
public ChunkPacketBuffer(ByteBuf wrapped) {
super(wrapped);
}

public ChunkPacketBuffer writeTickRecord(TickRecord tickRecord) {
if (tickRecord == null) {
writeVarInt(-1);
} else {
writeVarInt(tickRecord.eventOrdinal);
writeVarInt(tickRecord.tickOrdinal);
writeVarLong(tickRecord.gameTime);
GamePhase gamePhase = tickRecord.gamePhase;
writeEnumValue(gamePhase);
if (gamePhase.dimensional) {
writeEnumValue(tickRecord.dimensionType);
}
writeSubPhase(tickRecord.subPhase);
}
return this;
}

public ChunkPacketBuffer writeSignedVarInt(int input) {
int sign = (input & 0x80000000) >>> 31;
long abs = Math.abs((long) input);
long value = (abs << 1) | sign;
writeVarLong(value);
return this;
}

public int readSignedVarInt() {
long value = readVarLong();
int sign = (int) (value & 0x1L);
long abs = value >>> 1;
int output;
if (sign == 0) {
output = (int) abs;
} else {
output = (int) (-abs);
}
return output;
}

public TickRecord readTickRecord() {
int eventOrdinal = readVarInt();
if (eventOrdinal == -1) {
return null;
}
int tickOrdinal = readVarInt();
long gameTime = readVarLong();
GamePhase gamePhase = readEnumValue(GamePhase.class);
DimensionType dimensionType = null;
if (gamePhase.dimensional) {
dimensionType = readEnumValue(DimensionType.class);
}
SubPhase subPhase = readSubPhase(gamePhase);
return TickRecord.getInstance(tickOrdinal, gameTime, dimensionType, gamePhase, subPhase, eventOrdinal);
}

@SuppressWarnings("UnusedReturnValue")
public ChunkPacketBuffer writeSubPhase(SubPhase subPhase) {
if (subPhase == null) {
writeBoolean(false);
} else {
writeBoolean(true);
subPhase.writeToPacket(this);
}
return this;
}

public SubPhase readSubPhase(GamePhase gamePhase) {
if (readBoolean()) {
SubPhase subPhase = SubPhase.createInstance(gamePhase);
if (subPhase != null) {
subPhase.readFromPacket(this);
}
return subPhase;
} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.github.rainyaphthyl.potteckit.chunkphase.chunkgraph;

public class ChunkRecord {
public enum Event {
LOADING,
QUEUE_UNLOAD,
CANCEL_UNLOAD,
UNLOADING,
}
}
Loading

0 comments on commit 2784eca

Please sign in to comment.