net.caseif.flint.common.lobby.CommonLobbySign.java Source code

Java tutorial

Introduction

Here is the source code for net.caseif.flint.common.lobby.CommonLobbySign.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2016, Max Roncace <me@caseif.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package net.caseif.flint.common.lobby;

import static javafx.scene.input.KeyCode.R;

import net.caseif.flint.arena.Arena;
import net.caseif.flint.common.CommonCore;
import net.caseif.flint.common.arena.CommonArena;
import net.caseif.flint.common.component.CommonComponent;
import net.caseif.flint.common.util.file.CommonDataFiles;
import net.caseif.flint.common.util.helper.JsonHelper;
import net.caseif.flint.component.exception.OrphanedComponentException;
import net.caseif.flint.config.ConfigNode;
import net.caseif.flint.config.RoundConfigNode;
import net.caseif.flint.lobby.LobbySign;
import net.caseif.flint.lobby.populator.LobbySignPopulator;
import net.caseif.flint.lobby.type.ChallengerListingLobbySign;
import net.caseif.flint.lobby.type.StatusLobbySign;
import net.caseif.flint.util.physical.Location3D;

import com.google.gson.JsonObject;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * Implements {@link LobbySign}.
 *
 * @author Max Roncac
 */
public abstract class CommonLobbySign implements LobbySign, CommonComponent<Arena> {

    public static final String PERSIST_TYPE_KEY = "type";
    public static final String PERSIST_TYPE_STATUS = "status";
    public static final String PERSIST_TYPE_LISTING = "listing";

    public static final String PERSIST_INDEX_KEY = "index";

    private final Location3D location;
    private final CommonArena arena;
    private final Type type;

    private boolean orphan = false;

    protected CommonLobbySign(Location3D location, CommonArena arena, Type type) {
        this.location = location;
        this.arena = arena;
        this.type = type;
    }

    @Override
    public Arena getOwner() throws OrphanedComponentException {
        checkState();
        return arena;
    }

    @Override
    public Arena getArena() throws OrphanedComponentException {
        return getOwner();
    }

    @Override
    public Location3D getLocation() throws OrphanedComponentException {
        checkState();
        return location;
    }

    @Override
    public Type getType() {
        return type;
    }

    @Override
    public void unregister() throws OrphanedComponentException {
        checkState();
        arena.unregisterLobbySign(location);
    }

    @Override
    public void update() {
        checkState();

        RoundConfigNode<LobbySignPopulator> node;
        if (getType() == Type.STATUS) {
            node = ConfigNode.STATUS_LOBBY_SIGN_POPULATOR;
        } else if (getType() == Type.CHALLENGER_LISTING) {
            node = ConfigNode.CHALLENGER_LISTING_LOBBY_SIGN_POPULATOR;
        } else {
            throw new AssertionError();
        }
        LobbySignPopulator pop = getArena().getRound().isPresent()
                ? getArena().getRound().get().getConfigValue(node)
                : getArena().getMinigame().getConfigValue(node);
        updatePhysicalSign(pop.first(this), pop.second(this), pop.third(this), pop.fourth(this));
    }

    protected abstract void updatePhysicalSign(String... lines);

