Passed
Push — master ( 5884cf...2dd329 )
by Vincent
04:16 queued 11s
created

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
ccs 1
cts 1
cp 1
c 0
b 0
f 0
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2020 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.admin.player;
21
22
import fr.quatrevieux.araknemu.core.event.Listener;
23
import fr.quatrevieux.araknemu.game.admin.AdminPerformer;
24
import fr.quatrevieux.araknemu.game.admin.account.AccountContextResolver;
25
import fr.quatrevieux.araknemu.game.admin.context.AbstractContextConfigurator;
26
import fr.quatrevieux.araknemu.game.admin.context.ConfigurableContextResolver;
27
import fr.quatrevieux.araknemu.game.admin.context.Context;
28
import fr.quatrevieux.araknemu.game.admin.exception.ContextException;
29
import fr.quatrevieux.araknemu.game.handler.event.Disconnected;
30
import fr.quatrevieux.araknemu.game.player.GamePlayer;
31
import fr.quatrevieux.araknemu.game.player.PlayerService;
32
33
import java.util.ArrayList;
34
import java.util.HashMap;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.NoSuchElementException;
38
import java.util.function.Supplier;
39
40
/**
41
 * Context resolver for player
42
 */
43
public final class PlayerContextResolver implements ConfigurableContextResolver<PlayerContext> {
44
    private final PlayerService service;
45
    private final AccountContextResolver accountContextResolver;
46
47 1
    private final List<AbstractContextConfigurator<PlayerContext>> configurators = new ArrayList<>();
48 1
    private final Map<GamePlayer, PlayerContext> contexts = new HashMap<>();
49
50 1
    public PlayerContextResolver(PlayerService service, AccountContextResolver accountContextResolver) {
51 1
        this.service = service;
52 1
        this.accountContextResolver = accountContextResolver;
53 1
    }
54
55
    @Override
56
    public Context resolve(AdminPerformer performer, Supplier<String> argument) throws ContextException {
57 1
        final String name = argument.get();
58
59
        try {
60 1
            return resolve(service.get(name));
61 1
        } catch (NoSuchElementException e) {
62 1
            throw new ContextException("Cannot found the player " + name);
63
        }
64
    }
65
66
    @Override
67
    public char prefix() {
68 1
        return '@';
69
    }
70
71
    @Override
72
    public PlayerContextResolver register(AbstractContextConfigurator<PlayerContext> configurator) {
73 1
        configurators.add(configurator);
74
75 1
        return this;
76
    }
77
78
    /**
79
     * Create the context from the given player instance
80
     *
81
     * @param player The player instance
82
     *
83
     * @return The created context
84
     */
85
    public PlayerContext resolve(GamePlayer player) throws ContextException {
86 1
        return contexts.computeIfAbsent(player, key -> {
87 1
            final PlayerContext context = new PlayerContext(
88
                player,
89 1
                accountContextResolver.resolve(player.account()),
90
                configurators
91
            );
92
93 1
            configurePlayerListener(player);
94
95 1
            return context;
96
        });
97
    }
98
99
    /**
100
     * Register listener on player dispatch for free cached context on disconnect
101
     */
102
    private void configurePlayerListener(GamePlayer player) {
103 1
        player.dispatcher().add(new Listener<Disconnected>() {
104
            @Override
105
            public void on(Disconnected event) {
106 1
                contexts.remove(player);
107 1
            }
108
109
            @Override
110
            public Class<Disconnected> event() {
111 1
                return Disconnected.class;
112
            }
113
        });
114 1
    }
115
}
116