Earthcomputer
- Earthcomputer
- earthcomputer
- Europe/Stockholm
- Yes
- No
Put the summary of the bug you're having here
What I expected to happen was that the Creeper wouldn't react, since it should only be provoked by the player. This caused grieving in my creative world
Instead it should not explode at all in creative mode and only explode when provoked by the player in survival. Also, Snow Golems shouldn't attack when Iron Golems wouldn't attack in the same situation (this bug doesn't happen with an Iron Golem)The Creeper exploded when attacked by the Snow Golem
Steps to Reproduce:
1. In creative mode, create a 2x1 pen and make a Snow Golem in it
2. Spawn a creeper in it and watch the Golem attack the Creeper and the Creeper react!What I expected to happen was that the Creeper wouldn't react, since it should only be provoked by the player. This caused grieving in my creative world
Instead it should not explode at all in creative mode and only explode when provoked by the player in survival. Also, Snow Golems shouldn't attack when Iron Golems wouldn't attack in the same situation (this bug doesn't happen with an Iron Golem)The Creeper exploded when attacked by the Snow Golem
Steps to Reproduce:
1. In creative mode, create a 2x1 pen and make a Snow Golem in it
2. Spawn a creeper in it and watch the Golem attack the Creeper and the Creeper react!
Creepers explode when provoked by Snow GolemsSnow Golems attack in creative mode
What I expected to happen was that the Creeper wouldn't react, since it should only be provoked by the player. This caused grieving in my creative world
Instead it should not explode at all in creative mode and only explode when provoked by the player in survival. Also, Snow Golems shouldn't attack when Iron Golems wouldn't attack in the same situation (this bug doesn't happen with an Iron Golem)The Creeper exploded when attacked by the Snow Golem
Steps to Reproduce:
1. In creative mode, create a 2x1 pen and make a Snow Golem in it
2. Spawn acreeper in it and watch the Golem attack the Creeper and the Creeper react!What I expected to happen was that the Creeper wouldn't react, since it should only be provoked by the player. This caused grieving in my creative world
Instead it should not explode at all in creative mode except with flint and steel and only explode when provoked by the player in survival. Also, Snow Golems shouldn't attack when Iron Golems wouldn't attack in the same situation (i.e. not in creative mode) (this bug doesn't happen with an Iron Golem)The Creeper exploded when attacked by the Snow Golem
Steps to Reproduce:
1. In creative mode, create a 2x1 pen and make a Snow Golem in it
2. Spawn a Creeper in it and watch the Golem attack the Creeper and the Creeper react!
What I expected to happen was that the Creeper wouldn't react, since it should only be provoked by the player. This caused serious grieving in my creative world
Instead it should not explode at all in creative mode except with flint and steel and only explode when provoked by the player in survival. Also, Snow Golems shouldn't attack when Iron Golems wouldn't attack in the same situation (i.e. not in creative mode) (this bug doesn't happen with an Iron Golem)The Creeper exploded when attacked by the Snow Golem
Steps to Reproduce:
1. In creative mode, create a 2x1 pen and make a Snow Golem in it
2. Spawn a Creeper in it and watch the Golem attack the Creeper and the Creeper react!
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: to make the error occur on your system you may need to increase the maxCommandChainLength gamerule (untested, depends on the amount of memory available to Java).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. This needs to be separate from the code in CommandBase that currently does this because it needs to recognize nested execute commands, e.g.:execute @e[type=skeleton] ~ ~ ~ execute @a[r=10,tag=unlucky] ~ ~ ~ detect ~ ~-1 ~ diamond_ore * summon arrowMaybe there could be a static method in CommandExecute which would, for the example above, find all unlucky players within 10 blocks of a skeleton standing on diamond ore, and also return the string 'summon arrow'. CommandExecute could also use this static method itself.
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute-with-function command combination. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of function command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { if(command.length > 1 &&"function".equals(command[command.length - 2]))returnnewExecuteWithFunctionInsn(command, sender); }return new NormalCommandInsn(command, sender); } ... private static class ExecuteWithFunctionInsn extends Insn { private List<ICommandSender> senders; private String function; public ExecuteWithFunctionInsn(String[] command) { senders = CommandExecute.getExecutingEntities(sender, ArrayUtils.subarray(command, 1, command.length)); function = command[command.length - 1]; } public void execute(Deque<Insn> insns) { senders.forEach(sender -> insns.addFirst(new FunctionInsn(function, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functionsDescription
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: to make the error occur on your system you may need to increase the maxCommandChainLength gamerule (untested, depends on the amount of memory available to Java).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. This needs to be separate from the code in CommandBase that currently does this because it needs to recognize nested execute commands, e.g.:execute @e[type=skeleton] ~ ~ ~ execute @a[r=10,tag=unlucky] ~ ~ ~ detect ~ ~-1 ~ diamond_ore * summon arrowMaybe there could be a static method in CommandExecute which would, for the example above, find all unlucky players within 10 blocks of a skeleton standing on diamond ore, and also return the string 'summon arrow'. CommandExecute could also use this static method itself.
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute-with-function command combination. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of function command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the function command at the end of the execute command(s) and modify the list of command senders String[] functionCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender); if (functionCmd.length > 1 && "function".equals(functionCmd[0]) return new ExecuteWithFunctionInsn(functionCmd[1], senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteWithFunctionInsn extends Insn { private List<ICommandSender> senders; private String function; public ExecuteWithFunctionInsn(List<ICommandSender> senders, String function) { this.senders = senders; this.function = function; } public void execute(Deque<Insn> insns) { senders.forEach(sender -> insns.addFirst(new FunctionInsn(function, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: to make the error occur on your system you may need to increase the maxCommandChainLength gamerule (untested, depends on the amount of memory available to Java).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. This needs to be separate from the code in CommandBase that currently does this because it needs to recognize nested execute commands, e.g.:execute @e[type=skeleton] ~ ~ ~ execute @a[r=10,tag=unlucky] ~ ~ ~ detect ~ ~-1 ~ diamond_ore * summon arrowMaybe there could be a static method in CommandExecute which would, for the example above, find all unlucky players within 10 blocks of a skeleton standing on diamond ore, and also return the string 'summon arrow'. CommandExecute could also use this static method itself.
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute-with-function command combination. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of function command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the function command at the end of the execute command(s) and modify the list of command senders String[] functionCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); if (functionCmd.length > 1 && "function".equals(functionCmd[0]) return new ExecuteWithFunctionInsn(functionCmd[1], senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteWithFunctionInsn extends Insn { private List<ICommandSender> senders; private String function; public ExecuteWithFunctionInsn(List<ICommandSender> senders, String function) { this.senders = senders; this.function = function; } public void execute(Deque<Insn> insns) { senders.forEach(sender -> insns.addFirst(new FunctionInsn(function, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: t
o make the error occur on your system you may need to increasethe maxCommandChainLengthgamerule(untested,depends on the amount of memory available to Java).Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them.This needs to be separate from the code in CommandBase that currently does this because it needs to recognize nested execute commands, e.g.:execute @e[type=skeleton] ~ ~ ~ execute @a[r=10,tag=unlucky]~ ~ ~ detect ~ ~-1 ~ diamond_ore * summon arrowMaybe there could be a static method in CommandExecute which would, for the example above, find all
unlucky players within 10 blocks of a skeleton standing on diamond ore, and alsoreturn the string 'summon arrow'. CommandExecute could also use this static method itself.Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute
-with-function command combination. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set offunctioncommand 'instructions'.// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return thefunctioncommand at the end of the execute command(s)and modify the list of command senders String[]functionCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders);if(functionCmd.length > 1 &&"function".equals(functionCmd[0])return newExecuteWithFunctionInsn(functionCmd[1], senders);}returnnewNormalCommandInsn(command, sender); } ...private static class ExecuteWithFunctionInsn extends Insn { private List<ICommandSender> senders; private Stringfunction; public ExecuteWithFunctionInsn(List<ICommandSender> senders, Stringfunction) { this.senders = senders; this.function = function; } public void execute(Deque<Insn> insns) { senders.forEach(sender -> insns.addFirst(newFunctionInsn(function, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functionsDescription
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteWithFunctionInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteWithFunctionInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } public void execute(Deque<Insn> insns) { senders.forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteWithFunctionInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteWithFunctionInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } public void execute(Deque<Insn> insns) { senders.forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteWithFunctionInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } public void execute(Deque<Insn> insns) { senders.forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } publicvoid execute(Deque<Insn> insns) {senders.forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functionsDescription
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } public void execute(Deque<Insn> insns) { // Reverse order because we're adding them at the start Collections.reverse(senders).forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Clearly, for thistobesolved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, andthenexecutethecommandon each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } public void execute(Deque<Insn> insns) { // Reverse order because we're adding them at the start Collections.reverse(senders).forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functionsDescription
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Edit: there is a better solution in the comments. I'd read that before wasting your time on this suggestion
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } public void execute(Deque<Insn> insns) { // Reverse order because we're adding them at the start Collections.reverse(senders).forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
Proposed solution
Edit: there is a better solution in the comments. I'd read that before wasting your time on this suggestion
Clearly, for this to be solved properly, the code needs to recognize the execute command as a special case. With this, of course, comes a problem: we are duplicating the logic of the execute command into the function code, which is never a good thing.
To get around this, it is possible to modify CommandExecute to find all the matching entities first, and then execute the command on each of them. E.g.:execute @a ~ ~ ~ detect ~ ~-1 ~ diamond_ore * say I am a very lucky personMaybe there could be a static method in CommandExecute which would, for the example above, find all players (command senders) standing on diamond ore (matching the criteria) and returning the string 'say I am a very lucky person' (the command to execute).
Back to the case of functions, it seems (from decompiled source code) the list of commands is first converted to a polymorphic set of 'instructions', of which at the moment there are 2 types: a function command and a regular command. I propose that a third type is added, one for an execute command. This would use the logic from the static method in CommandExecute to 'unroll' the execute command into a set of other command 'instructions'.
// I believe the code looked something like this (can't remember exactly) // It could be modified like this public Insn getInstruction(String[] command, ICommandSender sender) { if ("function".equals(command[0])) return new FunctionInsn(command[1], sender); else if ("execute".equals(command[0])) { List<ICommandSender> senders = Lists.newArrayList(); // This method will return the nested command at the end of the execute command and modify the list of command senders String[] nestedCmd = CommandExecute.processExecuteCommand(ArrayUtils.subarray(command, 1, command.length), sender, senders); return new ExecuteInsn(nestedCmd, senders); } return new NormalCommandInsn(command, sender); } ... private static class ExecuteInsn extends Insn { private List<ICommandSender> senders; private String[] nestedCmd; public ExecuteInsn(List<ICommandSender> senders, String[] nestedCmd) { this.senders = senders; this.nestedCmd = nestedCmd; } public void execute(Deque<Insn> insns) { // Reverse order because we're adding them at the start Collections.reverse(senders).forEach(sender -> insns.addFirst(getInstruction(nestedCmd, sender))); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functionsDescription
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
What calls what:
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- FunctionManager.runFunction(Function, ICommandSender) (line 114)
- FunctionManager$LineOfCode.execute(ArrayDeque<LineOfCode>, int) (line 176)
- Function$CommandInsn.execute(FunctionManager, ICommandSender, ArrayDeque<LineOfCode>, int) (line 60)
- AbstractCommandManager.execute(ICommandSender, String) (line 62)
- AbstractCommandManager.tryExecute(ICommandSender, String[], ICommand, String) (line 92)
- CommandExecute.execute(MinecraftServer, ICommandSender, String[]) (line 118)
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- ...
Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
What calls what:
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- FunctionManager.runFunction(Function, ICommandSender) (line 114)
- FunctionManager$LineOfCode.execute(ArrayDeque<LineOfCode>, int) (line 176)
- Function$CommandInsn.execute(FunctionManager, ICommandSender, ArrayDeque<LineOfCode>, int) (line 60)
- AbstractCommandManager.execute(ICommandSender, String) (line 62)
- AbstractCommandManager.tryExecute(ICommandSender, String[], ICommand, String) (line 92)
- CommandExecute.execute(MinecraftServer, ICommandSender, String[]) (line 118)
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- ...
Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functionsDescription
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
What calls what:
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- FunctionManager.runFunction(Function, ICommandSender) (line 114)
- FunctionManager$LineOfCode.execute(ArrayDeque<LineOfCode>, int) (line 176)
- Function$CommandInsn.execute(FunctionManager, ICommandSender, ArrayDeque<LineOfCode>, int) (line 60)
- AbstractCommandManager.execute(ICommandSender, String) (line 62)
- AbstractCommandManager.tryExecute(ICommandSender, String[], ICommand, String) (line 92)
- CommandExecute.execute(MinecraftServer, ICommandSender, String[]) (line 118)
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- ...
The current implementation of FunctionManager.runFunction looks like this:
public int runFunction(Function func, ICommandSender sender) { int maxChainLength = getMaxCommandChainLength(); // Attempted fix for this bug (I think) // This should also be a >= 1 (if I'm not mistaken) if (this.linesLeftToExecute.size() > 1) { if (this.linesLeftToExecute.size() < maxChainLength) { this.linesLeftToExecute.addFirst(new LineOfCode(this, sender, new FunctionInsn(func))); } return 0; } try { int linesExecuted = 0; // ... read function to add all lines ... while (!this.linesLeftToExecute.isEmpty()) { // Since the line of code is removed *before* it is executed, // linesLeftToExecute could be empty before we reach the lines above again this.linesLeftToExecute.removeFirst().execute(this.linesLeftToExecute, maxChainLength); if (++linesExecuted >= maxChainLength) { return linesExecuted; } } return linesExecuted; } finally { this.linesLeftToExecute.clear(); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
Description
When executing the following command:
/function test:testand the definition of test:test is as follows:
execute @s ~ ~ ~ function test:testyou get this error message in the chat and server log:
An unknown error occurred while attempting to perform this commandNote: this also gets around the maxCommandChainLength limit (untested, but assumed true based on the code analysis below).
Edit: as of 1.12-pre3, the execute command must be the last command in the function
Why this is a problem
Though the example above may be solvable by just replacing the execute command with a function command, it turns out that the execute command is the only way to create real conditionals, terminating loops and recursive functions. If I have a recursive function equivalent to a for loop from 1-1000, for example, it takes up a lot of space on the stack (see code analysis below). It may even be possible for more complex functions to run out of stack space, which kind of defeats the point of the maxCommandChainLength gamerule.
Code analysis
The bug is probably caused by a StackOverflowError. The current code used to execute functions is quite clever: it treats function commands inside functions differently to other commands such to avoid stack overflows from occurring. This is why we need it inside an execute command in the function definition, so the game doesn't recognize it as a function command.
What calls what:
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- FunctionManager.runFunction(Function, ICommandSender) (line 114)
- FunctionManager$LineOfCode.execute(ArrayDeque<LineOfCode>, int) (line 176)
- Function$CommandInsn.execute(FunctionManager, ICommandSender, ArrayDeque<LineOfCode>, int) (line 60)
- AbstractCommandManager.execute(ICommandSender, String) (line 62)
- AbstractCommandManager.tryExecute(ICommandSender, String[], ICommand, String) (line 92)
- CommandExecute.execute(MinecraftServer, ICommandSender, String[]) (line 118)
- CommandFunction.execute(MinecraftServer, ICommandSender, String[]) (line 46)
- ...
The current implementation of FunctionManager.runFunction looks like this:
public int runFunction(Function func, ICommandSender sender) { int maxChainLength = getMaxCommandChainLength(); // Attempted fix for this bug (I think) // This should also be a >= 1 (if I'm not mistaken) if (this.linesLeftToExecute.size() > 1) { if (this.linesLeftToExecute.size() < maxChainLength) { this.linesLeftToExecute.addFirst(new LineOfCode(this, sender, new FunctionInsn(func))); } return 0; } try { int linesExecuted = 0; // ... read function to add all lines ... while (!this.linesLeftToExecute.isEmpty()) { // Since the line of code is removed *before* it is executed, // linesLeftToExecute could be empty before we reach the lines above again this.linesLeftToExecute.removeFirst().execute(this.linesLeftToExecute, maxChainLength); if (++linesExecuted >= maxChainLength) { return linesExecuted; } } return linesExecuted; } finally { this.linesLeftToExecute.clear(); } }Alternative solution
(doesn't fix bug, but add a way round it)
Add proper support for conditionals in functions
If a block that would pop off when pushed is pulled, it also pops off.
Expected behaviour (happens in 1.12):
The block is ignored, not pulled
Actual behaviour:
Block is pulled, usually resulting in it popping off
Also affects glazed terracotta
When a 1.12 world is upgraded to 1.13, chunks marked for repopulation are deleted and regenerated from scratch, as far as I can tell.
Expected behaviour
Existing structures in the chunk marked for repopulation should be preserved, and population is added on top of it. For example, if you built a house with a grass roof then marked the chunk for repopulation, next time you enter the area you might expect to see grass + trees on the roof. This was especially useful for larger areas.
Actual behaviour
The chunk is deleted and regenerated from scratch. For example, if you built a house then marked the chunk for repopulation, next time you enter the area the house will be gone.
Steps to reproduce
- Load up 1.12
Build some structure in a chunk (bonus points for prettiness!)Close the game and open the world in mcedit- Mark the chunks containing the structure for repopulation
Close mcedit- Open the world in 1.13
- Observe your beutiful structure is gone
Note: building the structure in 1.12 and using mcedit is only for ease of reproduction. If mcedit or some other tool were to work for 1.13 worlds this bug would also probably apply.
Note 2: I did testing in the End if you can't reproduce it in the overworld
When a 1.12 world is upgraded to 1.13, chunks marked for repopulation are deleted and regenerated from scratch, as far as I can tell.
Expected behaviour
Existing structures in the chunk marked for repopulation should be preserved, and population is added on top of it. For example, if you built a house with a grass roof then marked the chunk for repopulation, next time you enter the area you might expect to see grass + trees on the roof. This was especially useful for larger areas.
Actual behaviour
The chunk is deleted and regenerated from scratch. For example, if you built a house then marked the chunk for repopulation, next time you enter the area the house will be gone.
Steps to reproduce
- Load the test world (attached) in 1.12.
- The pretty building is still intact, and a chorus flower has grown on the roof
- Load the test world in 1.13.
- The pretty building has disappeared
When a 1.12 world is upgraded to 1.13, chunks marked for repopulation are deleted and regenerated from scratch, as far as I can tell.
Expected behaviour
Existing structures in the chunk marked for repopulation should be preserved, and population is added on top of it. For example, if you built a house with a grass roof then marked the chunk for repopulation, next time you enter the area you might expect to see grass + trees on the roof. This was especially useful for larger areas.
Actual behaviour
The chunk is deleted and regenerated from scratch. For example, if you built a house then marked the chunk for repopulation, next time you enter the area the house will be gone.
Steps to reproduce
- Load the test world (attached) in 1.12.
- The pretty building is still intact, and a chorus flower has grown on the roof
- Load the test world in 1.13.
- The pretty building has disappeared
- Note: you have to load two copies of the test world or the chunk will no longer be marked for population
Self-explanatory
It's responding with unknown command/no permission
Ubuntu 18.04
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)
Apologies if this has been reported before, I searched for "save" and "saving" and could not find anything relevant.
This issue has occurred for a
new snapshots now, but wasn't an issue in the last release, 1.15.2.To reproduce in singleplayer, start a world and close it again, observe that the world can take tens of seconds to close. To reproduce on a dedicated server, start the server and type stop in the console, and observe that the server hangs for a bit after printing the "saving chunks for level" message.
Given that this hasn't been reported yet, I'm assuming it may be operating system dependent, although I haven't tested this on other operating systems. My OS is Ubuntu 18.04 (see the environment section).
I ran the server through VisualVM, and at first glance it seems like a race condition where two threads are trying to close the same output stream. I have attached a screenshot of part of the profile results, as well as a CSV containing the entire snapshot.
Apologies if this has been reported before, I searched for "save" and "saving" and could not find anything relevant.
This issue has occurred for a few snapshots now, but wasn't an issue in the last release, 1.15.2.
To reproduce in singleplayer, start a world and close it again, observe that the world can take tens of seconds to close. To reproduce on a dedicated server, start the server and type stop in the console, and observe that the server hangs for a bit after printing the "saving chunks for level" message.
Given that this hasn't been reported yet, I'm assuming it may be operating system dependent, although I haven't tested this on other operating systems. My OS is Ubuntu 18.04 (see the environment section).
I ran the server through VisualVM, and at first glance it seems like a race condition where two threads are trying to close the same output stream. I have attached a screenshot of part of the profile results, as well as a CSV containing the entire snapshot.
Apologies if this has been reported before, I searched for "save" and "saving" and could not find anything relevant.
This issue has occurred
for a few snapshots now, but wasn't an issue in the last release, 1.15.2.To reproduce in singleplayer, start a world and close it again, observe that the world can take tens of seconds to close. To reproduce on a dedicated server, start the server and type stop in the console, and observe that the server hangs for a bit after printing the "saving chunks for level" message.
Given that this hasn't been reported yet, I'm assuming it may be operating system dependent, although I haven't tested this on other operating systems. My OS is Ubuntu 18.04 (see the environment section).
I ran the server through VisualVM
, and at first glance it seems like a race condition where two threads are trying to close the same output stream. I have attached a screenshot of part of the profile results, as well as a CSV containing the entire snapshot.Apologies if this has been reported before, I searched for "save" and "saving" and could not find anything relevant.
This issue has occurred since 20w14a. There is a workaround on a server, to disable sync-chunk-writes, but there is no workaround in singleplayer.
To reproduce in singleplayer, start a world and close it again, observe that the world can take tens of seconds to close. To reproduce on a dedicated server, start the server and type stop in the console, and observe that the server hangs for a bit after printing the "saving chunks for level" message.
Given that this hasn't been reported yet, I'm assuming it may be operating system dependent, although I haven't tested this on other operating systems. My OS is Ubuntu 18.04 (see the environment section).
I ran the server through VisualVM. I have attached a screenshot of part of the profile results, as well as a CSV containing the entire snapshot.
Worlds take a very long time to closesync-chunk-writes often takes over a minute to close a world
If you try to create multiple empty tags in a datapack, the server crashes on startup.
Steps to reproduce:
- Add the attached datapack (empty_tags.zip) to your world
- (Make sure the datapack is enabled)
- Observe that the server crashes
Note that the proposed fix still has a slight bias towards the northwest (with both stalagmites and stalactites). This is due to rounding down when the windSpeed is actually added to the position in the "offset" method. To remove all bias, in addition to the fix above, the windSpeed needs to be rounded with e.g. Math.round() when added to the position in "offset".
The /reload command doesn't reload the test_instance registry, requiring a server restart in order to detect changes in this registry. I expected the /reload command to reload the test_instance registry so I don't have to restart the server when I change the datapack.
Steps to reproduce:
- Open a world
- Add a test instance to the test instance registry in a datapack
- Run the /reload command
- Observe that the new test instance isn't registered
This also affects existing test instances which are modified.
The bug
When you let a structure block with integrity lower than 1.0 and seed of 0 (= random seed) load a structure every tick, the block at the lowest X, Y and Z coordinate of the structure appears to be less random over time. Compared to the other blocks of the structure, there are longer "streaks" where the block is either loaded or not loaded.
An extreme example (and reproduction steps) can be seen in this video: https://youtu.be/N8azjRO4KM0
Every tick a 8x8x8 cube of blocks is placed and afterwards a structure block loads a 8x8x8 cube with an integrity of 0.5. The block at the lowest X, Y and Z coordinates of the resulting cube stays for a significant amount of time the same.
Code analysis
20w49a, Mojang names
When a random seed is used (value 0) the method net.minecraft.world.level.block.entity.StructureBlockEntity.createRandom(long) creates a new Random instance based on the current milliseconds. Despite the milliseconds value being different every tick, the values are too similar as seed for the JDK Random implementation, as described in Earthcomputer's comment.
A better solution might be to have only one static Random instance which is reused.
The Bug
When you hover over a structure block, it used to display the mode and name, allowing players to determine which structure loads which without accessing the GUI. Now it's gone.
Steps to Reproduce:
- Summon a structure block with its "mode" set to "data" by using the command provided below.
/setblock ~ ~ ~ minecraft:structure_block[mode=data]
- Look at the structure block and take note as to whether or not it displays its mode when looked at.
Observed Behavior
Structure blocks don't display their mode when looked at.
Expected Behavior
Structure blocks would display their mode when looked at.
Code Analysis
See Earthcomputer's comment.
Earthcomputer My practical expermientation seems to indicate that what I proposed is true. Can you provide information about your experiments so that I may be able to explain what happens or can agree with your point of view?
Just saying something is wrong without saying why, is not helpful in any way.
Earthcomputer uhm, sorry, accidentally forward resolved this. let me fix this real quick









I think it's fine that Snow Golems attack Creepers in general, but in creative mode...
Well it happened once, I can't seem to reproduce the issue, even with Java 7 (I tried both 7 and 8). I'll come back here if I ever manage to reproduce it.
I think the real issue is actually the inconsistency between snow golems and iron golems. Iron golems won't attack creepers, whereas snow golems will. It used to be that creepers attack golems, which is what
MC-61844was about. Now the creeper sits there peacefully until the snow golem provokes it.I am unsure as to how this inconsistency would best be fixed. Preventing snow golems attacking creepers could break some creeper-based tree farms (but who still uses them?), but making iron golems attack creepers would just reverse the fix to
MC-61844.Can't reproduce this issue on latest snapshot. Are you sure that you don't have your chat turned off or something?
I think this might be because the /reload command is only intended to be used by players. Out of interest, what might you use this for?
Duplicates
MC-117330The code above as it is slightly changes the functionality of the execute command. I'll edit the post a bit later when I have more time.
Edit: fixed
Duplicate of
MC-117319That may indeed be a better solution.
What may be even better is to have the ICommandSender execute the command itself. The default implementation of ICommandSender.execute(String[] command) just delegates to CommandHandler.executeCommand (because we have default methods in Java 8), but FunctionCommandSender could override this to add the command to the deque instead if necessary. That way we're still keeping track of the maxCommandChainLength.
What also makes yours and this new solution better than my original proposed solution is that it would work for any command capable of running other commands, including /function, /execute and any others which may be added in the future. There will be no special cases in the function-executing code anymore.
Woah, no need for that. It's okay, everyone forgets things sometimes
On second thoughts, a cancellable ICommandSender.onCommandExecuted might be better
It says it's fixed, though it still happens on 1.12-pre3
I have replaced the old suggested fix in the original bug report to a stack-trace-type-deal.
Added more code analysis
I've done some more research into this. It seems that the bug was indeed partially fixed for 1.12-pre3, but not for all cases.
The bug now occurs if and only if the execute command is the last command in the function. I think I have identified the cause of this in the code analysis above.
This does mean however that there is a temporary workaround for map-makers:
This works because the execute command is no longer the last command in the function. It does however mean that we reach the maxCommandChainLength quicker with a dummy command we're not even using though...
The problem is, in 1.12 they added a new type of ICommandSender, let's call it DelegatingCommandSender, which, as the name suggests, delegates to another command sender. It's used by the execute command and functions.
Now, the execute command overrides the ICommandSender.getEntity() method to return the entity matched by the selector, so this mostly works fine. However, in the case that another DelegatingCommandSender delegates to this DelegatingCommandSender, which in turn delegates to the executor of the execute command (in your example the command block), there is a problem.
There is currently an oversight in DelegatingCommandSender. If it's told to delegate to another DelegatingCommandSender, it thinks "oh look! another delegating command sender. That's just delegating somewhere else, there's no point going through it, so I'm just going to bypass it and delegate to its child delegate instead". It does not take into account that the execute command and functions have subclassed DelegatingCommandSender.
So, in conclusion:
By the way, this bypassing of delegation is important to prevent StackOverflowError s from occurring while executing recursive functions. So if you reverse it you break something else, so it's a kind of catch 22.
The solution that springs to my mind is to do away with delegation and, it might be possible to store all the ICommandSender s on a stack instead.
We need recursion at the moment because there is no way to make a loop in a function. All I am saying is that such a seemingly simple fix to this bug here might have dire consequences for recursive functions (as I explained in more detail above). That doesn't mean that this bug can't be fixed, it just means that the fix might be slightly more complex, that's all.
The dilemma they have is they have to fix this bug without breaking
MC-117428again (which is still a bit broken, but that's another story).Just want to throw this in here:
As I was typing that both bugs got fixed haha
This could be more serious if the chest generates over a large lava lake
Note that this doesn't affect the vanilla texture
A fix for this might fit nicely with the change to tab-completion of functions in the gameLoopFunction gamerule
Just happened to me on 1.12.2
Affects 17w43b
What happens if you place a chest in beta 1.7.3, then load it in an intermediate version (1.5, say) and then load it in 1.12.2?
Just happened to me on a server on my LAN.
Happens using both the global IP addresses and the local 192.168.x.x addresses.
Happens when Windows Firewall is disabled serverside (and also when it's enabled).
I am able to connect to the server with no issues from a client on the same computer using localhost.
When I try to connect from a second computer, the message says that the connection was forcibly closed by the remote host (i.e. the server), but in the server console it simply says "Disconnected", which you normally just get when you log out. This happens both when a second account is already logged onto the server and when there's no-one else online. The second account never gets kicked.
First this:
cxb$c: nullcxb$c: null at cxb.a(SourceFile:295) ~[18w22c.jar:?] at cxb.a(SourceFile:299) ~[18w22c.jar:?] at cxb.b(SourceFile:289) ~[18w22c.jar:?] at dhg.l(SourceFile:653) ~[18w22c.jar:?] at dhg.a(SourceFile:221) ~[18w22c.jar:?] at dhh.a(SourceFile:23) ~[18w22c.jar:?] at uq.c(SourceFile:123) ~[18w22c.jar:?] at uq.a(SourceFile:106) ~[18w22c.jar:?] at cio.f(SourceFile:652) [18w22c.jar:?] at cos$2.a(SourceFile:65) [18w22c.jar:?] at cjp.mouseClicked(SourceFile:103) [18w22c.jar:?] at ckl.mouseClicked(SourceFile:45) [18w22c.jar:?] at ciq.b(SourceFile:67) [18w22c.jar:?] at ciq$$Lambda$756/500268044.run(Unknown Source) [18w22c.jar:?] at cmf.a(SourceFile:429) [18w22c.jar:?] at ciq.a(SourceFile:67) [18w22c.jar:?] at ciq$$Lambda$678/6650683.invoke(Unknown Source) [18w22c.jar:?] at org.lwjgl.glfw.GLFWMouseButtonCallbackI.callback(GLFWMouseButtonCallbackI.java:23) [lwjgl-glfw-3.1.2.jar:?] at org.lwjgl.system.JNI.invokeV(Native Method) ~[lwjgl-3.1.2.jar:?] at org.lwjgl.glfw.GLFW.glfwWaitEventsTimeout(GLFW.java:2599) [lwjgl-glfw-3.1.2.jar:?] at ciy.a(SourceFile:298) [18w22c.jar:?] at cio.c(SourceFile:844) [18w22c.jar:?] at cio.a(SourceFile:380) [18w22c.jar:?] at net.minecraft.client.main.Main.main(SourceFile:144) [18w22c.jar:?]Then one of these for every texture in the game:
Then one of these for every sound event:
[12:39:58] [Client thread/WARN]: Missing sound for event: minecraft:ambient.caveThen one of these for every block model and variant:
Then one of these for every item model:
Then one of these for every item model:
[12:40:05] [Client thread/WARN]: Missing model for: minecraft:item/carrot_on_a_stickSo ya, a lot in the log
Practical experimentation disagrees with the above code analysis. More code analysis is needed.
The way you tested is flawed. A better way to test would be to use `/blockdata` on the block 36 tile entity to inspect its state. As for why, we don't know yet, more code analysis is needed. But if you would like to see my theory, check discord.
You can make a flying machine to go out to unpopulated chunks in 1.12, then upgrade to 1.12 and the flying machine will disappear. However, I doubt players (even technical players) will encounter that by accident. NeunEinser is correct, this example was just for ease of reproducibility.
Also, getting the world that I uploaded would have been possible (but difficult) without external tools because you can generate the chunks in a way such that the 2x2 of chunks is never simultaneously loaded, and place the blocks with commands.
I encountered this when I was trying to test if something that works in 1.12 would work in 1.13, and was surprised to see that some stuff had disappeared. But if what ProfMobius said is true then that thing is unlikely to work in 1.13 anyway.
Since this is very minor I wouldn't mind it being closed as WaI.
Confirmed for 1.13 release
Also affects other containers e.g. hoppers
Probably same bug as https://bugs.mojang.com/browse/MCPE-26842
Related to
BDS-43Relates to
BDS-45Just had the same issue on Debian 9 today. I have both libssl1.0.2 and libssl1.1 installed.
Duplicate? Of what?
Yep, the first fix is simply a change from HashMap to LinkedHashMap.
The second fix is simply that the piston tile entity didn't save lastProgress, with the fix it does.
Affects 1.14
Confirmed for 19w46b
After testing various server versions, I can now say that this bug was introduced in 20w14a.
Aha, it's fixed by turning setting `sync-chunk-writes` to `false` in `server.properties`.
I will update the bug report to mention that `sync-chunk-writes` seriously needs optimizing, and also point out that there is no way to disable it in singleplayer (and no progress bar).
@Mish Rodic you mean 22a? I can't confirm in 21a, only 22a.
It should be pointed out that this bug report is quite misleading as to what the actual issue is here. writeByte is the method which should be used to write both signed and unsigned data, so the issue isn't a mismatch with serialization.
The actual effect of this issue is that in multiplayer, previousGameMode is deserialized as survival mode when the server sends not_set, whereas in singleplayer (since packets aren't serialized) it is decoded as not_set. This would cause the client to send /gamemode survival when pressing f3+n for the first time if the player starts off in spectator mode, and /gamemode with no argument in singleplayer (although I'm not sure it's possible to first spawn in spectator mode in singleplayer). It also causes different defaults of the game mode GUI depending on whether it's singleplayer or multiplayer, and I think the defaults for singleplayer are the intended behaviour.
The actual bug here is not that it is being read as an unsigned byte, it's that not_set is being sent in the first place. As I explained in the previous comment, this causes issues whether it's read correctly or not. The real fix is to do the logic that the game mode switcher screen currently does for the initial game mode, on the server, rather than on the client, so that not_set doesn't have to be sent in the first place. Or else the client can send "/gamemode " with no arguments.
It looks like the obfuscated text splash text, which is works as intended.
Works as intended. This is because the string only updates the observer every 10gt (half a second). So if you fly through the string and exit it within half a second, it will only update the observer once and leave the dispenser on. You need to redesign your contraption to work around this issue.
Could this be https://github.com/glfw/glfw/issues/747 ?
In that case, this bug would be fixed by updating the version of glfw that Minecraft uses to 3.3.
By the way, if this is the issue, then to have the best chance of reproducing it, you want to use the X11 window manager, and make sure the game is running at a low framerate (client-side lag).
Can confirm Marcono's comment that this is caused by the seeds being too similar to each other due to being initialized to the current time in milliseconds. Before producing any outputs, a Random object will multiply the seed you give by 0x5deece66d; there are 50ms in a tick, so you could expect the internal seed of the Random to differ by a maximum of approximately 0x5deece66d * 50 = 1‚260‚745‚195‚850 (give or take a few milliseconds). This make look like a lot, but nextFloat() < 0.5 will only be true if this internal seed is between 0 and 2^47 (mod 2^48), which about 100x larger. This explains the delay of seconds you can see.
The other blocks in the structure are not as noticeably affected, as repeated multiplication of 0x5deece66d (and then addition of 11 which I left out for simplicity) quickly scrambles seeds even if they started close together.
P.S. can confirm for 1.16.3
Confirmed for 1.16.3
This is caused by a refactor, which looks like it happened in 1.13, to block entity rendering. In 1.12, `BlockEntityRenderer.render` used to render the display name of a block entity if it had a name to display. `StructureBlockRenderer.render` used to call the superclass method. Now (at least in 1.16), the `BlockEntityRenderer.render` method is abstract and the code for rendering nameplates appears to have been removed (either by accident or by proguard).
As a side note, in 1.12, most block entities didn't call `super.render` even though the corresponding block entities overrode the method to get the nameplate, so didn't end up displaying the nameplate, which was probably a bug.
Thanks Sherlock
Note that the proposed fix still has a slight bias towards the northwest (with both stalagmites and stalactites). This is due to rounding down when the windSpeed is actually added to the position in the "offset" method. To remove all bias, in addition to the fix above, the windSpeed needs to be rounded with e.g. Math.round() when added to the position in "offset".
Hi, can someone please transfer the reporter from me, as I'm no longer interested in this issue and I get emails from it despite not watching it.
According to cortex, this is caused by the new jfr profiler support.
(for future reference, your UUID isn't private information, you can see other players' UUIDs when hovering over their name in chat, and there are websites where you can look up a player's UUID by their username).
It looks like this game event has been removed.
Mojang's code in `next` looks like this:
So isn't `m` always positive here? I don't see where the difference between >> and >>> in this case
I cannot reproduce using MC@h Matt 's repro instructions. I can only assume that their JavaRnd implementation is not equivalent to Mojang's RandomSource, or maybe that Mojang fixed it since the issue was reported. Here's the code I ran using Mojang's actual RandomSource:
And the output:
I think this issue can be closed.
If you're gonna make ender pearls load chunks on portal cooldown, imo you may as well make them load chunks all the time. It's easier to implement and would allow for much easier ender pearl cannon contraptions.
I have added reproduction steps to the description, even though most people who know how datapacks work should have been able to figure them out.
Fair but this one is particularly inconvenient and unexpected