be.guntherdw.minecraft.snowballsclient.LiteModSnowBalls.java Source code

Java tutorial

Introduction

Here is the source code for be.guntherdw.minecraft.snowballsclient.LiteModSnowBalls.java

Source

/*
 * Copyright (c) 2012-2015 GuntherDW
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package be.guntherdw.minecraft.snowballsclient;

import com.google.common.collect.ImmutableList;
import com.mojang.realmsclient.dto.RealmsServer;
import com.mumfrey.liteloader.JoinGameListener;
import com.mumfrey.liteloader.PluginChannelListener;
import com.mumfrey.liteloader.PostRenderListener;
import com.mumfrey.liteloader.Tickable;
import com.mumfrey.liteloader.core.LiteLoader;
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.network.INetHandler;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.network.play.server.S01PacketJoinGame;
import net.minecraft.util.ChatComponentText;
import org.apache.logging.log4j.core.Logger;

import java.io.File;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author GuntherDW
 */
public class LiteModSnowBalls implements JoinGameListener, PluginChannelListener, Tickable, PostRenderListener {

    public List<SnowBallRecipe> ShapelessRecipes;
    public List<SnowBallShapedRecipe> ShapedRecipes;
    private HashMap<Integer, Integer> originalStackSizes = new HashMap<Integer, Integer>();
    public static Pattern lineSplitterPattern = Pattern.compile("([^|]*)\\|?(.*)");
    private static Minecraft minecraft;
    private final String snowballsPluginMessageChannel = "SnowBalls";
    private boolean loadedrecipes = false;
    private boolean shownWarning = false;

    private SearchRenderer searchRenderer;

    private final static int DELAYED_HELO_TICKS = 10;
    private int delayedHelo = 0;
    private boolean sendRegisterPacket = false;

    Logger log = LiteLoaderLogger.getLogger();

    private boolean DEBUG = false;

    public LiteModSnowBalls() {
        ShapelessRecipes = new ArrayList<SnowBallRecipe>();
        ShapedRecipes = new ArrayList<SnowBallShapedRecipe>();
        minecraft = Minecraft.getMinecraft();
    }

    @Override
    public String getVersion() {
        String version = LiteLoader.getInstance().getModMetaData(this, "version", "");
        String build = LiteLoader.getInstance().getModMetaData(this, "revision", "");

        return version + (!(build.equals("")) ? " (build: " + build + ")" : "");
    }

    /**
     * Do startup stuff here, minecraft is not fully initialised when this function is called so mods *must not*
     * interact with minecraft in any way here
     *
     * @param configPath Configuration path to use
     */
    @Override
    public void init(File configPath) {
        searchRenderer = new SearchRenderer(this);
    }

    /**
     * Called when the loader detects that a version change has happened since this mod was last loaded
     *
     * @param version       new version
     * @param configPath    Path for the new version-specific config
     * @param oldConfigPath Path for the old version-specific config
     */
    @Override
    public void upgradeSettings(String version, File configPath, File oldConfigPath) {

    }

    private void log(String message) {
        log.info("[mod_SnowBalls] " + message);
        if (minecraft != null && minecraft.ingameGUI.getChatGUI() != null)
            minecraft.ingameGUI.getChatGUI()
                    .printChatMessage(new ChatComponentText("[mod_SnowBalls] 6" + message));
    }

    private void loadShapelessRecipes() {
        if (!loadedrecipes) {
            for (SnowBallRecipe sr : ShapelessRecipes) {
                CraftingManager.getInstance().addShapelessRecipe(sr.getResult(), sr.getIngredients().toArray());
            }
        }
        loadedrecipes = true;
    }

    private void setItemMaxStack(Integer itemId, int maxstack) {
        if (maxstack < 0)
            maxstack = 1;
        if (itemId < 1 || itemId > 4096)
            return;
        if (DEBUG)
            log("6" + itemId + " : " + maxstack);
        try {
            if (!originalStackSizes.containsKey(itemId))
                originalStackSizes.put(itemId, Item.getItemById(itemId).getItemStackLimit());

            Item.getItemById(itemId).setMaxStackSize(maxstack);
        } catch (ArrayIndexOutOfBoundsException ex) {
            return;
        }
    }

