MultiPlayerGameMode.java
net.minecraft.client.multiplayer.MultiPlayerGameMode
信息
- 全限定名:net.minecraft.client.multiplayer.MultiPlayerGameMode
- 类型:public class
- 包:net.minecraft.client.multiplayer
- 源码路径:src/main/java/net/minecraft/client/multiplayer/MultiPlayerGameMode.java
- 起始行号:L74
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L75 - 说明:
TODO
- 类型:
-
minecraft- 类型:
Minecraft - 修饰符:
private final - 源码定位:
L76 - 说明:
TODO
- 类型:
-
connection- 类型:
ClientPacketListener - 修饰符:
private final - 源码定位:
L77 - 说明:
TODO
- 类型:
-
destroyBlockPos- 类型:
BlockPos - 修饰符:
private - 源码定位:
L78 - 说明:
TODO
- 类型:
-
destroyingItem- 类型:
ItemStack - 修饰符:
private - 源码定位:
L79 - 说明:
TODO
- 类型:
-
destroyProgress- 类型:
float - 修饰符:
private - 源码定位:
L80 - 说明:
TODO
- 类型:
-
destroyTicks- 类型:
float - 修饰符:
private - 源码定位:
L81 - 说明:
TODO
- 类型:
-
destroyDelay- 类型:
int - 修饰符:
private - 源码定位:
L82 - 说明:
TODO
- 类型:
-
isDestroying- 类型:
boolean - 修饰符:
private - 源码定位:
L83 - 说明:
TODO
- 类型:
-
localPlayerMode- 类型:
GameType - 修饰符:
private - 源码定位:
L84 - 说明:
TODO
- 类型:
-
previousLocalPlayerMode- 类型:
GameType - 修饰符:
private - 源码定位:
L85 - 说明:
TODO
- 类型:
-
carriedIndex- 类型:
int - 修饰符:
private - 源码定位:
L86 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
public MultiPlayerGameMode(Minecraft minecraft, ClientPacketListener connection) @ L88
- 构造器名:MultiPlayerGameMode
- 源码定位:L88
- 修饰符:public
参数:
- minecraft: Minecraft
- connection: ClientPacketListener
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void adjustPlayer(Player player) @ L93
- 方法名:adjustPlayer
- 源码定位:L93
- 返回类型:void
- 修饰符:public
参数:
- player: Player
说明:
TODO
public void setLocalMode(GameType mode, GameType previousMode) @ L97
- 方法名:setLocalMode
- 源码定位:L97
- 返回类型:void
- 修饰符:public
参数:
- mode: GameType
- previousMode: GameType
说明:
TODO
public void setLocalMode(GameType mode) @ L103
- 方法名:setLocalMode
- 源码定位:L103
- 返回类型:void
- 修饰符:public
参数:
- mode: GameType
说明:
TODO
public boolean canHurtPlayer() @ L112
- 方法名:canHurtPlayer
- 源码定位:L112
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean destroyBlock(BlockPos pos) @ L116
- 方法名:destroyBlock
- 源码定位:L116
- 返回类型:boolean
- 修饰符:public
参数:
- pos: BlockPos
说明:
TODO
public boolean startDestroyBlock(BlockPos pos, Direction direction) @ L148
- 方法名:startDestroyBlock
- 源码定位:L148
- 返回类型:boolean
- 修饰符:public
参数:
- pos: BlockPos
- direction: Direction
说明:
TODO
public void stopDestroyBlock() @ L207
- 方法名:stopDestroyBlock
- 源码定位:L207
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean continueDestroyBlock(BlockPos pos, Direction direction) @ L224
- 方法名:continueDestroyBlock
- 源码定位:L224
- 返回类型:boolean
- 修饰符:public
参数:
- pos: BlockPos
- direction: Direction
说明:
TODO
private void startPrediction(ClientLevel level, PredictiveAction predictiveAction) @ L290
- 方法名:startPrediction
- 源码定位:L290
- 返回类型:void
- 修饰符:private
参数:
- level: ClientLevel
- predictiveAction: PredictiveAction
说明:
TODO
public void tick() @ L298
- 方法名:tick
- 源码定位:L298
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private boolean sameDestroyTarget(BlockPos pos) @ L307
- 方法名:sameDestroyTarget
- 源码定位:L307
- 返回类型:boolean
- 修饰符:private
参数:
- pos: BlockPos
说明:
TODO
private void ensureHasSentCarriedItem() @ L312
- 方法名:ensureHasSentCarriedItem
- 源码定位:L312
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
public InteractionResult useItemOn(LocalPlayer player, InteractionHand hand, BlockHitResult blockHit) @ L320
- 方法名:useItemOn
- 源码定位:L320
- 返回类型:InteractionResult
- 修饰符:public
参数:
- player: LocalPlayer
- hand: InteractionHand
- blockHit: BlockHitResult
说明:
TODO
private InteractionResult performUseItemOn(LocalPlayer player, InteractionHand hand, BlockHitResult blockHit) @ L334
- 方法名:performUseItemOn
- 源码定位:L334
- 返回类型:InteractionResult
- 修饰符:private
参数:
- player: LocalPlayer
- hand: InteractionHand
- blockHit: BlockHitResult
说明:
TODO
public InteractionResult useItem(Player player, InteractionHand hand) @ L379
- 方法名:useItem
- 源码定位:L379
- 返回类型:InteractionResult
- 修饰符:public
参数:
- player: Player
- hand: InteractionHand
说明:
TODO
public LocalPlayer createPlayer(ClientLevel level, StatsCounter stats, ClientRecipeBook recipeBook) @ L412
- 方法名:createPlayer
- 源码定位:L412
- 返回类型:LocalPlayer
- 修饰符:public
参数:
- level: ClientLevel
- stats: StatsCounter
- recipeBook: ClientRecipeBook
说明:
TODO
public LocalPlayer createPlayer(ClientLevel level, StatsCounter stats, ClientRecipeBook recipeBook, Input lastSentInput, boolean wasSprinting) @ L416
- 方法名:createPlayer
- 源码定位:L416
- 返回类型:LocalPlayer
- 修饰符:public
参数:
- level: ClientLevel
- stats: StatsCounter
- recipeBook: ClientRecipeBook
- lastSentInput: Input
- wasSprinting: boolean
说明:
TODO
public void attack(Player player, Entity entity) @ L420
- 方法名:attack
- 源码定位:L420
- 返回类型:void
- 修饰符:public
参数:
- player: Player
- entity: Entity
说明:
TODO
public void spectate(Entity entity) @ L427
- 方法名:spectate
- 源码定位:L427
- 返回类型:void
- 修饰符:public
参数:
- entity: Entity
说明:
TODO
public InteractionResult interact(Player player, Entity entity, EntityHitResult hitResult, InteractionHand hand) @ L431
- 方法名:interact
- 源码定位:L431
- 返回类型:InteractionResult
- 修饰符:public
参数:
- player: Player
- entity: Entity
- hitResult: EntityHitResult
- hand: InteractionHand
说明:
TODO
public void handleContainerInput(int containerId, int slotNum, int buttonNum, ContainerInput containerInput, Player player) @ L438
- 方法名:handleContainerInput
- 源码定位:L438
- 返回类型:void
- 修饰符:public
参数:
- containerId: int
- slotNum: int
- buttonNum: int
- containerInput: ContainerInput
- player: Player
说明:
TODO
public void handlePlaceRecipe(int containerId, RecipeDisplayId recipe, boolean useMaxItems) @ L478
- 方法名:handlePlaceRecipe
- 源码定位:L478
- 返回类型:void
- 修饰符:public
参数:
- containerId: int
- recipe: RecipeDisplayId
- useMaxItems: boolean
说明:
TODO
public void handleInventoryButtonClick(int containerId, int buttonId) @ L482
- 方法名:handleInventoryButtonClick
- 源码定位:L482
- 返回类型:void
- 修饰符:public
参数:
- containerId: int
- buttonId: int
说明:
TODO
public void handleCreativeModeItemAdd(ItemStack clicked, int slot) @ L486
- 方法名:handleCreativeModeItemAdd
- 源码定位:L486
- 返回类型:void
- 修饰符:public
参数:
- clicked: ItemStack
- slot: int
说明:
TODO
public void handleCreativeModeItemDrop(ItemStack clicked) @ L492
- 方法名:handleCreativeModeItemDrop
- 源码定位:L492
- 返回类型:void
- 修饰符:public
参数:
- clicked: ItemStack
说明:
TODO
public void releaseUsingItem(Player player) @ L504
- 方法名:releaseUsingItem
- 源码定位:L504
- 返回类型:void
- 修饰符:public
参数:
- player: Player
说明:
TODO
public void piercingAttack(PiercingWeapon weapon) @ L510
- 方法名:piercingAttack
- 源码定位:L510
- 返回类型:void
- 修饰符:public
参数:
- weapon: PiercingWeapon
说明:
TODO
public boolean hasExperience() @ L518
- 方法名:hasExperience
- 源码定位:L518
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean hasMissTime() @ L522
- 方法名:hasMissTime
- 源码定位:L522
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isServerControlledInventory() @ L526
- 方法名:isServerControlledInventory
- 源码定位:L526
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isSpectator() @ L530
- 方法名:isSpectator
- 源码定位:L530
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public GameType getPreviousPlayerMode() @ L534
- 方法名:getPreviousPlayerMode
- 源码定位:L534
- 返回类型:GameType
- 修饰符:public
参数:
- 无
说明:
TODO
public GameType getPlayerMode() @ L538
- 方法名:getPlayerMode
- 源码定位:L538
- 返回类型:GameType
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isDestroying() @ L542
- 方法名:isDestroying
- 源码定位:L542
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public int getDestroyStage() @ L546
- 方法名:getDestroyStage
- 源码定位:L546
- 返回类型:int
- 修饰符:public
参数:
- 无
说明:
TODO
public void handlePickItemFromBlock(BlockPos pos, boolean includeData) @ L550
- 方法名:handlePickItemFromBlock
- 源码定位:L550
- 返回类型:void
- 修饰符:public
参数:
- pos: BlockPos
- includeData: boolean
说明:
TODO
public void handlePickItemFromEntity(Entity entity, boolean includeData) @ L554
- 方法名:handlePickItemFromEntity
- 源码定位:L554
- 返回类型:void
- 修饰符:public
参数:
- entity: Entity
- includeData: boolean
说明:
TODO
public void handleSlotStateChanged(int slotId, int containerId, boolean newState) @ L558
- 方法名:handleSlotStateChanged
- 源码定位:L558
- 返回类型:void
- 修饰符:public
参数:
- slotId: int
- containerId: int
- newState: boolean
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class MultiPlayerGameMode {
private static final Logger LOGGER = LogUtils.getLogger();
private final Minecraft minecraft;
private final ClientPacketListener connection;
private BlockPos destroyBlockPos = new BlockPos(-1, -1, -1);
private ItemStack destroyingItem = ItemStack.EMPTY;
private float destroyProgress;
private float destroyTicks;
private int destroyDelay;
private boolean isDestroying;
private GameType localPlayerMode = GameType.DEFAULT_MODE;
private @Nullable GameType previousLocalPlayerMode;
private int carriedIndex;
public MultiPlayerGameMode(Minecraft minecraft, ClientPacketListener connection) {
this.minecraft = minecraft;
this.connection = connection;
}
public void adjustPlayer(Player player) {
this.localPlayerMode.updatePlayerAbilities(player.getAbilities());
}
public void setLocalMode(GameType mode, @Nullable GameType previousMode) {
this.localPlayerMode = mode;
this.previousLocalPlayerMode = previousMode;
this.localPlayerMode.updatePlayerAbilities(this.minecraft.player.getAbilities());
}
public void setLocalMode(GameType mode) {
if (mode != this.localPlayerMode) {
this.previousLocalPlayerMode = this.localPlayerMode;
}
this.localPlayerMode = mode;
this.localPlayerMode.updatePlayerAbilities(this.minecraft.player.getAbilities());
}
public boolean canHurtPlayer() {
return this.localPlayerMode.isSurvival();
}
public boolean destroyBlock(BlockPos pos) {
if (this.minecraft.player.blockActionRestricted(this.minecraft.level, pos, this.localPlayerMode)) {
return false;
} else {
Level level = this.minecraft.level;
BlockState oldState = level.getBlockState(pos);
if (!this.minecraft.player.getMainHandItem().canDestroyBlock(oldState, level, pos, this.minecraft.player)) {
return false;
} else {
Block oldBlock = oldState.getBlock();
if (oldBlock instanceof GameMasterBlock && !this.minecraft.player.canUseGameMasterBlocks()) {
return false;
} else if (oldState.isAir()) {
return false;
} else {
oldBlock.playerWillDestroy(level, pos, oldState, this.minecraft.player);
FluidState fluidState = level.getFluidState(pos);
boolean changed = level.setBlock(pos, fluidState.createLegacyBlock(), 11);
if (changed) {
oldBlock.destroy(level, pos, oldState);
}
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.error("client broke {} {} -> {}", pos, oldState, level.getBlockState(pos));
}
return changed;
}
}
}
}
public boolean startDestroyBlock(BlockPos pos, Direction direction) {
if (this.minecraft.player.blockActionRestricted(this.minecraft.level, pos, this.localPlayerMode)) {
return false;
} else if (!this.minecraft.level.getWorldBorder().isWithinBounds(pos)) {
return false;
} else {
if (this.minecraft.player.getAbilities().instabuild) {
BlockState state = this.minecraft.level.getBlockState(pos);
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, pos, state, 1.0F);
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("Creative start {} {}", pos, state);
}
this.startPrediction(this.minecraft.level, sequence -> {
this.destroyBlock(pos);
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence);
});
this.destroyDelay = 5;
} else if (!this.isDestroying || !this.sameDestroyTarget(pos)) {
if (this.isDestroying) {
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("Abort old break {} {}", pos, this.minecraft.level.getBlockState(pos));
}
this.connection
.send(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, this.destroyBlockPos, direction));
}
BlockState state = this.minecraft.level.getBlockState(pos);
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, pos, state, 0.0F);
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("Start break {} {}", pos, state);
}
this.startPrediction(this.minecraft.level, sequence -> {
boolean notAir = !state.isAir();
if (notAir && this.destroyProgress == 0.0F) {
state.attack(this.minecraft.level, pos, this.minecraft.player);
}
if (notAir && state.getDestroyProgress(this.minecraft.player, this.minecraft.player.level(), pos) >= 1.0F) {
this.destroyBlock(pos);
} else {
this.isDestroying = true;
this.destroyBlockPos = pos;
this.destroyingItem = this.minecraft.player.getMainHandItem();
this.destroyProgress = 0.0F;
this.destroyTicks = 0.0F;
this.minecraft.level.destroyBlockProgress(this.minecraft.player.getId(), this.destroyBlockPos, this.getDestroyStage());
}
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence);
});
}
return true;
}
}
public void stopDestroyBlock() {
if (this.isDestroying) {
BlockState state = this.minecraft.level.getBlockState(this.destroyBlockPos);
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, this.destroyBlockPos, state, -1.0F);
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("Stop dest {} {}", this.destroyBlockPos, state);
}
this.connection
.send(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, this.destroyBlockPos, Direction.DOWN));
this.isDestroying = false;
this.destroyProgress = 0.0F;
this.minecraft.level.destroyBlockProgress(this.minecraft.player.getId(), this.destroyBlockPos, -1);
this.minecraft.player.resetAttackStrengthTicker();
}
}
public boolean continueDestroyBlock(BlockPos pos, Direction direction) {
this.ensureHasSentCarriedItem();
if (this.destroyDelay > 0) {
this.destroyDelay--;
return true;
} else if (this.minecraft.player.getAbilities().instabuild && this.minecraft.level.getWorldBorder().isWithinBounds(pos)) {
this.destroyDelay = 5;
BlockState state = this.minecraft.level.getBlockState(pos);
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, pos, state, 1.0F);
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("Creative cont {} {}", pos, state);
}
this.startPrediction(this.minecraft.level, sequence -> {
this.destroyBlock(pos);
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence);
});
return true;
} else if (this.sameDestroyTarget(pos)) {
BlockState state = this.minecraft.level.getBlockState(pos);
if (state.isAir()) {
this.isDestroying = false;
return false;
} else {
this.destroyProgress = this.destroyProgress + state.getDestroyProgress(this.minecraft.player, this.minecraft.player.level(), pos);
if (this.destroyTicks % 4.0F == 0.0F) {
SoundType soundType = state.getSoundType();
this.minecraft
.getSoundManager()
.play(
new SimpleSoundInstance(
soundType.getHitSound(),
SoundSource.BLOCKS,
(soundType.getVolume() + 1.0F) / 8.0F,
soundType.getPitch() * 0.5F,
SoundInstance.createUnseededRandom(),
pos
)
);
}
this.destroyTicks++;
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, pos, state, Mth.clamp(this.destroyProgress, 0.0F, 1.0F));
if (this.destroyProgress >= 1.0F) {
this.isDestroying = false;
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("Finished breaking {} {}", pos, state);
}
this.startPrediction(this.minecraft.level, sequence -> {
this.destroyBlock(pos);
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK, pos, direction, sequence);
});
this.destroyProgress = 0.0F;
this.destroyTicks = 0.0F;
this.destroyDelay = 5;
}
this.minecraft.level.destroyBlockProgress(this.minecraft.player.getId(), this.destroyBlockPos, this.getDestroyStage());
return true;
}
} else {
return this.startDestroyBlock(pos, direction);
}
}
private void startPrediction(ClientLevel level, PredictiveAction predictiveAction) {
try (BlockStatePredictionHandler prediction = level.getBlockStatePredictionHandler().startPredicting()) {
int sequence = prediction.currentSequence();
Packet<ServerGamePacketListener> packetConcludingPrediction = predictiveAction.predict(sequence);
this.connection.send(packetConcludingPrediction);
}
}
public void tick() {
this.ensureHasSentCarriedItem();
if (this.connection.getConnection().isConnected()) {
this.connection.getConnection().tick();
} else {
this.connection.getConnection().handleDisconnection();
}
}
private boolean sameDestroyTarget(BlockPos pos) {
ItemStack selected = this.minecraft.player.getMainHandItem();
return pos.equals(this.destroyBlockPos) && ItemStack.isSameItemSameComponents(selected, this.destroyingItem);
}
private void ensureHasSentCarriedItem() {
int index = this.minecraft.player.getInventory().getSelectedSlot();
if (index != this.carriedIndex) {
this.carriedIndex = index;
this.connection.send(new ServerboundSetCarriedItemPacket(this.carriedIndex));
}
}
public InteractionResult useItemOn(LocalPlayer player, InteractionHand hand, BlockHitResult blockHit) {
this.ensureHasSentCarriedItem();
if (!this.minecraft.level.getWorldBorder().isWithinBounds(blockHit.getBlockPos())) {
return InteractionResult.FAIL;
} else {
MutableObject<InteractionResult> result = new MutableObject<>();
this.startPrediction(this.minecraft.level, sequence -> {
result.setValue(this.performUseItemOn(player, hand, blockHit));
return new ServerboundUseItemOnPacket(hand, blockHit, sequence);
});
return result.get();
}
}
private InteractionResult performUseItemOn(LocalPlayer player, InteractionHand hand, BlockHitResult blockHit) {
BlockPos pos = blockHit.getBlockPos();
ItemStack itemStack = player.getItemInHand(hand);
if (this.localPlayerMode == GameType.SPECTATOR) {
return InteractionResult.CONSUME;
} else {
boolean haveSomethingInOurHands = !player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty();
boolean suppressUsingBlock = player.isSecondaryUseActive() && haveSomethingInOurHands;
if (!suppressUsingBlock) {
BlockState blockState = this.minecraft.level.getBlockState(pos);
if (!this.connection.isFeatureEnabled(blockState.getBlock().requiredFeatures())) {
return InteractionResult.FAIL;
}
InteractionResult itemUse = blockState.useItemOn(player.getItemInHand(hand), this.minecraft.level, player, hand, blockHit);
if (itemUse.consumesAction()) {
return itemUse;
}
if (itemUse instanceof InteractionResult.TryEmptyHandInteraction && hand == InteractionHand.MAIN_HAND) {
InteractionResult use = blockState.useWithoutItem(this.minecraft.level, player, blockHit);
if (use.consumesAction()) {
return use;
}
}
}
if (!itemStack.isEmpty() && !player.getCooldowns().isOnCooldown(itemStack)) {
UseOnContext context = new UseOnContext(player, hand, blockHit);
InteractionResult success;
if (player.hasInfiniteMaterials()) {
int count = itemStack.getCount();
success = itemStack.useOn(context);
itemStack.setCount(count);
} else {
success = itemStack.useOn(context);
}
return success;
} else {
return InteractionResult.PASS;
}
}
}
public InteractionResult useItem(Player player, InteractionHand hand) {
if (this.localPlayerMode == GameType.SPECTATOR) {
return InteractionResult.PASS;
} else {
this.ensureHasSentCarriedItem();
MutableObject<InteractionResult> interactionResult = new MutableObject<>();
this.startPrediction(this.minecraft.level, sequence -> {
ServerboundUseItemPacket packet = new ServerboundUseItemPacket(hand, sequence, player.getYRot(), player.getXRot());
ItemStack itemStack = player.getItemInHand(hand);
if (player.getCooldowns().isOnCooldown(itemStack)) {
interactionResult.setValue(InteractionResult.PASS);
return packet;
} else {
InteractionResult resultHolder = itemStack.use(this.minecraft.level, player, hand);
ItemStack result;
if (resultHolder instanceof InteractionResult.Success success) {
result = Objects.requireNonNullElseGet(success.heldItemTransformedTo(), () -> player.getItemInHand(hand));
} else {
result = player.getItemInHand(hand);
}
if (result != itemStack) {
player.setItemInHand(hand, result);
}
interactionResult.setValue(resultHolder);
return packet;
}
});
return interactionResult.get();
}
}
public LocalPlayer createPlayer(ClientLevel level, StatsCounter stats, ClientRecipeBook recipeBook) {
return this.createPlayer(level, stats, recipeBook, Input.EMPTY, false);
}
public LocalPlayer createPlayer(ClientLevel level, StatsCounter stats, ClientRecipeBook recipeBook, Input lastSentInput, boolean wasSprinting) {
return new LocalPlayer(this.minecraft, level, this.connection, stats, recipeBook, lastSentInput, wasSprinting, this.minecraft.computeChatAbilities());
}
public void attack(Player player, Entity entity) {
this.ensureHasSentCarriedItem();
this.connection.send(new ServerboundAttackPacket(entity.getId()));
player.attack(entity);
player.resetAttackStrengthTicker();
}
public void spectate(Entity entity) {
this.connection.send(new ServerboundSpectateEntityPacket(entity.getId()));
}
public InteractionResult interact(Player player, Entity entity, EntityHitResult hitResult, InteractionHand hand) {
this.ensureHasSentCarriedItem();
Vec3 location = hitResult.getLocation().subtract(entity.getX(), entity.getY(), entity.getZ());
this.connection.send(new ServerboundInteractPacket(entity.getId(), hand, location, player.isShiftKeyDown()));
return (InteractionResult)(this.localPlayerMode == GameType.SPECTATOR ? InteractionResult.PASS : player.interactOn(entity, hand, location));
}
public void handleContainerInput(int containerId, int slotNum, int buttonNum, ContainerInput containerInput, Player player) {
AbstractContainerMenu containerMenu = player.containerMenu;
if (containerId != containerMenu.containerId) {
LOGGER.warn("Ignoring click in mismatching container. Click in {}, player has {}.", containerId, containerMenu.containerId);
} else {
NonNullList<Slot> slots = containerMenu.slots;
int slotCount = slots.size();
List<ItemStack> itemsBeforeClick = Lists.newArrayListWithCapacity(slotCount);
for (Slot slot : slots) {
itemsBeforeClick.add(slot.getItem().copy());
}
containerMenu.clicked(slotNum, buttonNum, containerInput, player);
Int2ObjectMap<HashedStack> changedSlots = new Int2ObjectOpenHashMap<>();
for (int i = 0; i < slotCount; i++) {
ItemStack before = itemsBeforeClick.get(i);
ItemStack after = slots.get(i).getItem();
if (!ItemStack.matches(before, after)) {
changedSlots.put(i, HashedStack.create(after, this.connection.decoratedHashOpsGenenerator()));
}
}
HashedStack carriedItem = HashedStack.create(containerMenu.getCarried(), this.connection.decoratedHashOpsGenenerator());
this.connection
.send(
new ServerboundContainerClickPacket(
containerId,
containerMenu.getStateId(),
Shorts.checkedCast(slotNum),
SignedBytes.checkedCast(buttonNum),
containerInput,
changedSlots,
carriedItem
)
);
}
}
public void handlePlaceRecipe(int containerId, RecipeDisplayId recipe, boolean useMaxItems) {
this.connection.send(new ServerboundPlaceRecipePacket(containerId, recipe, useMaxItems));
}
public void handleInventoryButtonClick(int containerId, int buttonId) {
this.connection.send(new ServerboundContainerButtonClickPacket(containerId, buttonId));
}
public void handleCreativeModeItemAdd(ItemStack clicked, int slot) {
if (this.minecraft.player.hasInfiniteMaterials() && this.connection.isFeatureEnabled(clicked.getItem().requiredFeatures())) {
this.connection.send(new ServerboundSetCreativeModeSlotPacket(slot, clicked));
}
}
public void handleCreativeModeItemDrop(ItemStack clicked) {
boolean hasOtherInventoryOpen = this.minecraft.screen instanceof AbstractContainerScreen
&& !(this.minecraft.screen instanceof CreativeModeInventoryScreen);
if (this.minecraft.player.hasInfiniteMaterials()
&& !hasOtherInventoryOpen
&& !clicked.isEmpty()
&& this.connection.isFeatureEnabled(clicked.getItem().requiredFeatures())) {
this.connection.send(new ServerboundSetCreativeModeSlotPacket(-1, clicked));
this.minecraft.player.getDropSpamThrottler().increment();
}
}
public void releaseUsingItem(Player player) {
this.ensureHasSentCarriedItem();
this.connection.send(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.RELEASE_USE_ITEM, BlockPos.ZERO, Direction.DOWN));
player.releaseUsingItem();
}
public void piercingAttack(PiercingWeapon weapon) {
this.ensureHasSentCarriedItem();
this.connection.send(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.STAB, BlockPos.ZERO, Direction.DOWN));
this.minecraft.player.onAttack();
this.minecraft.player.postPiercingAttack();
weapon.makeSound(this.minecraft.player);
}
public boolean hasExperience() {
return this.localPlayerMode.isSurvival();
}
public boolean hasMissTime() {
return !this.localPlayerMode.isCreative();
}
public boolean isServerControlledInventory() {
return this.minecraft.player.isPassenger() && this.minecraft.player.getVehicle() instanceof HasCustomInventoryScreen;
}
public boolean isSpectator() {
return this.localPlayerMode == GameType.SPECTATOR;
}
public @Nullable GameType getPreviousPlayerMode() {
return this.previousLocalPlayerMode;
}
public GameType getPlayerMode() {
return this.localPlayerMode;
}
public boolean isDestroying() {
return this.isDestroying;
}
public int getDestroyStage() {
return this.destroyProgress > 0.0F ? (int)(this.destroyProgress * 10.0F) : -1;
}
public void handlePickItemFromBlock(BlockPos pos, boolean includeData) {
this.connection.send(new ServerboundPickItemFromBlockPacket(pos, includeData));
}
public void handlePickItemFromEntity(Entity entity, boolean includeData) {
this.connection.send(new ServerboundPickItemFromEntityPacket(entity.getId(), includeData));
}
public void handleSlotStateChanged(int slotId, int containerId, boolean newState) {
this.connection.send(new ServerboundContainerSlotStateChangedPacket(slotId, containerId, newState));
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/构造调用/返回值 - 关联成员:
LocalPlayer()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
SimpleSoundInstance()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SoundInstance.createUnseededRandom()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用 - 关联成员:
BlockPos()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
HashedStack.create()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ServerboundAttackPacket()
- 引用位置:
-
ServerboundContainerButtonClickPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundContainerButtonClickPacket()
- 引用位置:
-
ServerboundContainerClickPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundContainerClickPacket()
- 引用位置:
-
ServerboundContainerSlotStateChangedPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundContainerSlotStateChangedPacket()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ServerboundInteractPacket()
- 引用位置:
-
ServerboundPickItemFromBlockPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundPickItemFromBlockPacket()
- 引用位置:
-
ServerboundPickItemFromEntityPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundPickItemFromEntityPacket()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ServerboundPlaceRecipePacket()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ServerboundPlayerActionPacket()
- 引用位置:
-
ServerboundSetCarriedItemPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundSetCarriedItemPacket()
- 引用位置:
-
ServerboundSetCreativeModeSlotPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundSetCreativeModeSlotPacket()
- 引用位置:
-
ServerboundSpectateEntityPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundSpectateEntityPacket()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ServerboundUseItemOnPacket()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ServerboundUseItemPacket()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.clamp()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/方法调用 - 关联成员:
ItemStack.isSameItemSameComponents(), ItemStack.matches()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
UseOnContext()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置: