Well, I just installed Linux (Debian, if anyone's interested) and I can confirm that kill -STOP and kill -CONT do pause and resume the server properly.
I will now get started writing the proxy server. I'll put up a download/guide here when I'm finished, for anyone with a similar problem and stumbles across this in the future.
I'm currently hosting an FTB server on my laptop (yeah, yeah, not vanilla, but the principles apply to all Minecraft servers). The problem is, it's quite noisy, even when no-one's online.
The solution I am currently in the process of planning and implementing is this:
Run the server inside QEMU.
Run a proxy server on my actual computer, which users will connect to.
The proxy server will suspend (using QMP) the execution of QEMU when no-one has logged into the server for the last 5 minutes.
When someone connects, the proxy server will unsuspend QEMU and redirect all future packets to it.
While I'm fairly sure this would work (though I would appreciate it if someone saw and pointed out any flaws in it), are there any other, less drastic ways to reduce the CPU load of my server (especially when no-one is online).
Thanks in advance.
EDIT:
I'm running Windows, but am planning to switch to Linux soon.
The server takes quite a while to start up, so stopping/restarting the server should be avoided.
EDIT2:
When I install Linux, could I use kill -STOP and kill -CONT to achieve the same thing without QEMU? I don't have Linux installed so I can't test right now.
William Shakespeare (the English poet and playwright, who brought us such works as Romeo and Juliet and Macbeth) versus J. K. Rowling (the British novelist and philanthropist, who wrote the Harry Potter series)
Who, do you think, is more deserving of their fame? Not necessarily a better writer, but more deserving of the recognition they have received.
[insert 5 letter food substance which may or may not begin with 'b']
*brace for princess-ification followed by lengthy debate on what 'may or may not' means*
I so want to actually download this. Just for fun.
On an unrelated note: [insert 5 letter food substance which may or may not begin with 'b']
*brace for princess-ification followed by lengthy debate on what 'may or may not' means*
I'm writing a simple tile entity that stores a char[0x10000] array. Each 16-bit char is represented as two 8-bit bytes within the NBT format.
However, when saving the world, the console reports that it has written 65536 words of null (0) data. Always. Even when there is data in the array. NBTExplorer confirms this.
My code (messy version):
public class ComputerTileEntity extends TileEntity {
public static final int MEMORY_SIZE = 0x10000;
public char[] memory = new char[MEMORY_SIZE];
public int PC = 0, SP = 0, EX = 0, IA = 0;
public int A = 0, B = 0, C = 0, X = 0, Y = 0, Z = 0, I = 0, J = 0;
public String status = "LOC: " + String.format("%04X", PC);
public String input = "";
public void resetStatus() {
status = "LOC: " + String.format("%04X", PC);
}
public void commandLOC(String[] args) {
if (args.length > 1) {
try {
int newLoc = Integer.parseInt(args[1], 16);
if (newLoc > MEMORY_SIZE || newLoc < 0)
status = "? Address";
else {
PC = newLoc;
resetStatus();
input = "";
}
} catch (NumberFormatException e) {
status = "? Address";
}
} else {
resetStatus();
input = "";
}
}
public void commandMEM(String[] args) {
char[] newData = new char[args.length - 1];
try {
for (int i = 1; i < args.length; i++) {
int parsed = Integer.parseInt(args[i], 16);
if (parsed < 0 || parsed > 65535)
throw new NumberFormatException("Too big for char");
newData[i - 1] = (char) parsed;
}
for (int i = 0; i < newData.length; i++) {
memory[PC] = newData[i];
PC++;
}
resetStatus();
input = "";
} catch (NumberFormatException e) {
status = "? Value";
}
}
public void commandDMP(String[] args) {
status = "";
for (int i = 0; i < 6; i++) {
status += String.format("%04X", (int) memory[PC + i]);
if (i != 5)
status += " ";
}
input = "";
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
byte[] mem8 = new byte[MEMORY_SIZE * 2];
int bytes = 0;
for (int i = 0; i < MEMORY_SIZE; i++) {
byte lS = (byte) (memory[i] & 0xFF);
byte mS = (byte) (memory[i] >> 8 & 0xFF);
mem8[2 * i] = lS;
mem8[2 * i + 1] = mS;
if (memory[i] == 0)
bytes += 1;
}
nbt.setByteArray("memory", mem8);
System.out.println("Wrote " + bytes + "w null data");
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
byte[] mem8 = nbt.getByteArray("memory");
int bytes = 0;
for (int i = 0; i < MEMORY_SIZE; i++) {
int lSi = mem8[2 * i] & 0xFF;
int mSi = mem8[2 * i + 1] & 0xFF;
char m = (char) (mSi << 8 | lSi);
memory[i] = m;
if (memory[i] == 0)
bytes += 1;
}
System.out.println("Read " + bytes + "w null data");
}
@Override
public String toString() {
return "ComputerTileEntity instance";
}
}
My code (SSCCE version):
public class ComputerTileEntity extends TileEntity {
public static final int MEMORY_SIZE = 0x10000;
public char[] memory = new char[MEMORY_SIZE];
public int PC = 0, SP = 0, EX = 0, IA = 0;
public int A = 0, B = 0, C = 0, X = 0, Y = 0, Z = 0, I = 0, J = 0;
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
byte[] mem8 = new byte[MEMORY_SIZE * 2];
int bytes = 0;
for (int i = 0; i < MEMORY_SIZE; i++) {
byte lS = (byte) (memory[i] & 0xFF);
byte mS = (byte) (memory[i] >> 8 & 0xFF);
mem8[2 * i] = lS;
mem8[2 * i + 1] = mS;
if (memory[i] == 0)
bytes += 1;
}
nbt.setByteArray("memory", mem8);
System.out.println("Wrote " + bytes + "w null data");
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
byte[] mem8 = nbt.getByteArray("memory");
int bytes = 0;
for (int i = 0; i < MEMORY_SIZE; i++) {
int lSi = mem8[2 * i] & 0xFF;
int mSi = mem8[2 * i + 1] & 0xFF;
char m = (char) (mSi << 8 | lSi);
memory[i] = m;
if (memory[i] == 0)
bytes += 1;
}
System.out.println("Read " + bytes + "w null data");
}
}
Can someone please tell me what's going on here? It's like there's two instances of my tile entity or something?!
QuickStats:
Server status: = Ready
Server HP: ========== (200,000/200,000)
Server TPS: ========== (1 Tick per 20 Milliseconds/20 TPS)
Server Website: Online
Events:
Hacker:
- None
General:
-None
Server:
- None
Server portions destroyed: 0% Server portions burning: 0% Server portions above 100 degrees Celsius: 0% Server portions operational: 100% Server portions operating at 100%: 100% Server portions operating above 50%: 100% Server modems remaining: 20/20 Server network connection: 2,000 Gigabits Server memory remaining: 200/200 TB Server memory operational: 200 TB SSD's destroyed: 100% SSD's operational: 100% SSD IO Remaining: 50/50 Gigabits IO. File Server efficiency: 100% Percentage of map corrupted/lost: 0% Power remaining: 20 kW/ 20 kW
Firstly, thanks for replying.
I understand how tile entities work. I've looked at the command block code, but I don't know what I'm doing wrong:
(Relevant parts of) my code:
MCPU.java
@Mod(modid = "MCPU", name = "MCPU", version = "0.1b1")
@NetworkMod(clientSideRequired = true, serverSideRequired = false)
public class MCPU {
public final static Block computerBlock = new ComputerBlock(500)
.setHardness(1.5F).setStepSound(Block.soundStoneFootstep)
.setUnlocalizedName("computerBlock")
.setCreativeTab(CreativeTabs.tabRedstone);
@Instance("MCPU")
public static MCPU instance;
@SidedProxy(clientSide = "org.runas.mcpu.ClientProxy", serverSide = "org.runas.mcpu.CommonProxy")
public static CommonProxy proxy;
@Init
public void load(FMLInitializationEvent event) {
GameRegistry.registerBlock(computerBlock, "computerBlock");
GameRegistry.registerTileEntity(ComputerTileEntity.class,
"computerBlock");
LanguageRegistry.addName(computerBlock, "Computer");
MinecraftForge.setBlockHarvestLevel(computerBlock, "pickaxe", 0);
NetworkRegistry.instance().registerGuiHandler(this,
new ComputerGUIHandler());
proxy.registerRenderers();
}
}
ComputerBlock.java
public class ComputerBlock extends BlockContainer {
@Override
public boolean onBlockActivated(World world, int xPos, int zPos, int yPos,
EntityPlayer player, int par6, float par7, float par8, float par9) {
if (!world.isRemote) {
player.addChatMessage("onBlockActivated: "
+ world.getBlockTileEntity(xPos, yPos, zPos));
}
return true;
}
@Override
public TileEntity createNewTileEntity(World world) {
return new ComputerTileEntity();
}
//Is this one even necessary???
@Override
public boolean hasTileEntity(int metadata) {
return true;
}
}
ComputerTileEntity.java
public class ComputerTileEntity extends TileEntity {
@Override
public String toString() {
return "ComputerTileEntity instance";
}
}
When I place a computer block and right click it, it shows
onBlockActivated: null
instead of
onBlockActivated: ComputerTileEntity instance
EDIT: I'll be darned if this is the problem, does the argument to registerTileEntity have to match the block name? I'll try it now. EDIT2: I tried that, still not working.I've updated my code to reflect the changes.
I've tried making my block implement ITileEntityProvider, and then override createNewTileEntity to return a new instance of ComputerTileEntity, but it doesn't work! getBlockTileEntity just returns null!
I see you've done your research, but there should be something in the Furnace block source code relating to this (I believe Furnaces use metadata for direction).
0
Minecraft ‘Gold’ Plan
0
I would guess it's because of this. Scroll up and down a bit for the full story.
As you can see, he's even changed his Minecraft Forums username.
0
I will now get started writing the proxy server. I'll put up a download/guide here when I'm finished, for anyone with a similar problem and stumbles across this in the future.
0
The solution I am currently in the process of planning and implementing is this:
Thanks in advance.
EDIT:
When I install Linux, could I use kill -STOP and kill -CONT to achieve the same thing without QEMU? I don't have Linux installed so I can't test right now.
0
Who, do you think, is more deserving of their fame? Not necessarily a better writer, but more deserving of the recognition they have received.
0
1
*brace for princess-ification followed by lengthy debate on what 'may or may not' means*
0
On an unrelated note: [insert 5 letter food substance which may or may not begin with 'b']
*brace for princess-ification followed by lengthy debate on what 'may or may not' means*
0
Derp! Of course! How did I not think of that? Things were so much simpler back in Beta...
(Now... where's that packet handling documentation.............)
0
I'm writing a simple tile entity that stores a char[0x10000] array. Each 16-bit char is represented as two 8-bit bytes within the NBT format.
However, when saving the world, the console reports that it has written 65536 words of null (0) data. Always. Even when there is data in the array. NBTExplorer confirms this.
My code (messy version):
My code (SSCCE version):
Can someone please tell me what's going on here? It's like there's two instances of my tile entity or something?!
0
Say, it's almost as if nothing's happened yet!
0
Hmm... Odd. The tile entity seems to have been created.
Makes the console spam 'Hello!' like crazy, but it getBlockTileEntity still returns null.
Maybe my parameters are in the wrong order or something?
EDIT:
Thought so!
Thanks! I'll try it now!
EDIT2:
Awesome, it works! I think that x,z,y thing was a leftover from copying an outdated tutorial.
Thanks for your help!
0
Firstly, thanks for replying.
I understand how tile entities work. I've looked at the command block code, but I don't know what I'm doing wrong:
(Relevant parts of) my code:
ComputerBlock.java
ComputerTileEntity.java
instead of
EDIT: I'll be darned if this is the problem, does the argument to registerTileEntity have to match the block name? I'll try it now.
EDIT2: I tried that, still not working. I've updated my code to reflect the changes.
0
getBlockTileEntity just returns null!
Help! Anyone!!!
1