    private void injectShapelessRecipe(SnowBallRecipe sr) {
        CraftingManager.getInstance().addShapelessRecipe(sr.getResult(), sr.getIngredients().toArray());
    }

    private void injectShapedRecipe(SnowBallShapedRecipe shr) {
        CraftingManager.getInstance().addRecipe(shr.getResult(), shr.generateRecipeLine());
    }

    private boolean addItems(String[] items) {
        for (String itemstring : items) {
            String[] split = itemstring.split(";");
            Integer itemId = null;
            Integer maxStack = null;
            try {
                itemId = Integer.parseInt(split[0]);
                maxStack = Integer.parseInt(split[1]);
            } catch (NumberFormatException ex) {
                ex.printStackTrace();
            } catch (ArrayIndexOutOfBoundsException ex) {
                ex.printStackTrace();
            }
            if (maxStack == null)
                maxStack = 64;
            if (itemId != null)
                this.setItemMaxStack(itemId, maxStack);
            // System.out.println(itemId+":"+maxStack);
        }
        return true;
    }

    private boolean parseLine(String result, String[] args, boolean inject) {
        String[] res = result.split(":");
        try {
            String modus = res[0];
            if (DEBUG)
                log("4SnowBalls-client 6" + result);
            if (modus.equals("i")) {
                return this.addItems(args);
            } else if (modus.equals("1") || modus.equals("0")) {
                return this.addRecipe(result, args, inject);
            } else {
                if (!shownWarning) {
                    shownWarning = true;
                    log("error");
                    log("6please make sure you are running");
                    log("6the latest version!");
                }

                return true;
            }

        } catch (ArrayIndexOutOfBoundsException ex) {
            return false;
        } catch (NumberFormatException ex) {
            return false;
        }
    }

