ActivityManager.java 6.27 KB
Newer Older
Akka's avatar
Akka committed
1
2
3
4
5
6
7
package emu.grasscutter.game.activity;

import com.esotericsoftware.reflectasm.ConstructorAccess;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.data.GameData;
Melledy's avatar
Melledy committed
8
import emu.grasscutter.game.player.BasePlayerManager;
Akka's avatar
Akka committed
9
import emu.grasscutter.game.player.Player;
Akka's avatar
Akka committed
10
import emu.grasscutter.game.props.ActivityType;
Akka's avatar
Akka committed
11
12
13
14
15
16
17
18
19
20
21
22
import emu.grasscutter.game.props.WatcherTriggerType;
import emu.grasscutter.net.proto.ActivityInfoOuterClass;
import emu.grasscutter.server.packet.send.PacketActivityScheduleInfoNotify;
import lombok.Getter;
import org.reflections.Reflections;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Getter
Melledy's avatar
Melledy committed
23
public class ActivityManager extends BasePlayerManager {
Akka's avatar
Akka committed
24
25
26
27
28
29
30
31
32
33
    private static final Map<Integer, ActivityConfigItem> activityConfigItemMap;
    private final Map<Integer, PlayerActivityData> playerActivityDataMap;

    static {
        activityConfigItemMap = new HashMap<>();
        loadActivityConfigData();
    }

    private static void loadActivityConfigData() {
        // scan activity type handler & watcher type
Akka's avatar
Akka committed
34
35
        var activityHandlerTypeMap = new HashMap<ActivityType, ConstructorAccess<?>>();
        var activityWatcherTypeMap = new HashMap<WatcherTriggerType, ConstructorAccess<?>>();
Akka's avatar
Akka committed
36
37
38
        var reflections = new Reflections(ActivityManager.class.getPackage().getName());

        reflections.getSubTypesOf(ActivityHandler.class).forEach(item -> {
Akka's avatar
Akka committed
39
            var typeName = item.getAnnotation(GameActivity.class);
Akka's avatar
Akka committed
40
41
42
            activityHandlerTypeMap.put(typeName.value(), ConstructorAccess.get(item));
        });
        reflections.getSubTypesOf(ActivityWatcher.class).forEach(item -> {
Akka's avatar
Akka committed
43
44
            var typeName = item.getAnnotation(ActivityWatcherType.class);
            activityWatcherTypeMap.put(typeName.value(), ConstructorAccess.get(item));
Akka's avatar
Akka committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
        });

        try(InputStream is = DataLoader.load("ActivityConfig.json"); InputStreamReader isr = new InputStreamReader(is)) {
            List<ActivityConfigItem> activities = Grasscutter.getGsonFactory().fromJson(
                isr,
                TypeToken.getParameterized(List.class, ActivityConfigItem.class).getType());


            activities.forEach(item -> {
                var activityData = GameData.getActivityDataMap().get(item.getActivityId());
                if(activityData == null){
                    Grasscutter.getLogger().warn("activity {} not exist.", item.getActivityId());
                    return;
                }
Akka's avatar
Akka committed
59
60
                var activityHandlerType = activityHandlerTypeMap.get(ActivityType.getTypeByName(activityData.getActivityType()));
                ActivityHandler activityHandler;
Akka's avatar
Akka committed
61
62

                if(activityHandlerType != null) {
Akka's avatar
Akka committed
63
64
65
                    activityHandler = (ActivityHandler) activityHandlerType.newInstance();
                }else{
                    activityHandler = new DefaultActivityHandler();
Akka's avatar
Akka committed
66
                }
Akka's avatar
Akka committed
67
68
69
                activityHandler.setActivityConfigItem(item);
                activityHandler.initWatchers(activityWatcherTypeMap);
                item.setActivityHandler(activityHandler);
Akka's avatar
Akka committed
70
71
72
73

                activityConfigItemMap.putIfAbsent(item.getActivityId(), item);
            });

Akka's avatar
Akka committed
74
            Grasscutter.getLogger().info("Enable {} activities.", activityConfigItemMap.size());
Akka's avatar
Akka committed
75
        } catch (Exception e) {
Akka's avatar
Akka committed
76
            Grasscutter.getLogger().error("Unable to load activities config.", e);
Akka's avatar
Akka committed
77
78
79
80
        }

    }

Akka's avatar
Akka committed
81
    public ActivityManager(Player player){
Melledy's avatar
Melledy committed
82
        super(player);
Akka's avatar
Akka committed
83

Akka's avatar
Akka committed
84
85
86
87
88
89
90
91
92
93
94
95
        playerActivityDataMap = new ConcurrentHashMap<>();
        // load data for player
        activityConfigItemMap.values().forEach(item -> {
            var data = PlayerActivityData.getByPlayer(player, item.getActivityId());
            if(data == null){
                data = item.getActivityHandler().initPlayerActivityData(player);
                data.save();
            }
            data.setPlayer(player);
            data.setActivityHandler(item.getActivityHandler());
            playerActivityDataMap.put(item.getActivityId(), data);
        });
Akka's avatar
Akka committed
96

Akka's avatar
Akka committed
97
        player.sendPacket(new PacketActivityScheduleInfoNotify(activityConfigItemMap.values()));
Akka's avatar
Akka committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    }

    /**
     * trigger activity watcher
     */
    public void triggerWatcher(WatcherTriggerType watcherTriggerType, String... params) {
        var watchers = activityConfigItemMap.values().stream()
            .map(ActivityConfigItem::getActivityHandler)
            .filter(Objects::nonNull)
            .map(ActivityHandler::getWatchersMap)
            .map(map -> map.get(watcherTriggerType))
            .filter(Objects::nonNull)
            .flatMap(Collection::stream)
            .toList();

        watchers.forEach(watcher -> watcher.trigger(
            playerActivityDataMap.get(watcher.getActivityHandler().getActivityConfigItem().getActivityId()),
            params));
    }
Akka's avatar
Akka committed
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

    public ActivityInfoOuterClass.ActivityInfo getInfoProtoByActivityId(int activityId){
        var activityHandler = activityConfigItemMap.get(activityId).getActivityHandler();
        var activityData = playerActivityDataMap.get(activityId);

        return activityHandler.toProto(activityData);
    }

    public Optional<ActivityHandler> getActivityHandler(ActivityType type){
        return activityConfigItemMap.values().stream()
            .map(ActivityConfigItem::getActivityHandler)
            .filter(x -> type == x.getClass().getAnnotation(GameActivity.class).value())
            .findFirst();
    }

    public <T extends ActivityHandler> Optional<T> getActivityHandlerAs(ActivityType type, Class<T> clazz){
        return getActivityHandler(type).map(x -> (T)x);
    }

    public Optional<Integer> getActivityIdByActivityType(ActivityType type){
        return getActivityHandler(type)
            .map(ActivityHandler::getActivityConfigItem)
            .map(ActivityConfigItem::getActivityId);
    }
    public Optional<PlayerActivityData> getPlayerActivityDataByActivityType(ActivityType type){
        return getActivityIdByActivityType(type)
            .map(playerActivityDataMap::get);
    }
    public Optional<ActivityInfoOuterClass.ActivityInfo> getInfoProtoByActivityType(ActivityType type){
       return getActivityIdByActivityType(type)
           .map(this::getInfoProtoByActivityId);
    }

Akka's avatar
Akka committed
150
}