mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-30 05:03:51 +00:00
Hunting and deforestation support. (#1083)
* add drops for animals wild pig,fishes,foxes,birds * append fox * Deforestation Support implement drop woods when attacking tree * Deforestation support (remove prints) implement drop woods when attacking tree * Deforestation support (remove prints) implement drop woods when attacking tree * add AutoRecycleHashMap Map's KEY is automatic expire if key long time no use (query or modify from HashMap) * use AutoRecycleHashMap in case of memory leak * fix bug * remove prints * static AutoRecycleHashMap * fix problems * Delete AutoRecycleHashMap.java * remove log * fix build * improve * remove unnecessary information Co-authored-by: Albedo <105265570+arub3do@users.noreply.github.com> Co-authored-by: Albedo <105265570+arub3do@users.noreply.github.com>
This commit is contained in:
parent
830ac793fe
commit
a95002fd40
@ -0,0 +1,91 @@
|
|||||||
|
package emu.grasscutter.game.managers.DeforestationManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import dev.morphia.annotations.Transient;
|
||||||
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.data.GameData;
|
||||||
|
import emu.grasscutter.game.entity.EntityItem;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
import emu.grasscutter.game.world.Scene;
|
||||||
|
import emu.grasscutter.net.proto.HitTreeNotifyOuterClass;
|
||||||
|
import emu.grasscutter.net.proto.VectorOuterClass;
|
||||||
|
import emu.grasscutter.utils.Position;
|
||||||
|
|
||||||
|
public class DeforestationManager {
|
||||||
|
final static int RECORD_EXPIRED_SECONDS = 60*5; // 5 min
|
||||||
|
final static int RECORD_MAX_TIMES = 3; // max number of wood
|
||||||
|
final static int RECORD_MAX_TIMES_OTHER_HIT_TREE = 10; // if hit 10 times other trees, reset wood
|
||||||
|
|
||||||
|
@Transient private final Player player;
|
||||||
|
@Transient private final ArrayList<HitTreeRecord> currentRecord;
|
||||||
|
@Transient private final static HashMap<Integer, Integer> ColliderTypeToWoodItemID = new HashMap<>();
|
||||||
|
static {
|
||||||
|
/* define wood types which reflected to item id*/
|
||||||
|
ColliderTypeToWoodItemID.put(1,101301);
|
||||||
|
ColliderTypeToWoodItemID.put(2,101302);
|
||||||
|
ColliderTypeToWoodItemID.put(3,101303);
|
||||||
|
ColliderTypeToWoodItemID.put(4,101304);
|
||||||
|
ColliderTypeToWoodItemID.put(5,101305);
|
||||||
|
ColliderTypeToWoodItemID.put(6,101306);
|
||||||
|
ColliderTypeToWoodItemID.put(7,101307);
|
||||||
|
ColliderTypeToWoodItemID.put(8,101308);
|
||||||
|
ColliderTypeToWoodItemID.put(9,101309);
|
||||||
|
ColliderTypeToWoodItemID.put(10,101310);
|
||||||
|
ColliderTypeToWoodItemID.put(11,101311);
|
||||||
|
ColliderTypeToWoodItemID.put(12,101312);
|
||||||
|
}
|
||||||
|
public DeforestationManager(Player player){
|
||||||
|
this.player = player;
|
||||||
|
this.currentRecord = new ArrayList<>();
|
||||||
|
}
|
||||||
|
public void resetWood(){
|
||||||
|
synchronized (currentRecord) {
|
||||||
|
currentRecord.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void onDeforestationInvoke(HitTreeNotifyOuterClass.HitTreeNotify hit){
|
||||||
|
synchronized (currentRecord) {
|
||||||
|
//Grasscutter.getLogger().info("onDeforestationInvoke! Wood records {}", currentRecord);
|
||||||
|
VectorOuterClass.Vector hitPosition = hit.getHitPostion();
|
||||||
|
int woodType = hit.getWoodType();
|
||||||
|
if (ColliderTypeToWoodItemID.containsKey(woodType)) {// is a available wood type
|
||||||
|
Scene scene = player.getScene();
|
||||||
|
int itemId = ColliderTypeToWoodItemID.get(woodType);
|
||||||
|
int positionHash = hitPosition.hashCode();
|
||||||
|
HitTreeRecord record = searchRecord(positionHash);
|
||||||
|
if (record == null) {
|
||||||
|
record = new HitTreeRecord(positionHash);
|
||||||
|
}else{
|
||||||
|
currentRecord.remove(record);// move it to last position
|
||||||
|
}
|
||||||
|
currentRecord.add(record);
|
||||||
|
if(currentRecord.size()>RECORD_MAX_TIMES_OTHER_HIT_TREE){
|
||||||
|
currentRecord.remove(0);
|
||||||
|
}
|
||||||
|
if(record.record()) {
|
||||||
|
EntityItem entity = new EntityItem(scene,
|
||||||
|
null,
|
||||||
|
GameData.getItemDataMap().get(itemId),
|
||||||
|
new Position(hitPosition.getX(), hitPosition.getY(), hitPosition.getZ()),
|
||||||
|
1,
|
||||||
|
false);
|
||||||
|
scene.addEntity(entity);
|
||||||
|
}
|
||||||
|
//record.record()=false : too many wood they have deforested, no more wood dropped!
|
||||||
|
} else {
|
||||||
|
Grasscutter.getLogger().warn("No wood type {} found.", woodType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// unknown wood type
|
||||||
|
}
|
||||||
|
private HitTreeRecord searchRecord(int id){
|
||||||
|
for (HitTreeRecord record : currentRecord) {
|
||||||
|
if (record.getUnique() == id) {
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package emu.grasscutter.game.managers.DeforestationManager;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class HitTreeRecord {
|
||||||
|
private final int unique;
|
||||||
|
private short count; // hit this tree times
|
||||||
|
private long time; // last available hitting time
|
||||||
|
HitTreeRecord(int unique){
|
||||||
|
this.count = 0;
|
||||||
|
this.time = 0;
|
||||||
|
this.unique = unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reset hit time
|
||||||
|
*/
|
||||||
|
private void resetTime(){
|
||||||
|
this.time = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* commit hit behavior
|
||||||
|
*/
|
||||||
|
public boolean record(){
|
||||||
|
if (this.count < DeforestationManager.RECORD_MAX_TIMES) {
|
||||||
|
this.count++;
|
||||||
|
resetTime();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// check expired
|
||||||
|
boolean isWaiting = System.currentTimeMillis() - this.time < DeforestationManager.RECORD_EXPIRED_SECONDS * 1000L;
|
||||||
|
if(isWaiting){
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
this.count = 1;
|
||||||
|
resetTime();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* get unique id
|
||||||
|
*/
|
||||||
|
public int getUnique(){
|
||||||
|
return unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "HitTreeRecord{" +
|
||||||
|
"unique=" + unique +
|
||||||
|
", count=" + count +
|
||||||
|
", time=" + time +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import emu.grasscutter.game.ability.AbilityManager;
|
|||||||
import emu.grasscutter.game.avatar.Avatar;
|
import emu.grasscutter.game.avatar.Avatar;
|
||||||
import emu.grasscutter.game.avatar.AvatarProfileData;
|
import emu.grasscutter.game.avatar.AvatarProfileData;
|
||||||
import emu.grasscutter.game.avatar.AvatarStorage;
|
import emu.grasscutter.game.avatar.AvatarStorage;
|
||||||
|
import emu.grasscutter.game.managers.DeforestationManager.DeforestationManager;
|
||||||
import emu.grasscutter.game.entity.EntityGadget;
|
import emu.grasscutter.game.entity.EntityGadget;
|
||||||
import emu.grasscutter.game.entity.EntityItem;
|
import emu.grasscutter.game.entity.EntityItem;
|
||||||
import emu.grasscutter.game.entity.GameEntity;
|
import emu.grasscutter.game.entity.GameEntity;
|
||||||
@ -145,11 +146,11 @@ public class Player {
|
|||||||
@Transient private MapMarksManager mapMarksManager;
|
@Transient private MapMarksManager mapMarksManager;
|
||||||
@Transient private StaminaManager staminaManager;
|
@Transient private StaminaManager staminaManager;
|
||||||
@Transient private EnergyManager energyManager;
|
@Transient private EnergyManager energyManager;
|
||||||
|
@Transient private DeforestationManager deforestationManager;
|
||||||
|
|
||||||
private long springLastUsed;
|
private long springLastUsed;
|
||||||
private HashMap<String, MapMark> mapMarks;
|
private HashMap<String, MapMark> mapMarks;
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
|
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
|
||||||
public Player() {
|
public Player() {
|
||||||
@ -159,6 +160,8 @@ public class Player {
|
|||||||
this.mailHandler = new MailHandler(this);
|
this.mailHandler = new MailHandler(this);
|
||||||
this.towerManager = new TowerManager(this);
|
this.towerManager = new TowerManager(this);
|
||||||
this.abilityManager = new AbilityManager(this);
|
this.abilityManager = new AbilityManager(this);
|
||||||
|
this.deforestationManager = new DeforestationManager(this);
|
||||||
|
|
||||||
this.setQuestManager(new QuestManager(this));
|
this.setQuestManager(new QuestManager(this));
|
||||||
this.pos = new Position();
|
this.pos = new Position();
|
||||||
this.rotation = new Position();
|
this.rotation = new Position();
|
||||||
@ -227,6 +230,7 @@ public class Player {
|
|||||||
this.staminaManager = new StaminaManager(this);
|
this.staminaManager = new StaminaManager(this);
|
||||||
this.sotsManager = new SotSManager(this);
|
this.sotsManager = new SotSManager(this);
|
||||||
this.energyManager = new EnergyManager(this);
|
this.energyManager = new EnergyManager(this);
|
||||||
|
this.deforestationManager = new DeforestationManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getUid() {
|
public int getUid() {
|
||||||
@ -923,7 +927,6 @@ public class Player {
|
|||||||
// Add to inventory
|
// Add to inventory
|
||||||
boolean success = getInventory().addItem(item, ActionReason.SubfieldDrop);
|
boolean success = getInventory().addItem(item, ActionReason.SubfieldDrop);
|
||||||
if (success) {
|
if (success) {
|
||||||
|
|
||||||
if (!drop.isShare()) // not shared drop
|
if (!drop.isShare()) // not shared drop
|
||||||
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
|
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
|
||||||
else
|
else
|
||||||
@ -1109,6 +1112,10 @@ public class Player {
|
|||||||
return abilityManager;
|
return abilityManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeforestationManager getDeforestationManager() {
|
||||||
|
return deforestationManager;
|
||||||
|
}
|
||||||
|
|
||||||
public HashMap<String, MapMark> getMapMarks() { return mapMarks; }
|
public HashMap<String, MapMark> getMapMarks() { return mapMarks; }
|
||||||
|
|
||||||
public void setMapMarks(HashMap<String, MapMark> newMarks) { mapMarks = newMarks; }
|
public void setMapMarks(HashMap<String, MapMark> newMarks) { mapMarks = newMarks; }
|
||||||
@ -1294,6 +1301,9 @@ public class Player {
|
|||||||
|
|
||||||
// Call quit event.
|
// Call quit event.
|
||||||
PlayerQuitEvent event = new PlayerQuitEvent(this); event.call();
|
PlayerQuitEvent event = new PlayerQuitEvent(this); event.call();
|
||||||
|
|
||||||
|
//reset wood
|
||||||
|
getDeforestationManager().resetWood();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SceneLoadState {
|
public enum SceneLoadState {
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package emu.grasscutter.server.packet.recv;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import emu.grasscutter.net.packet.Opcodes;
|
||||||
|
import emu.grasscutter.net.packet.PacketHandler;
|
||||||
|
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||||
|
import emu.grasscutter.net.proto.HitTreeNotifyOuterClass.HitTreeNotify;
|
||||||
|
import emu.grasscutter.server.game.GameSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement Deforestation Function
|
||||||
|
*/
|
||||||
|
@Opcodes(PacketOpcodes.HitTreeNotify)
|
||||||
|
public class HandlerHitTreeNotify extends PacketHandler {
|
||||||
|
@Override
|
||||||
|
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||||
|
HitTreeNotify hit = HitTreeNotify.parseFrom(payload);
|
||||||
|
session.getPlayer().getDeforestationManager().onDeforestationInvoke(hit);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,44 @@
|
|||||||
[
|
[
|
||||||
|
{"monsterId":28040101,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28040102,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28040103,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28040104,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28040105,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28040106,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28040107,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28040108,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020301,"dropDataList":[{"itemId":100061,"minCount":2,"maxCount":2,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020302,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020101,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020102,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020103,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020104,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020105,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020106,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020701,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020702,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020303,"dropDataList":[{"itemId":100094,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28020304,"dropDataList":[{"itemId":100094,"minCount":2,"maxCount":3,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030401,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030402,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030403,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030404,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030405,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030406,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030407,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030408,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030409,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030301,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030302,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030303,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030304,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030305,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030306,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030307,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030308,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030309,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030310,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
|
{"monsterId":28030311,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]},
|
||||||
{
|
{
|
||||||
"monsterId": 21010101,
|
"monsterId": 21010101,
|
||||||
"dropDataList": [
|
"dropDataList": [
|
||||||
|
Loading…
Reference in New Issue
Block a user