Compare commits

...
Author SHA1 Message Date
Ludovic MarieandClaude Opus 5.5 2307872298 World options: the game rules page edits the server thread's rules
With single player on the server thread, the world's game rules live on
the server, but the World Options game rules page read and wrote the
window's own copy: the rules it showed were not the world's, and Done
changed nothing the world used (Allow Commands, read from the window's
empty level, also refused every change). The page now reads the
server's rules, and Done sets them there behind the server's Allow
Commands, as ServerboundSetGameRulePacket reaches handleSetGameRule.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 08:09:25 +02:00
+31 -2
View File
@@ -483,7 +483,30 @@ impl Game<'_> {
let Exit::Apply(changes) = exit else {
return;
};
if !self.allow_commands() || changes.is_empty() {
if changes.is_empty() {
return;
}
// The world (and whether it allows commands) is the server
// thread's when there is one.
let applied = match &self.integrated {
Some(server) => {
let sent = changes.clone();
server
.call(move |g| {
if !g.allow_commands() {
return false;
}
for (name, value) in sent {
g.ui.rules.set(name, value);
}
g.sync_rules();
true
})
.unwrap_or(false)
}
None => self.allow_commands(),
};
if !applied {
return;
}
for (name, value) in changes {
@@ -789,7 +812,13 @@ impl Game<'_> {
Some(Button::Lock) => o.locked = !o.locked,
Some(Button::Restrictions) => o.view = View::Restrictions,
Some(Button::GameRules) => {
o.rules = Some(RulesScreen::new(&self.ui.rules));
// The world's rules are the server thread's when there is one.
let rules = self
.integrated
.as_ref()
.and_then(|s| s.call(|g| g.ui.rules.clone()))
.unwrap_or_else(|| self.ui.rules.clone());
o.rules = Some(RulesScreen::new(&rules));
o.view = View::GameRules;
}
Some(Button::Lan) => {