Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions src/main/java/cn/nukkit/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
Expand Down Expand Up @@ -265,6 +266,7 @@ public class Player extends EntityHuman implements CommandSender, InventoryHolde

private int exp = 0;
private int expLevel = 0;
private int expSeed;

protected PlayerFood foodData = null;

Expand Down Expand Up @@ -2390,6 +2392,18 @@ private static EntityInteractable getEntityAtPosition(Entity[] nearbyEntities, i
return null;
}

public int getEnchantmentSeed() {
return this.expSeed;
}

public void setEnchantmentSeed(int seed) {
this.expSeed = seed;
}

public int generateEnchantmentSeed() {
return ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE);
}

public void checkNetwork() {
if (this.protocol < ProtocolInfo.v1_16_100 && !this.isOnline()) {
return;
Expand Down Expand Up @@ -2442,11 +2456,15 @@ protected void processLogin() {
if (!this.server.isWhitelisted(lowerName)) {
this.kick(PlayerKickEvent.Reason.NOT_WHITELISTED, server.whitelistReason);
return;
} else if (this.isBanned()) {
}

if (this.isBanned()) {
String reason = this.server.getNameBans().getEntires().get(lowerName).getReason();
this.kick(PlayerKickEvent.Reason.NAME_BANNED, "You are banned!" + (reason.isEmpty() ? "" : (" Reason: " + reason)));
return;
} else if (!server.strongIPBans && this.server.getIPBans().isBanned(this.getAddress())) {
}

if (!server.strongIPBans && this.server.getIPBans().isBanned(this.getAddress())) {
this.kick(PlayerKickEvent.Reason.IP_BANNED, "Your IP is banned!");
return;
}
Expand Down Expand Up @@ -2554,7 +2572,6 @@ protected void processLogin() {
this.fogStack.add(i, new PlayerFogPacket.Fog(Identifier.tryParse(fogIdentifiers.get(i).data), userProvidedFogIds.get(i).data));
}


for (Tag achievement : nbt.getCompound("Achievements").getAllTags()) {
if (!(achievement instanceof ByteTag)) {
continue;
Expand Down Expand Up @@ -2593,6 +2610,13 @@ protected void processLogin() {
this.namedTag.putFloat("foodSaturationLevel", 20);
}

if (this.namedTag.contains("xpSeed")) {
this.expSeed = this.namedTag.getInt("xpSeed");
} else {
this.expSeed = this.generateEnchantmentSeed();
this.namedTag.putInt("xpSeed", this.expSeed);
}

this.foodData = new PlayerFood(this, this.namedTag.getInt("foodLevel"), this.namedTag.getFloat("foodSaturationLevel"));

if (this.isSpectator()) {
Expand Down Expand Up @@ -5316,9 +5340,9 @@ public void save(boolean async) {
namedTag.remove("SpawnBlockPositionX").remove("SpawnBlockPositionY").remove("SpawnBlockPositionZ").remove("SpawnBlockLevel");
} else if (spawnBlockPosition.isValid()) {
namedTag.putInt("SpawnBlockPositionX", spawnBlockPosition.getFloorX())
.putInt("SpawnBlockPositionY", spawnBlockPosition.getFloorY())
.putInt("SpawnBlockPositionZ", spawnBlockPosition.getFloorZ())
.putString("SpawnBlockLevel", this.spawnBlockPosition.getLevel().getFolderName());
.putInt("SpawnBlockPositionY", spawnBlockPosition.getFloorY())
.putInt("SpawnBlockPositionZ", spawnBlockPosition.getFloorZ())
.putString("SpawnBlockLevel", this.spawnBlockPosition.getLevel().getFolderName());
}

CompoundTag achievements = new CompoundTag();
Expand All @@ -5339,6 +5363,7 @@ public void save(boolean async) {
this.namedTag.putInt("foodLevel", this.foodData.getLevel());
this.namedTag.putFloat("foodSaturationLevel", this.foodData.getFoodSaturationLevel());

this.namedTag.putInt("xpSeed", this.expSeed);
this.namedTag.putInt("TimeSinceRest", this.timeSinceRest);

ListTag<StringTag> fogIdentifiers = new ListTag<>("fogIdentifiers");
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/cn/nukkit/block/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ public int getItemId() {
}

return id;
}
}

/**
* The full id is a combination of the id and data.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cn.nukkit.event.player;

import cn.nukkit.Player;
import cn.nukkit.event.Cancellable;
import cn.nukkit.event.HandlerList;
import cn.nukkit.inventory.EnchantInventory;
import cn.nukkit.network.protocol.PlayerEnchantOptionsPacket;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.List;

@EqualsAndHashCode(callSuper = true)
@Data
public class PlayerEnchantOptionsRequestEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();

private EnchantInventory table;
private List<PlayerEnchantOptionsPacket.EnchantOptionData> options;

public PlayerEnchantOptionsRequestEvent(Player player, EnchantInventory table, List<PlayerEnchantOptionsPacket.EnchantOptionData> options) {
this.player = player;
this.table = table;
this.options = options;
}
}
31 changes: 30 additions & 1 deletion src/main/java/cn/nukkit/inventory/EnchantInventory.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
package cn.nukkit.inventory;

import cn.nukkit.Player;
import cn.nukkit.event.player.PlayerEnchantOptionsRequestEvent;
import cn.nukkit.item.Item;
import cn.nukkit.item.enchantment.EnchantmentHelper;
import cn.nukkit.level.Position;
import cn.nukkit.network.protocol.PlayerEnchantOptionsPacket;
import lombok.Getter;

import java.util.Collections;
import java.util.List;

/**
* @author MagicDroidX
* Nukkit Project
*/
public class EnchantInventory extends FakeBlockUIComponent {

public static final int ENCHANT_INPUT_ITEM_UI_SLOT = 14;
public static final int ENCHANT_REAGENT_UI_SLOT = 15;

@Getter
private List<PlayerEnchantOptionsPacket.EnchantOptionData> options = Collections.emptyList();

public EnchantInventory(PlayerUIInventory playerUI, Position position) {
super(playerUI, InventoryType.ENCHANT_TABLE, 14, position);
}
Expand All @@ -36,6 +45,26 @@ public void onClose(Player who) {
who.resetCraftingGridType();
}

@Override
public void onSlotChange(int index, Item before, boolean send) {
if (index == 0) {
for (final Player viewer : this.getViewers()) {
List<PlayerEnchantOptionsPacket.EnchantOptionData> options = EnchantmentHelper.getEnchantOptions(this.getHolder(), this.getInputSlot(), viewer.getEnchantmentSeed());
PlayerEnchantOptionsRequestEvent event = new PlayerEnchantOptionsRequestEvent(viewer, this, options);

if (!event.isCancelled() && !event.getOptions().isEmpty()) {
this.options = event.getOptions();

PlayerEnchantOptionsPacket pk = new PlayerEnchantOptionsPacket();
pk.options = event.getOptions();
viewer.dataPacket(pk);
}
}
}

super.onSlotChange(index, before, false);
}

public Item getInputSlot() {
return this.getItem(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import cn.nukkit.Player;
import cn.nukkit.event.inventory.EnchantItemEvent;
import cn.nukkit.inventory.EnchantInventory;
import cn.nukkit.inventory.Inventory;
import cn.nukkit.inventory.transaction.action.EnchantingAction;
import cn.nukkit.inventory.transaction.action.InventoryAction;
import cn.nukkit.inventory.transaction.action.SlotChangeAction;
import cn.nukkit.item.Item;
import cn.nukkit.item.enchantment.Enchantment;
import cn.nukkit.network.protocol.PlayerEnchantOptionsPacket;
import cn.nukkit.network.protocol.types.NetworkInventoryAction;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -17,7 +18,7 @@
@Getter
@Setter
public class EnchantTransaction extends InventoryTransaction {

private EnchantInventory inv;
private Item inputItem;
private Item outputItem;
private int cost = -1;
Expand All @@ -35,16 +36,19 @@ public EnchantTransaction(Player source, List<InventoryAction> actions) {

@Override
public boolean canExecute() {
Inventory inv = getSource().getWindowById(Player.ENCHANT_WINDOW_ID);
if (inv == null) return false;
EnchantInventory eInv = (EnchantInventory) inv;
if (!getSource().isCreative()) {
if (cost == -1 || !eInv.getReagentSlot().equals(Item.get(Item.DYE, 4), true, false) || eInv.getReagentSlot().count < cost)
if (!(this.getSource().getWindowById(Player.ENCHANT_WINDOW_ID) instanceof final EnchantInventory inv)) {
return false;
}

if (!this.getSource().isCreative()) {
if (cost == -1 || !inv.getReagentSlot().equals(Item.get(Item.DYE, 4), true, false) || inv.getReagentSlot().count < cost) {
return false;
}
}

return inputItem != null && outputItem != null
&& inputItem.equals(eInv.getInputSlot(), true, true)
&& this.checkEnchantValid();
&& inputItem.equals(inv.getInputSlot(), true, true)
&& this.checkEnchantValid(inv);
}

@Override
Expand All @@ -55,7 +59,7 @@ public boolean execute() {
this.sendInventories();
return false;
}
EnchantInventory inv = (EnchantInventory) getSource().getWindowById(Player.ENCHANT_WINDOW_ID);
EnchantInventory inv = (EnchantInventory) this.getSource().getWindowById(Player.ENCHANT_WINDOW_ID);
EnchantItemEvent ev = new EnchantItemEvent(inv, inputItem, outputItem, cost, source);
source.getServer().getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
Expand All @@ -80,8 +84,10 @@ public boolean execute() {
}

if (!source.isCreative()) {
source.setEnchantmentSeed(source.generateEnchantmentSeed());
source.setExperience(source.getExperience(), source.getExperienceLevel() - ev.getXpCost());
}

return true;
}

Expand All @@ -90,21 +96,18 @@ public void addAction(InventoryAction action) {
super.addAction(action);
if (action instanceof EnchantingAction) {
switch (((EnchantingAction) action).getType()) {
case NetworkInventoryAction.SOURCE_TYPE_ENCHANT_INPUT:
case NetworkInventoryAction.SOURCE_TYPE_ENCHANT_INPUT ->
this.inputItem = action.getTargetItem(); // Input sent as newItem
break;
case NetworkInventoryAction.SOURCE_TYPE_ENCHANT_OUTPUT:
case NetworkInventoryAction.SOURCE_TYPE_ENCHANT_OUTPUT ->
this.outputItem = action.getSourceItem(); // Output sent as oldItem
break;
case NetworkInventoryAction.SOURCE_TYPE_ENCHANT_MATERIAL:
case NetworkInventoryAction.SOURCE_TYPE_ENCHANT_MATERIAL -> {
if (action.getTargetItem().equals(Item.get(Item.AIR), false, false)) {
this.cost = action.getSourceItem().count;
} else {
this.cost = action.getSourceItem().count - action.getTargetItem().count;
}
break;
}
}

}
}

Expand All @@ -115,14 +118,17 @@ public boolean checkForEnchantPart(List<InventoryAction> actions) {
return false;
}

public boolean checkEnchantValid() {
if (this.inputItem.getId() != this.outputItem.getId()
|| this.inputItem.getCount() != this.outputItem.getCount()) {
return false;
public boolean checkEnchantValid(EnchantInventory inv) {
for (final PlayerEnchantOptionsPacket.EnchantOptionData option : inv.getOptions()) {
for (final Enchantment ench : option.enchantments()) {
if (outputItem.hasEnchantment(ench.getId())) {
return outputItem.getId() == inputItem.getId() && outputItem.getDamage() == inputItem.getDamage();
}
}
}

//TODO 检查附魔
System.out.println(inv.getOptions());

return true;
return false;
}
}
Loading