93 lines
3.1 KiB
Java
93 lines
3.1 KiB
Java
package net.minecraft.client.multiplayer.prediction;
|
|
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
|
|
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
|
import net.minecraft.client.player.LocalPlayer;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class BlockStatePredictionHandler implements AutoCloseable {
|
|
private final Long2ObjectOpenHashMap<BlockStatePredictionHandler.ServerVerifiedState> serverVerifiedStates = new Long2ObjectOpenHashMap<>();
|
|
private int currentSequenceNr;
|
|
private boolean isPredicting;
|
|
|
|
public void retainKnownServerState(BlockPos pos, BlockState state, LocalPlayer player) {
|
|
this.serverVerifiedStates
|
|
.compute(
|
|
pos.asLong(),
|
|
(long_, serverVerifiedState) -> serverVerifiedState != null
|
|
? serverVerifiedState.setSequence(this.currentSequenceNr)
|
|
: new BlockStatePredictionHandler.ServerVerifiedState(this.currentSequenceNr, state, player.position())
|
|
);
|
|
}
|
|
|
|
public boolean updateKnownServerState(BlockPos pos, BlockState state) {
|
|
BlockStatePredictionHandler.ServerVerifiedState serverVerifiedState = this.serverVerifiedStates.get(pos.asLong());
|
|
if (serverVerifiedState == null) {
|
|
return false;
|
|
} else {
|
|
serverVerifiedState.setBlockState(state);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public void endPredictionsUpTo(int sequence, ClientLevel level) {
|
|
ObjectIterator<Entry<BlockStatePredictionHandler.ServerVerifiedState>> objectIterator = this.serverVerifiedStates.long2ObjectEntrySet().iterator();
|
|
|
|
while (objectIterator.hasNext()) {
|
|
Entry<BlockStatePredictionHandler.ServerVerifiedState> entry = (Entry<BlockStatePredictionHandler.ServerVerifiedState>)objectIterator.next();
|
|
BlockStatePredictionHandler.ServerVerifiedState serverVerifiedState = (BlockStatePredictionHandler.ServerVerifiedState)entry.getValue();
|
|
if (serverVerifiedState.sequence <= sequence) {
|
|
BlockPos blockPos = BlockPos.of(entry.getLongKey());
|
|
objectIterator.remove();
|
|
level.syncBlockState(blockPos, serverVerifiedState.blockState, serverVerifiedState.playerPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
public BlockStatePredictionHandler startPredicting() {
|
|
this.currentSequenceNr++;
|
|
this.isPredicting = true;
|
|
return this;
|
|
}
|
|
|
|
public void close() {
|
|
this.isPredicting = false;
|
|
}
|
|
|
|
public int currentSequence() {
|
|
return this.currentSequenceNr;
|
|
}
|
|
|
|
public boolean isPredicting() {
|
|
return this.isPredicting;
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
static class ServerVerifiedState {
|
|
final Vec3 playerPos;
|
|
int sequence;
|
|
BlockState blockState;
|
|
|
|
ServerVerifiedState(int sequence, BlockState blockState, Vec3 playerPos) {
|
|
this.sequence = sequence;
|
|
this.blockState = blockState;
|
|
this.playerPos = playerPos;
|
|
}
|
|
|
|
BlockStatePredictionHandler.ServerVerifiedState setSequence(int sequence) {
|
|
this.sequence = sequence;
|
|
return this;
|
|
}
|
|
|
|
void setBlockState(BlockState blockState) {
|
|
this.blockState = blockState;
|
|
}
|
|
}
|
|
}
|