com.sk89q.craftbook.sponge.mechanics.variable.Variables.java Source code

Java tutorial

Introduction

Here is the source code for com.sk89q.craftbook.sponge.mechanics.variable.Variables.java

Source

/*
 * CraftBook Copyright (C) 2010-2018 sk89q <http://www.sk89q.com>
 * CraftBook Copyright (C) 2011-2018 me4502 <http://www.me4502.com>
 * CraftBook Copyright (C) Contributors
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not,
 * see <http://www.gnu.org/licenses/>.
 */
package com.sk89q.craftbook.sponge.mechanics.variable;

import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken;
import com.google.inject.Inject;
import com.me4502.modularframework.module.Module;
import com.me4502.modularframework.module.guice.ModuleConfiguration;
import com.sk89q.craftbook.core.util.ConfigValue;
import com.sk89q.craftbook.core.util.CraftBookException;
import com.sk89q.craftbook.core.util.PermissionNode;
import com.sk89q.craftbook.core.util.documentation.DocumentationProvider;
import com.sk89q.craftbook.sponge.CraftBookPlugin;
import com.sk89q.craftbook.sponge.mechanics.types.SpongeMechanic;
import com.sk89q.craftbook.sponge.mechanics.variable.command.GetVariableCommand;
import com.sk89q.craftbook.sponge.mechanics.variable.command.ListVariableCommand;
import com.sk89q.craftbook.sponge.mechanics.variable.command.RemoveVariableCommand;
import com.sk89q.craftbook.sponge.mechanics.variable.command.SetVariableCommand;
import com.sk89q.craftbook.sponge.util.SpongePermissionNode;
import com.sk89q.craftbook.sponge.util.TextUtil;
import com.sk89q.craftbook.sponge.util.type.TypeTokens;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandMapping;
import org.spongepowered.api.command.args.GenericArguments;
import org.spongepowered.api.command.spec.CommandSpec;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.command.SendCommandEvent;
import org.spongepowered.api.event.message.MessageChannelEvent;
import org.spongepowered.api.service.permission.PermissionDescription;
import org.spongepowered.api.text.LiteralText;
import org.spongepowered.api.text.Text;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

@Module(id = "variables", name = "Variables", onEnable = "onInitialize", onDisable = "onDisable")
public class Variables extends SpongeMechanic implements DocumentationProvider {

    public static final String GLOBAL_NAMESPACE = "global";

    private static final Pattern VARIABLE_PATTERN = Pattern.compile("%(?:([a-zA-Z0-9_]+)\\|)*([a-zA-Z0-9]+)%");

    public static Variables instance;

    private Map<String, Map<String, String>> variableStore;

    @Inject
    @ModuleConfiguration
    public ConfigurationNode config;

    private SpongePermissionNode setPermission = new SpongePermissionNode("craftbook.variables.set",
            "Allows setting variables.", PermissionDescription.ROLE_USER);
    private SpongePermissionNode setGlobalPermission = new SpongePermissionNode("craftbook.variables.set.global",
            "Allows setting global variables.", PermissionDescription.ROLE_STAFF);

    private SpongePermissionNode getPermission = new SpongePermissionNode("craftbook.variables.get",
            "Allows getting variables.", PermissionDescription.ROLE_USER);
    private SpongePermissionNode getGlobalPermission = new SpongePermissionNode("craftbook.variables.get.global",
            "Allows getting global variables.", PermissionDescription.ROLE_STAFF);

    private SpongePermissionNode delPermission = new SpongePermissionNode("craftbook.variables.remove",
            "Allows removing variables.", PermissionDescription.ROLE_USER);
    private SpongePermissionNode delGlobalPermission = new SpongePermissionNode("craftbook.variables.remove.global",
            "Allows removing global variables.", PermissionDescription.ROLE_STAFF);

    private SpongePermissionNode listPermission = new SpongePermissionNode("craftbook.variables.list",
            "Allows listing variables.", PermissionDescription.ROLE_USER);
    private SpongePermissionNode listGlobalPermission = new SpongePermissionNode("craftbook.variables.list.global",
            "Allows listing global variables.", PermissionDescription.ROLE_STAFF);

    private ConfigValue<Boolean> defaultToGlobal = new ConfigValue<>("default-to-global",
            "If no namespace is provided, default to global. " + "Otherwise personal namespace", true);

    private CommandMapping variableCommandMapping;

