Skip to content

Commit

Permalink
refactor: GameRules is changed to an interface
Browse files Browse the repository at this point in the history
  • Loading branch information
smartcmd committed Dec 26, 2024
1 parent 29f33c9 commit 7556d67
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 133 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Unless otherwise specified, any version comparison below is the comparison of se

### Changed

- (API) `GameRules` is changed to an interface.
- Breaking block related warnings are now moved to debug channel.
- Improved code readability for I18n module.
- NBT library is now updated to 3.0.10.
Expand Down
124 changes: 5 additions & 119 deletions api/src/main/java/org/allaymc/api/world/gamerule/GameRules.java
Original file line number Diff line number Diff line change
@@ -1,92 +1,30 @@
package org.allaymc.api.world.gamerule;

import org.allaymc.api.world.World;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.GameRuleData;
import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket;
import org.jetbrains.annotations.UnmodifiableView;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* GameRules is a container for storing and managing game rules.
*
* @author Jukebox | Cool_Loong
* @author Cool_Loong
*/
public class GameRules {
public static final GameRules DEFAULT = new GameRules();

private final Map<GameRule, Object> gameRules = new HashMap<>();

/**
* Whether the game rules have been modified since last sending to the players.
*/
private boolean dirty;

/**
* Creates a new GameRules instance with default values.
*/
public GameRules() {
for (GameRule gameRule : GameRule.values()) {
this.gameRules.put(gameRule, gameRule.getDefaultValue());
}
}

/**
* Creates a new GameRules instance with the specified game rules.
*
* @param gameRules the game rules to be added
*/
public GameRules(Map<GameRule, Object> gameRules) {
this.gameRules.putAll(gameRules);
}

/**
* Reads game rules from NBT.
*
* @param nbt the NBT to read from
*
* @return the game rules
*/
public static GameRules readFromNBT(NbtMap nbt) {
Map<GameRule, Object> gameRules = new HashMap<>();
for (GameRule gameRule : GameRule.values()) {
var key = gameRule.getName().toLowerCase();
if (nbt.containsKey(key)) {
switch (gameRule.getType()) {
case INT -> gameRules.put(gameRule, nbt.getInt(key));
case BOOLEAN -> gameRules.put(gameRule, nbt.getBoolean(key));
}
}
}
return new GameRules(gameRules);
}

public interface GameRules {
/**
* Get the game rules.
*
* @return the game rules
*/
@UnmodifiableView
public Map<GameRule, Object> getGameRules() {
return Collections.unmodifiableMap(gameRules);
}
Map<GameRule, Object> getGameRules();

/**
* Set a game rule's value.
*
* @param gameRule the game rule
* @param value the value
*/
public void put(GameRule gameRule, Object value) {
gameRules.put(gameRule, value);
dirty = true;
}
void set(GameRule gameRule, Object value);

/**
* Get a game rule's value.
Expand All @@ -96,57 +34,5 @@ public void put(GameRule gameRule, Object value) {
*
* @return the value
*/
@SuppressWarnings("unchecked")
public <V> V get(GameRule gameRule) {
return (V) gameRules.getOrDefault(gameRule, gameRule.getDefaultValue());
}

/**
* Send the game rules to the players in a world.
*
* @param world the world which players are in.
*/
public void sync(World world) {
if (!dirty) return;
world.broadcastPacket(buildPacket());
dirty = false;
}

/**
* Builds a GameRulesChangedPacket from the game rules.
*
* @return the packet
*/
public GameRulesChangedPacket buildPacket() {
var pk = new GameRulesChangedPacket();
pk.getGameRules().addAll(toNetworkGameRuleData());
return pk;
}

/**
* Converts the game rules to a list of GameRuleData.
*
* @return the list of GameRuleData
*/
public List<GameRuleData<?>> toNetworkGameRuleData() {
return this.getGameRules().entrySet().stream()
.map(entry -> new GameRuleData<>(entry.getKey().getName(), entry.getValue()))
.collect(Collectors.toList());
}

/**
* Writes the game rules to NBT.
*
* @param builder the NbtMapBuilder to write to
*/
public void writeToNBT(NbtMapBuilder builder) {
for (Map.Entry<GameRule, Object> entry : this.gameRules.entrySet()) {
// Lower case name should be used for key
var key = entry.getKey().getName().toLowerCase();
switch (entry.getKey().getType()) {
case INT -> builder.putInt(key, (Integer) entry.getValue());
case BOOLEAN -> builder.putBoolean(key, (Boolean) entry.getValue());
}
}
}
<V> V get(GameRule gameRule);
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.allaymc.server.entity.component.event.CPlayerMoveEvent;
import org.allaymc.server.entity.impl.EntityPlayerImpl;
import org.allaymc.server.world.AllayWorld;
import org.allaymc.server.world.gamerule.AllayGameRules;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
Expand Down Expand Up @@ -330,7 +331,7 @@ protected void teleportOverDimension(Location3fc target, EntityTeleportEvent.Rea
// Send new world's time
targetDim.getWorld().getWorldData().sendTimeOfDay(thisPlayer);
// Send new world's game rules
networkComponent.sendPacket(targetDim.getWorld().getWorldData().getGameRules().buildPacket());
networkComponent.sendPacket(((AllayGameRules) targetDim.getWorld().getWorldData().getGameRules()).buildPacket());
// Clear old world's weather
((AllayWorld) currentDim.getWorld()).clearWeather(thisPlayer);
// Send new world's weather
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.allaymc.server.entity.component.event.CPlayerLoggedInEvent;
import org.allaymc.server.network.processor.PacketProcessorHolder;
import org.allaymc.server.world.AllayWorld;
import org.allaymc.server.world.gamerule.AllayGameRules;
import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
Expand Down Expand Up @@ -249,7 +250,7 @@ public void disconnect(@MayContainTrKey String reason) {
try {
onDisconnect(disconnectReason);
// Tell the client that it should disconnect
if (thisPlayer.getClientSession().isConnected()){
if (thisPlayer.getClientSession().isConnected()) {
thisPlayer.getClientSession().disconnect(disconnectReason);
}
} catch (Throwable t) {
Expand Down Expand Up @@ -348,7 +349,7 @@ public void initializePlayer() {

protected StartGamePacket encodeStartGamePacket(World spawnWorld, PlayerData playerData, Dimension dimension) {
var startGamePacket = new StartGamePacket();
startGamePacket.getGamerules().addAll(spawnWorld.getWorldData().getGameRules().toNetworkGameRuleData());
startGamePacket.getGamerules().addAll(((AllayGameRules) spawnWorld.getWorldData().getGameRules()).toNetworkGameRuleData());
startGamePacket.setUniqueEntityId(thisPlayer.getRuntimeId());
startGamePacket.setRuntimeEntityId(thisPlayer.getRuntimeId());
startGamePacket.setPlayerGameType(GameType.from(playerData.getNbt().getInt("GameType", spawnWorld.getWorldData().getGameType().ordinal())));
Expand Down
5 changes: 0 additions & 5 deletions server/src/main/java/org/allaymc/server/world/AllayWorld.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ protected void tick(long currentTick) {
if (!ENABLE_INDEPENDENT_NETWORK_THREAD) {
handleSyncPackets(null);
}
syncData();
tickTime(currentTick);
tickWeather();
scheduler.tick();
Expand Down Expand Up @@ -304,10 +303,6 @@ public float getTickUsage() {
return gameLoop.getTickUsage();
}

protected void syncData() {
worldData.getGameRules().sync(this);
}

public void startTick() {
if (worldThread.getState() != Thread.State.NEW) {
throw new IllegalStateException("World is already start ticking!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import org.allaymc.api.world.World;
import org.allaymc.api.world.WorldData;
import org.allaymc.api.world.gamerule.GameRule;
import org.allaymc.api.world.gamerule.GameRules;
import org.allaymc.server.world.gamerule.AllayGameRules;
import org.cloudburstmc.protocol.bedrock.data.GameType;
import org.joml.Vector3i;
import org.joml.Vector3ic;
Expand All @@ -21,7 +21,6 @@
@Builder
public final class AllayWorldData implements WorldData {

@Setter
private World world;

@Builder.Default
Expand All @@ -39,11 +38,16 @@ public final class AllayWorldData implements WorldData {
@Builder.Default
private int timeOfDay = TIME_SUNRISE;
@Builder.Default
private GameRules gameRules = new GameRules();
private AllayGameRules gameRules = new AllayGameRules();
@Getter
@Builder.Default
private long worldStartCount = 0;

public void setWorld(World world) {
this.world = world;
this.gameRules.setWorld(world);
}

@Override
public void setGameType(GameType gameType) {
this.gameType = gameType;
Expand Down Expand Up @@ -79,7 +83,7 @@ private int rollbackTimeOfDay(int time) {
public void setGameRuleValue(GameRule gameRule, Object value) {
var event = new GameRuleChangeEvent(this.world, gameRule, getGameRuleValue(gameRule), value);
if (event.call()) {
this.gameRules.put(gameRule, event.getNewValue());
this.gameRules.set(gameRule, event.getNewValue());
}
}

Expand Down
Loading

0 comments on commit 7556d67

Please sign in to comment.