-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
56 changed files
with
3,375 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
src/main/java/io/github/rainyaphthyl/potteckit/chunkphase/chunkgraph/ChunkEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
115 changes: 115 additions & 0 deletions
115
src/main/java/io/github/rainyaphthyl/potteckit/chunkphase/chunkgraph/ChunkLoadCaptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
src/main/java/io/github/rainyaphthyl/potteckit/chunkphase/chunkgraph/ChunkLoadGraph.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
}); | ||
} | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/io/github/rainyaphthyl/potteckit/chunkphase/chunkgraph/ChunkLoadReason.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/io/github/rainyaphthyl/potteckit/chunkphase/chunkgraph/ChunkLoadSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
src/main/java/io/github/rainyaphthyl/potteckit/chunkphase/chunkgraph/ChunkPacketBuffer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/io/github/rainyaphthyl/potteckit/chunkphase/chunkgraph/ChunkRecord.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} | ||
} |
Oops, something went wrong.