    private boolean addRecipe(String result, String[] args, boolean inject) {
        /* System.out.println("SneuwSUI: " + result); */
        inject = true;
        Integer Iid, Idmg, Iam;
        Integer tid, tdmg, tam;
        List<ItemStack> recipe = new ArrayList<ItemStack>();
        ItemStack ResultItemStack = null;
        ItemStack tempstack = null;
        String[] res = result.split(":");
        Integer type = null;
        String resu = "";
        try {
            type = Integer.parseInt(res[0]);
            resu = res[1];
        } catch (ArrayIndexOutOfBoundsException ex) {
            resu = result;
        } catch (NumberFormatException ex) {
            resu = result;
        }

        if (args.length == 0)
            return false;

        try {
            String[] resultitem = resu.split(";");
            Iid = Integer.parseInt(resultitem[0]);
            Idmg = Integer.parseInt(resultitem[1]);
            Iam = Integer.parseInt(resultitem[2]);
            ResultItemStack = new ItemStack(Item.getItemById(Iid), Iam, Idmg);
            // System.out.println("Adding recipe for "+Iam+" "+ResultItemStack.l());
            /**
             * 0 or nothing (older format) : ShapeLess recipe
             * 1                           : Shaped    recipe
             */
            if (type == null || type == 0) {
                for (String a : args) {
                    String[] ra = a.split(";");
                    tid = Integer.parseInt(ra[0]);
                    tdmg = ra.length > 1 ? Integer.parseInt(ra[1]) : 0;
                    tam = ra.length > 2 ? Integer.parseInt(ra[2]) : 1;
                    tempstack = new ItemStack(Item.getItemById(tid), tam, tdmg);
                    recipe.add(tempstack);
                }
                SnowBallRecipe shapelessRecipe = new SnowBallRecipe(ResultItemStack, recipe);
                ShapelessRecipes.add(shapelessRecipe);
                if (inject)
                    this.injectShapelessRecipe(shapelessRecipe);
            } else {
                int pos = 0;
                SnowBallShapedRecipe shr = new SnowBallShapedRecipe(ResultItemStack);
                for (String a : args) {

                    if ((!a.trim().equals(""))) {
                        String[] ra = a.split(";");
                        tid = Integer.parseInt(ra[0]);
                        tdmg = ra.length > 1 ? Integer.parseInt(ra[1]) : 0;
                        tam = ra.length > 2 ? Integer.parseInt(ra[2]) : 1;
                        tempstack = new ItemStack(Item.getItemById(tid), tam, tdmg);
                        if (pos < 9) {
                            shr.setIngredientSpot(pos, tempstack);
                        }
                    }
                    pos++;
                }
                ShapedRecipes.add(shr);
                if (inject)
                    this.injectShapedRecipe(shr);
            }
        } catch (NumberFormatException ex) {
            log.warn("NumberFormatException!");
            ex.printStackTrace();
            return false;
        } catch (ArrayIndexOutOfBoundsException ex) {
            log.warn("ArrayIndexOutOfBoundsException!");
            ex.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Called when a custom payload packet arrives on a channel this mod has registered
     *
     * @param channel Channel on which the custom payload was received
     * @param data    Custom payload data
     */
    @Override
    public void onCustomPayload(String channel, PacketBuffer data) {
        if (DEBUG)
            log("Got custom payload packet!");

        byte[] bytes = data.array();
        byte controlByte = bytes[0];
        byte[] cleanData = new byte[bytes.length - 1];
        System.arraycopy(bytes, 1, cleanData, 0, bytes.length - 1);

        if (controlByte == 20) {
            searchRenderer.decodePayload(cleanData);
        } else if (controlByte == 10) {
            Set<String> recipeLines = new HashSet<String>();
            String recipeLine = "";

            for (byte b1 : cleanData) {
                if (b1 == (byte) 0) {
                    recipeLines.add(recipeLine);
                    recipeLine = "";
                } else {
                    recipeLine += (char) b1;
                }

            }

            for (String line : recipeLines) {
                Matcher matcher = lineSplitterPattern.matcher(line);
                if (matcher.find()) {
                    parseLine(matcher.group(1), matcher.group(2).split("\\|"), true);
                }
            }
        }
    }

    public C17PacketCustomPayload getRegisterPacket() {
        PacketBuffer pb = new PacketBuffer(Unpooled.buffer());
        pb.writeByte((byte) 26);
        C17PacketCustomPayload registerPacket = new C17PacketCustomPayload(snowballsPluginMessageChannel, pb);
        return registerPacket;
    }

    /**
     * Called on join game
     *
     * @param netHandler     Net handler
     * @param joinGamePacket Join game packet
     * @param serverData     ServerData object representing the server being connected to
     * @param realmsServer   If connecting to a realm, a reference to the RealmsServer object
     */
    @Override
    public void onJoinGame(INetHandler netHandler, S01PacketJoinGame joinGamePacket, ServerData serverData,
            RealmsServer realmsServer) {
        sendRegisterPacket = true;
        delayedHelo = DELAYED_HELO_TICKS;
    }

    /**
     * Get the display name
     *
     * @return display name
     */
    @Override
    public String getName() {
        return "SnowBalls";
    }

    /**
     * Return a list of the plugin channels the mod wants to register
     *
     * @return plugin channel names as a list, it is recommended to use {@link ImmutableList#of} for this purpose
     */
    @Override
    public List<String> getChannels() {
        return Arrays.asList(new String[] { snowballsPluginMessageChannel });
    }

    private boolean shouldTick() {
        return LiteLoader.getClientPluginChannels().isRemoteChannelRegistered(snowballsPluginMessageChannel);
    }

    /**
     * Called every frame
     *
     * @param minecraft    Minecraft instance
     * @param partialTicks Partial tick value
     * @param inGame       True if in-game, false if in the menu
     * @param clock        True if this is a new tick, otherwise false if it's a regular frame
     */
    @Override
    public void onTick(Minecraft minecraft, float partialTicks, boolean inGame, boolean clock) {
        if (!inGame)
            return;
        if (!shouldTick())
            return;

        if (sendRegisterPacket) {
            if (delayedHelo == 0) {
                if (DEBUG)
                    log("Sending helo packet");
                minecraft.getNetHandler().addToSendQueue(getRegisterPacket());
                sendRegisterPacket = false;
            } else {
                delayedHelo--;
            }
        }
    }

    /**
     * Called after entities are rendered but before particles
     *
     * @param partialTicks
     */
    @Override
    public void onPostRenderEntities(float partialTicks) {
        searchRenderer.onPostRenderEntities(partialTicks);
    }

    /**
     * Called after all world rendering is completed
     *
     * @param partialTicks
     */
    @Override
    public void onPostRender(float partialTicks) {

    }
}