Skip to content

Commit

Permalink
Added two more mods: ClientChunkSize and InstantMessage
Browse files Browse the repository at this point in the history
  • Loading branch information
fr1kin committed Nov 19, 2018
1 parent 5d0e1ac commit 5e8f5e3
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/main/java/com/matt/forgehax/asm/reflection/FastReflection.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import net.minecraft.client.gui.GuiDisconnected;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiEditSign;
import net.minecraft.client.multiplayer.GuiConnecting;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.BufferBuilder;
Expand All @@ -33,6 +34,7 @@
import net.minecraft.item.ItemTool;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.network.play.client.CPacketCloseWindow;
import net.minecraft.network.play.client.CPacketEntityAction;
Expand All @@ -52,6 +54,8 @@
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.AnvilChunkLoader;

/** Created on 5/8/2017 by fr1kin */
public interface FastReflection extends ASMCommon {
Expand Down Expand Up @@ -197,6 +201,14 @@ interface Fields {
.autoAssign()
.asField();

/** GuiConnecting */
FastField<NetworkManager> GuiConnecting_networkManager =
FastTypeBuilder.create()
.setInsideClass(GuiConnecting.class)
.setName("networkManager")
.autoAssign()
.asField();

/** GuiDisconnected */
FastField<GuiScreen> GuiDisconnected_parentScreen =
FastTypeBuilder.create()
Expand Down Expand Up @@ -498,5 +510,15 @@ interface Methods {
.setReturnType(void.class)
.autoAssign()
.asMethod();

/** IChunkLoader */
FastMethod<AnvilChunkLoader> AnvilChunkLoader_writeChunkToNBT =
FastTypeBuilder.create()
.setInsideClass(AnvilChunkLoader.class)
.setName("writeChunkToNBT")
.setParameters(Chunk.class, World.class, NBTTagCompound.class)
.setReturnType(void.class)
.autoAssign()
.asMethod();
}
}
128 changes: 128 additions & 0 deletions src/main/java/com/matt/forgehax/mods/ClientChunkSize.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.matt.forgehax.mods;

import static com.matt.forgehax.Helper.getFileManager;
import static com.matt.forgehax.Helper.getLocalPlayer;
import static com.matt.forgehax.Helper.getWorld;

import com.matt.forgehax.asm.reflection.FastReflection;
import com.matt.forgehax.util.SimpleTimer;
import com.matt.forgehax.util.mod.Category;
import com.matt.forgehax.util.mod.ToggleMod;
import com.matt.forgehax.util.mod.loader.RegisterMod;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.concurrent.Executors;
import java.util.zip.DeflaterOutputStream;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;

@RegisterMod
public class ClientChunkSize extends ToggleMod {
private static final File DUMMY = new File(getFileManager().getBaseDirectory(), "dummy");

private final SimpleTimer timer = new SimpleTimer();

private boolean running = false;
private long size = 0L;
private long compressedSize = 0L;
private ChunkPos current = null;

public ClientChunkSize() {
super(Category.MISC, "ClientChunkSize", false, "Shows the client-side chunk size in bytes");
}

private static String asString(long size) {
if (size < 0) return "<error>";

NumberFormat format = NumberFormat.getInstance();
format.setGroupingUsed(true);
return format.format((double) size / 1000.D) + " KB";
}

@Override
protected void onEnabled() {
timer.reset();
running = false;
size = compressedSize = 0L;
current = null;
}

@Override
public String getDisplayText() {
return super.getDisplayText()
+ " "
+ String.format("[%s | compressed %s]", asString(size), asString(compressedSize));
}

@SubscribeEvent
public void onTick(ClientTickEvent event) {
if (getWorld() == null || getLocalPlayer() == null || running) return;

switch (event.phase) {
case END:
{
Chunk chunk = getWorld().getChunkFromBlockCoords(getLocalPlayer().getPosition());
if (chunk.isEmpty()) return;

ChunkPos pos = chunk.getPos();
if (!pos.equals(current) || (timer.isStarted() && timer.hasTimeElapsed(1000L))) {
current = pos;

// this probably needs to be done on the main thread since it loops over entities
final NBTTagCompound root = new NBTTagCompound();
NBTTagCompound level = new NBTTagCompound();
root.setTag("Level", level);
root.setInteger("DataVersion", 7777);

try {
AnvilChunkLoader loader = new AnvilChunkLoader(DUMMY, null);
FastReflection.Methods.AnvilChunkLoader_writeChunkToNBT.invoke(
loader, chunk, getWorld(), level);
} catch (Throwable t) {
size = compressedSize = -1L;
return; // couldn't save chunk
}

running = true;

// process size calculation on another thread
Executors.defaultThreadFactory()
.newThread(
() -> {
DataOutputStream uncompressed =
new DataOutputStream(
new BufferedOutputStream(new ByteArrayOutputStream(8096)));
DataOutputStream compressed =
new DataOutputStream(
new BufferedOutputStream(
new DeflaterOutputStream(new ByteArrayOutputStream(8096))));
try {
CompressedStreamTools.write(root, uncompressed);
CompressedStreamTools.write(root, compressed);
size = uncompressed.size();
compressedSize = compressed.size();
} catch (IOException e) {
size = -1L;
compressedSize = -1L;
}

timer.start();
})
.start();
}
break;
}
default:
break;
}
}
}
40 changes: 40 additions & 0 deletions src/main/java/com/matt/forgehax/mods/InstantMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.matt.forgehax.mods;

import static com.matt.forgehax.Helper.getLog;
import static com.matt.forgehax.asm.reflection.FastReflection.Fields.GuiConnecting_networkManager;

import com.matt.forgehax.asm.events.PacketEvent;
import com.matt.forgehax.util.command.Setting;
import com.matt.forgehax.util.mod.Category;
import com.matt.forgehax.util.mod.ToggleMod;
import com.matt.forgehax.util.mod.loader.RegisterMod;
import net.minecraft.client.multiplayer.GuiConnecting;
import net.minecraft.network.login.server.SPacketLoginSuccess;
import net.minecraft.network.play.client.CPacketChatMessage;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

@RegisterMod
public class InstantMessage extends ToggleMod {
private final Setting<String> message =
getCommandStub()
.builders()
.<String>newSettingBuilder()
.name("message")
.description("Message to send")
.defaultTo("test")
.build();

public InstantMessage() {
super(Category.MISC, "InstantMessage", false, "Send message as soon as you join");
}

@SubscribeEvent
public void onPacketIn(PacketEvent.Incoming.Pre event) {
if (event.getPacket() instanceof SPacketLoginSuccess) {
if (MC.currentScreen instanceof GuiConnecting) {
GuiConnecting_networkManager.get(MC.currentScreen)
.sendPacket(new CPacketChatMessage(message.get()));
} else getLog().warn("Did not send message as current screen is not GuiConnecting");
}
}
}

0 comments on commit 5e8f5e3

Please sign in to comment.