    @Override
    public void onInitialize() throws CraftBookException {
        super.onInitialize();

        instance = this;

        try {
            variableStore = config.getNode("variables").getValue(new TypeTokens.VariableTypeToken(),
                    Maps.newHashMap());
        } catch (ObjectMappingException e) {
            CraftBookPlugin.spongeInst().getLogger().warn("Failed to read variables! Resetting..", e);
            variableStore = new HashMap<>();
        }

        setPermission.register();
        setGlobalPermission.register();

        getPermission.register();
        getGlobalPermission.register();

        delPermission.register();
        delGlobalPermission.register();

        listPermission.register();
        listGlobalPermission.register();

        defaultToGlobal.load(config);

        CommandSpec setVariable = CommandSpec.builder().description(Text.of("Set the value of a variable"))
                .permission(setPermission.getNode())
                .arguments(GenericArguments.string(Text.of("key")), GenericArguments.string(Text.of("value")),
                        GenericArguments.flags().permissionFlag(setGlobalPermission.getNode(), "g", "-global")
                                .valueFlag(GenericArguments.string(Text.of("namespace")), "n", "-namespace")
                                .buildWith(GenericArguments.none()))
                .executor(new SetVariableCommand(this)).build();

        CommandSpec getVariable = CommandSpec.builder().description(Text.of("Get the value of a variable"))
                .permission(getPermission.getNode())
                .arguments(GenericArguments.string(Text.of("key")),
                        GenericArguments.flags().permissionFlag(getGlobalPermission.getNode(), "g", "-global")
                                .valueFlag(GenericArguments.string(Text.of("namespace")), "n", "-namespace")
                                .buildWith(GenericArguments.none()))
                .executor(new GetVariableCommand(this)).build();

        CommandSpec removeVariable = CommandSpec.builder().description(Text.of("Removes a variable"))
                .permission(delPermission.getNode())
                .arguments(GenericArguments.string(Text.of("key")),
                        GenericArguments.flags().permissionFlag(delGlobalPermission.getNode(), "g", "-global")
                                .valueFlag(GenericArguments.string(Text.of("namespace")), "n", "-namespace")
                                .buildWith(GenericArguments.none()))
                .executor(new RemoveVariableCommand(this)).build();

        CommandSpec listVariable = CommandSpec.builder().description(Text.of("List variables"))
                .permission(listPermission.getNode())
                .arguments(GenericArguments.flags().permissionFlag(listPermission.getNode(), "g", "-global")
                        .valueFlag(GenericArguments.string(Text.of("namespace")), "n", "-namespace")
                        .buildWith(GenericArguments.none()))
                .executor(new ListVariableCommand(this)).build();

        CommandSpec variableCommand = CommandSpec.builder().description(Text.of("Base Variable command"))
                .child(setVariable, "set", "def", "define").child(getVariable, "get")
                .child(removeVariable, "rm", "del", "remove").child(listVariable, "list", "ls").build();

        variableCommandMapping = Sponge.getGame().getCommandManager()
                .register(CraftBookPlugin.spongeInst(), variableCommand, "var", "variable", "variables")
                .orElse(null);
    }

    @Override
    public void onDisable() {
        super.onDisable();

        try {
            config.getNode("variables").setValue(new TypeToken<Map<String, Map<String, String>>>() {
            }, variableStore);
        } catch (ObjectMappingException e) {
            e.printStackTrace();
        }

        if (variableCommandMapping != null) {
            Sponge.getCommandManager().removeMapping(variableCommandMapping);
        }
    }

    public void addVariable(String namespace, String key, String value) {
        Map<String, String> map = variableStore.getOrDefault(namespace, new HashMap<>());
        map.put(key, value);
        variableStore.put(namespace, map);
    }

    public String getVariable(String namespace, String key) {
        Map<String, String> map = variableStore.getOrDefault(namespace, new HashMap<>());
        return map.getOrDefault(key, null);
    }

    public void removeVariable(String namespace, String key) {
        Map<String, String> map = variableStore.getOrDefault(namespace, new HashMap<>());
        map.remove(key);
        if (!map.isEmpty())
            variableStore.put(namespace, map);
        else
            variableStore.remove(namespace);
    }

    public Map<String, String> getVariables(String namespace) {
        return variableStore.getOrDefault(namespace, Collections.emptyMap());
    }

    public String parseVariables(String line, @Nullable Player player) {
        for (Pair<String, String> possibleVariable : getPossibleVariables(line)) {
            String namespace = possibleVariable.getLeft();
            String name = possibleVariable.getRight();

            boolean explicit = true;
            if (namespace == null) {
                if (defaultToGlobal.getValue()) {
                    namespace = GLOBAL_NAMESPACE;
                    if (player != null && getVariable(player.getUniqueId().toString(), name) != null) {
                        namespace = player.getUniqueId().toString();
                    }
                } else {
                    if (player != null) {
                        namespace = player.getUniqueId().toString();
                    } else {
                        continue;
                    }
                }
                explicit = false;
            }

            String variable = getVariable(namespace, name);

            if (variable != null) {
                String variableText = (explicit ? (namespace + '|') : "") + name;
                line = line.replace('%' + variableText + '%', getVariable(namespace, name));
            }
        }

        return line;
    }

    @Listener
    public void onCommandSend(SendCommandEvent event) {
        Player source = null;
        if (event.getCause().first(Player.class).isPresent())
            source = event.getCause().first(Player.class).get();
        if (!event.getArguments().isEmpty())
            event.setArguments(parseVariables(event.getArguments(), source));
        event.setCommand(parseVariables(event.getCommand(), source));
    }

    @Listener
    public void onPlayerChat(MessageChannelEvent event) {
        event.setMessage(TextUtil.transform(event.getMessage(), old -> {
            if (old instanceof LiteralText) {
                LiteralText literal = (LiteralText) old;
                return literal.toBuilder().content(
                        parseVariables(literal.getContent(), event.getCause().first(Player.class).orElse(null)))
                        .toText();
            }

            return old;
        }));
    }

    public static Set<Pair<String, String>> getPossibleVariables(String line) {
        Set<Pair<String, String>> variables = new HashSet<>();

        if (!line.contains("%"))
            return variables;

        Matcher matcher = VARIABLE_PATTERN.matcher(line);

        while (matcher.find()) {
            String namespace = matcher.group(1);
            String key = matcher.group(2);
            variables.add(new ImmutablePair<>(namespace, key));
        }

        return variables;
    }

    public static boolean isValidVariableKey(String key) {
        return !key.contains("|") && !key.contains("%");
    }

    @Override
    public String getPath() {
        return "mechanics/variables";
    }

    @Override
    public ConfigValue<?>[] getConfigurationNodes() {
        return new ConfigValue[] { defaultToGlobal };
    }

    @Override
    public PermissionNode[] getPermissionNodes() {
        return new PermissionNode[] { setPermission, setGlobalPermission, getPermission, getGlobalPermission,
                delPermission, delGlobalPermission, listPermission, listGlobalPermission };
    }
}