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:
zhaodice
2022-05-29 21:16:49 +08:00
committed by GitHub
parent 830ac793fe
commit a95002fd40
5 changed files with 221 additions and 2 deletions

View File

@@ -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;
}
}

View File

@@ -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 +
'}';
}
}