AnnouncementManager.java 3.43 KB
Newer Older
Akka's avatar
Akka committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package emu.grasscutter.game.managers;

import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.AnnounceDataOuterClass;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketServerAnnounceNotify;
import emu.grasscutter.server.packet.send.PacketServerAnnounceRevokeNotify;
import emu.grasscutter.utils.Utils;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.experimental.FieldDefaults;

import java.io.InputStreamReader;
import java.util.*;

@Getter
public class AnnouncementManager {

    public final GameServer server;
    public AnnouncementManager(GameServer server){
        this.server = server;
        loadConfig();
    }
    Map<Integer, AnnounceConfigItem> announceConfigItemMap = new HashMap<>();

    private int loadConfig() {
        try (var fileReader = new InputStreamReader(DataLoader.load("Announcement.json"))) {
            List<AnnounceConfigItem> announceConfigItems = Grasscutter.getGsonFactory().fromJson(fileReader,
                TypeToken.getParameterized(List.class, AnnounceConfigItem.class).getType());

            announceConfigItemMap = new HashMap<>();
            announceConfigItems.forEach(i -> announceConfigItemMap.put(i.getTemplateId(), i));


        } catch (Exception e) {
            Grasscutter.getLogger().error("Unable to load server announce config.", e);
        }

        return announceConfigItemMap.size();
    }

    public List<Player> getOnlinePlayers() {
        return getServer().getWorlds().stream()
            .map(World::getPlayers)
            .flatMap(Collection::stream)
            .toList();
    }

    public void broadcast(List<AnnounceConfigItem> tpl) {
        if(tpl == null || tpl.size() == 0){
            return;
        }

        var list = tpl.stream()
            .map(AnnounceConfigItem::toProto)
            .map(AnnounceDataOuterClass.AnnounceData.Builder::build)
            .toList();

        getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceNotify(list)));
    }

    public int refresh() {
        return loadConfig();
    }

    public void revoke(int tplId) {
        getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceRevokeNotify(tplId)));
    }

    @Data
    @FieldDefaults(level = AccessLevel.PRIVATE)
    public class AnnounceConfigItem{
        int templateId;
        AnnounceType type;
        int frequency;
        String content;
        Date beginTime;
        Date endTime;
        boolean tick;
        int interval;

        public AnnounceDataOuterClass.AnnounceData.Builder toProto(){
            var proto = AnnounceDataOuterClass.AnnounceData.newBuilder();

            proto.setConfigId(templateId)
                // I found the time here is useless
                .setBeginTime(Utils.getCurrentSeconds() + 1)
                .setEndTime(Utils.getCurrentSeconds() + 10);

            if(type == AnnounceType.CENTER){
                proto.setCenterSystemText(content)
                    .setCenterSystemFrequency(frequency)
                ;
            }else{
                proto.setCountDownText(content)
                    .setCountDownFrequency(frequency)
                ;
            }

            return proto;
        }
    }

    public enum AnnounceType{
        CENTER, COUNTDOWN
    }
}