    /**
     * Stores this {@link LobbySign} to persistent storage.
     */
    private void store(boolean remove) {
        try {
            File store = CommonDataFiles.LOBBY_STORE.getFile(getArena().getMinigame());
            JsonObject json = JsonHelper.readOrCreateJson(store);

            JsonObject arena = json.getAsJsonObject(getArena().getId());
            if (arena == null) {
                if (!remove) { // okay to create it since we're newly storing the sign
                    arena = new JsonObject();
                    json.add(getArena().getId(), arena);
                } else { // can't delete something that's not there
                    CommonCore
                            .logWarning("Anomaly: Engine requested removal of lobby sign from store, but arena was "
                                    + "not defined");
                    return;
                }
            }

            String locSerial = getLocation().serialize();
            if (remove) {
                if (arena.has(locSerial)) {
                    arena.remove(locSerial);
                } else {
                    CommonCore
                            .logWarning("Engine requested removal of lobby sign from store, but respective section "
                                    + "was not defined");
                }
            } else {
                JsonObject sign = new JsonObject();
                arena.add(locSerial, sign);

                String type;
                if (this instanceof StatusLobbySign) {
                    type = PERSIST_TYPE_STATUS;
                } else if (this instanceof ChallengerListingLobbySign) {
                    type = PERSIST_TYPE_LISTING;
                } else {
                    throw new AssertionError("Invalid LobbySign object. Report this immediately.");
                }
                sign.addProperty(PERSIST_TYPE_KEY, type);
                if (this instanceof ChallengerListingLobbySign) {
                    sign.addProperty(PERSIST_INDEX_KEY, ((ChallengerListingLobbySign) this).getIndex());
                }
            }

            try (FileWriter writer = new FileWriter(store)) {
                writer.write(json.toString());
            }
        } catch (IOException ex) {
            CommonCore.logSevere("Failed to write to lobby sign store");
            ex.printStackTrace();
        }
    }

    public void store() {
        store(false);
    }

    /**
     * Removes this {@link LobbySign} from persistent storage.
     */
    public void unstore() {
        store(true);
    }

    protected String[] getChallengerListingText() {
        if (!validate()) {
            // hehe, illegal "state"
            unregister();
            CommonCore.logWarning(
                    "Cannot update lobby sign at (" + "\"" + location.getWorld() + "\", " + location.getX() + ", "
                            + location.getY() + ", " + location.getZ() + "): not a sign. Removing...");
        }
        int startIndex = ((ChallengerListingLobbySign) this).getIndex() * getSignSize();
        boolean round = getArena().getRound().isPresent();

        String[] lines = new String[getSignSize()];
        for (int i = 0; i < getSignSize(); i++) {
            if (round && startIndex + i < getArena().getRound().get().getChallengers().size()) {
                lines[i] = getArena().getRound().get().getChallengers().get(startIndex + i).getName();
            } else {
                lines[i] = "";
            }
        }

        return lines;
    }

    protected String[] getStatusText() {
        if (!validate()) {
            unregister();
            throw new IllegalStateException("Cannot update lobby sign: not a sign. Removing...");
        }

        String[] lines = new String[getSignSize()];

        lines[0] = getArena().getDisplayName();
        if (getArena().getRound().isPresent()) {
            lines[1] = getArena().getRound().get().getLifecycleStage().getId().toUpperCase();
            long seconds = getArena().getRound().get().getRemainingTime() != -1
                    ? getArena().getRound().get().getRemainingTime()
                    : getArena().getRound().get().getTime();
            String time = seconds / 60 + ":" + (seconds % 60 >= 10 ? seconds % 60 : "0" + seconds % 60);
            lines[2] = time;
            // get max player count
            int maxPlayers = getArena().getRound().get().getConfigValue(ConfigNode.MAX_PLAYERS);
            // format player count relative to max
            String players = getArena().getRound().get().getChallengers().size() + "/"
                    + (maxPlayers > 0 ? maxPlayers : "");
            // add label to player count (shortened version used if the full one won't fit)
            players += players.length() <= 5 ? " players" : (players.length() <= 7 ? " plyrs" : "");
            lines[3] = players;
        } else {
            for (int i = 1; i < getSignSize(); i++) {
                lines[i] = "";
            }
        }

        return lines;
    }

    protected abstract boolean validate();

    protected abstract int getSignSize();

    @Override
    public void checkState() throws OrphanedComponentException {
        if (orphan) {
            throw new OrphanedComponentException(this);
        }
    }

    @Override
    public void orphan() {
        CommonCore.orphan(this);
    }

    @Override
    public void setOrphanFlag() {
        this.orphan = true;
    }

}