mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-22 18:56:15 +00:00
implement simple drop system
This commit is contained in:
parent
9fc8cc1c17
commit
8b614d8df8
14
data/Drop.json
Normal file
14
data/Drop.json
Normal file
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"monsterId": 20010201,
|
||||
"dropDataList": [
|
||||
{
|
||||
"itemId": 223,
|
||||
"minCount": 1,
|
||||
"maxCount": 100,
|
||||
"minWeight": 0,
|
||||
"maxWeight": 10000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
57
src/main/java/emu/grasscutter/game/drop/DropData.java
Normal file
57
src/main/java/emu/grasscutter/game/drop/DropData.java
Normal file
@ -0,0 +1,57 @@
|
||||
package emu.grasscutter.game.drop;
|
||||
|
||||
public class DropData {
|
||||
private int minWeight;
|
||||
private int maxWeight;
|
||||
private int itemId;
|
||||
private int minCount;
|
||||
private int maxCount;
|
||||
private boolean share = false;
|
||||
|
||||
public int getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
public void setItemId(int itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
public int getMinCount() {
|
||||
return minCount;
|
||||
}
|
||||
|
||||
|
||||
public int getMaxCount() {
|
||||
return maxCount;
|
||||
}
|
||||
|
||||
|
||||
public int getMinWeight() {
|
||||
return minWeight;
|
||||
}
|
||||
|
||||
public int getMaxWeight() {
|
||||
return maxWeight;
|
||||
}
|
||||
|
||||
|
||||
public boolean isShare() {
|
||||
return share;
|
||||
}
|
||||
|
||||
public void setIsShare(boolean share) {
|
||||
this.share = share;
|
||||
}
|
||||
|
||||
public boolean isGive() {
|
||||
return give;
|
||||
}
|
||||
|
||||
private boolean give = false;
|
||||
|
||||
public boolean isExp() {
|
||||
return exp;
|
||||
}
|
||||
|
||||
private boolean exp = false;
|
||||
}
|
16
src/main/java/emu/grasscutter/game/drop/DropInfo.java
Normal file
16
src/main/java/emu/grasscutter/game/drop/DropInfo.java
Normal file
@ -0,0 +1,16 @@
|
||||
package emu.grasscutter.game.drop;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DropInfo {
|
||||
public int getMonsterId() {
|
||||
return monsterId;
|
||||
}
|
||||
|
||||
public List<DropData> getDropDataList() {
|
||||
return dropDataList;
|
||||
}
|
||||
|
||||
private int monsterId;
|
||||
private List<DropData> dropDataList;
|
||||
}
|
99
src/main/java/emu/grasscutter/game/drop/DropManager.java
Normal file
99
src/main/java/emu/grasscutter/game/drop/DropManager.java
Normal file
@ -0,0 +1,99 @@
|
||||
package emu.grasscutter.game.drop;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.def.ItemData;
|
||||
import emu.grasscutter.game.entity.EntityItem;
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class DropManager {
|
||||
public GameServer getGameServer() {
|
||||
return gameServer;
|
||||
}
|
||||
|
||||
private final GameServer gameServer;
|
||||
|
||||
public Int2ObjectMap<List<DropData>> getDropData() {
|
||||
return dropData;
|
||||
}
|
||||
|
||||
private final Int2ObjectMap<List<DropData>> dropData;
|
||||
|
||||
public DropManager(GameServer gameServer) {
|
||||
this.gameServer = gameServer;
|
||||
this.dropData = new Int2ObjectOpenHashMap<>();
|
||||
this.load();
|
||||
}
|
||||
|
||||
public synchronized void load() {
|
||||
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Drop.json")) {
|
||||
getDropData().clear();
|
||||
List<DropInfo> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, DropInfo.class).getType());
|
||||
if(banners.size() > 0) {
|
||||
for (DropInfo di : banners) {
|
||||
getDropData().put(di.getMonsterId(), di.getDropDataList());
|
||||
}
|
||||
Grasscutter.getLogger().info("Drop data successfully loaded.");
|
||||
} else {
|
||||
Grasscutter.getLogger().error("Unable to load drop data. Drop data size is 0.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void processDrop(DropData dd, EntityMonster em, Player gp) {
|
||||
int target = Utils.randomRange(1, 10000);
|
||||
if (target >= dd.getMinWeight() && target < dd.getMaxWeight()) {
|
||||
ItemData itemData = GameData.getItemDataMap().get(dd.getItemId());
|
||||
int num = Utils.randomRange(dd.getMinCount(), dd.getMaxCount());
|
||||
if (!dd.isGive()) {
|
||||
if (itemData.isEquip()) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
float range = (5f + (.1f * num));
|
||||
Position pos = em.getPosition().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2));
|
||||
EntityItem entity = new EntityItem(em.getScene(), gp, itemData, pos, num, dd.isShare());
|
||||
if (!dd.isShare())
|
||||
em.getScene().addEntityToSingleClient(gp, entity);
|
||||
else
|
||||
em.getScene().addEntity(entity);
|
||||
}
|
||||
} else {
|
||||
Position pos = em.getPosition().clone().addY(3f);
|
||||
EntityItem entity = new EntityItem(em.getScene(), gp, itemData, pos, num, dd.isShare());
|
||||
if (!dd.isShare())
|
||||
em.getScene().addEntityToSingleClient(gp, entity);
|
||||
else
|
||||
em.getScene().addEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void callDrop(EntityMonster em) {
|
||||
int id = em.getMonsterData().getId();
|
||||
if (getDropData().containsKey(id)) {
|
||||
for (DropData dd : getDropData().get(id)) {
|
||||
if (dd.isShare())
|
||||
processDrop(dd, em, null);
|
||||
else {
|
||||
for (Player gp : em.getScene().getPlayers()) {
|
||||
processDrop(dd, em, gp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||
@ -30,14 +29,30 @@ public class EntityItem extends EntityGadget {
|
||||
|
||||
private final GameItem item;
|
||||
private final long guid;
|
||||
|
||||
|
||||
private final boolean share;
|
||||
|
||||
public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count) {
|
||||
super(scene);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.pos = new Position(pos);
|
||||
this.rot = new Position();
|
||||
this.guid = player.getNextGameGuid();
|
||||
this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
|
||||
this.item = new GameItem(itemData, count);
|
||||
this.share = true;
|
||||
}
|
||||
|
||||
// In official game, some drop items are shared to all players, and some other items are independent to all players
|
||||
// For example, if you killed a monster in MP mode, all players could get drops but rarity and number of them are different
|
||||
// but if you broke regional mine, when someone picked up the drop then it disappeared
|
||||
public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) {
|
||||
super(scene);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.pos = new Position(pos);
|
||||
this.rot = new Position();
|
||||
this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
|
||||
this.item = new GameItem(itemData, count);
|
||||
this.share = share;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -81,6 +96,10 @@ public class EntityItem extends EntityGadget {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isShare() {
|
||||
return share;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
|
||||
|
@ -1,20 +1,16 @@
|
||||
package emu.grasscutter.game.player;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
import dev.morphia.annotations.*;
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.def.PlayerLevelData;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.avatar.AvatarProfileData;
|
||||
import emu.grasscutter.game.avatar.AvatarStorage;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.CoopRequest;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.avatar.AvatarProfileData;
|
||||
import emu.grasscutter.game.avatar.AvatarStorage;
|
||||
import emu.grasscutter.game.entity.EntityItem;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.friends.FriendsList;
|
||||
@ -34,7 +30,6 @@ import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage;
|
||||
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
|
||||
import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType;
|
||||
import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
|
||||
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
|
||||
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
|
||||
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
|
||||
import emu.grasscutter.net.proto.PlayerWorldLocationInfoOuterClass;
|
||||
@ -42,11 +37,12 @@ import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.DateHelper;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
@Entity(value = "players", useDiscriminator = false)
|
||||
@ -714,19 +710,30 @@ public class Player {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete
|
||||
entity.getScene().removeEntity(entity);
|
||||
|
||||
// Handle
|
||||
if (entity instanceof EntityItem) {
|
||||
// Pick item
|
||||
EntityItem drop = (EntityItem) entity;
|
||||
if (!drop.isShare()) // check drop owner to avoid someone picked up item in others' world
|
||||
{
|
||||
int dropOwner = (int)(drop.getGuid() >> 32);
|
||||
if (dropOwner != getUid())
|
||||
return;
|
||||
}
|
||||
entity.getScene().removeEntity(entity);
|
||||
GameItem item = new GameItem(drop.getItemData(), drop.getCount());
|
||||
// Add to inventory
|
||||
boolean success = getInventory().addItem(item, ActionReason.SubfieldDrop);
|
||||
if (success) {
|
||||
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
|
||||
|
||||
if (!drop.isShare()) // not shared drop
|
||||
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
|
||||
else
|
||||
this.getScene().broadcastPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
|
||||
}
|
||||
} else {
|
||||
// Delete directly
|
||||
entity.getScene().removeEntity(entity);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1,28 +1,12 @@
|
||||
package emu.grasscutter.game.world;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.danilopianini.util.SpatialIndex;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameDepot;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.def.MonsterData;
|
||||
import emu.grasscutter.data.def.SceneData;
|
||||
import emu.grasscutter.data.def.WorldLevelData;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.entity.EntityClientGadget;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.entity.*;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.player.TeamInfo;
|
||||
import emu.grasscutter.game.props.ClimateType;
|
||||
@ -37,10 +21,12 @@ import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneEntityDisappearNotify;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.danilopianini.util.SpatialIndex;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Scene {
|
||||
private final World world;
|
||||
@ -228,6 +214,11 @@ public class Scene {
|
||||
this.addEntityDirectly(entity);
|
||||
this.broadcastPacket(new PacketSceneEntityAppearNotify(entity));
|
||||
}
|
||||
|
||||
public synchronized void addEntityToSingleClient(Player player, GameEntity entity) {
|
||||
this.addEntityDirectly(entity);
|
||||
player.sendPacket(new PacketSceneEntityAppearNotify(entity));
|
||||
}
|
||||
|
||||
public synchronized void addEntities(Collection<GameEntity> entities) {
|
||||
for (GameEntity entity : entities) {
|
||||
@ -310,6 +301,12 @@ public class Scene {
|
||||
public void killEntity(GameEntity target, int attackerId) {
|
||||
// Packet
|
||||
this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD));
|
||||
|
||||
// Reward drop
|
||||
if (target instanceof EntityMonster) {
|
||||
Grasscutter.getGameServer().getDropManager().callDrop((EntityMonster) target);
|
||||
}
|
||||
|
||||
this.removeEntity(target);
|
||||
|
||||
// Death event
|
||||
|
@ -1,15 +1,11 @@
|
||||
package emu.grasscutter.server.game;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.CommandMap;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.drop.DropManager;
|
||||
import emu.grasscutter.game.dungeons.DungeonManager;
|
||||
import emu.grasscutter.game.gacha.GachaManager;
|
||||
import emu.grasscutter.game.managers.ChatManager;
|
||||
@ -27,6 +23,11 @@ import emu.grasscutter.server.event.internal.ServerStartEvent;
|
||||
import emu.grasscutter.server.event.internal.ServerStopEvent;
|
||||
import emu.grasscutter.task.TaskMap;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class GameServer extends KcpServer {
|
||||
private final InetSocketAddress address;
|
||||
private final GameServerPacketHandler packetHandler;
|
||||
@ -42,6 +43,7 @@ public final class GameServer extends KcpServer {
|
||||
private final DungeonManager dungeonManager;
|
||||
private final CommandMap commandMap;
|
||||
private final TaskMap taskMap;
|
||||
private final DropManager dropManager;
|
||||
|
||||
public GameServer(InetSocketAddress address) {
|
||||
super(address);
|
||||
@ -60,6 +62,7 @@ public final class GameServer extends KcpServer {
|
||||
this.dungeonManager = new DungeonManager(this);
|
||||
this.commandMap = new CommandMap(true);
|
||||
this.taskMap = new TaskMap(true);
|
||||
this.dropManager = new DropManager(this);
|
||||
|
||||
// Schedule game loop.
|
||||
Timer gameLoop = new Timer();
|
||||
@ -109,6 +112,10 @@ public final class GameServer extends KcpServer {
|
||||
public MultiplayerManager getMultiplayerManager() {
|
||||
return multiplayerManager;
|
||||
}
|
||||
|
||||
public DropManager getDropManager() {
|
||||
return dropManager;
|
||||
}
|
||||
|
||||
public DungeonManager getDungeonManager() {
|
||||
return dungeonManager;
|
||||
|
Loading…
Reference in New Issue
Block a user