me.cybermaxke.merchants.v16r3.SMerchant.java Source code

Java tutorial

Introduction

Here is the source code for me.cybermaxke.merchants.v16r3.SMerchant.java

Source

/**
 * This file is part of MerchantsAPI.
 * 
 * Copyright (c) 2014, Cybermaxke
 * 
 * MerchantsAPI 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.
 * 
 * MerchantsAPI 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 MerchantsAPI. If not, see <http://www.gnu.org/licenses/>.
 */
package me.cybermaxke.merchants.v16r3;

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.minecraft.server.v1_6_R3.Container;
import net.minecraft.server.v1_6_R3.EntityHuman;
import net.minecraft.server.v1_6_R3.EntityPlayer;
import net.minecraft.server.v1_6_R3.IMerchant;
import net.minecraft.server.v1_6_R3.ItemStack;
import net.minecraft.server.v1_6_R3.MerchantRecipe;
import net.minecraft.server.v1_6_R3.MerchantRecipeList;
import net.minecraft.server.v1_6_R3.Packet100OpenWindow;
import net.minecraft.server.v1_6_R3.Packet250CustomPayload;

import org.bukkit.craftbukkit.v1_6_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_6_R3.event.CraftEventFactory;
import org.bukkit.entity.Player;
import org.json.simple.parser.ParseException;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import me.cybermaxke.merchants.api.Merchant;
import me.cybermaxke.merchants.api.MerchantOffer;
import me.cybermaxke.merchants.api.MerchantTradeListener;

@SuppressWarnings("unchecked")
public class SMerchant implements IMerchant, Merchant {
    // The recipes list
    private final MerchantRecipeList offers = new MerchantRecipeList();

    // The customers
    private final Set<Player> customers = Sets.newHashSet();

    // The title of the merchant
    private String title;
    private boolean jsonTitle;

    // The title that will be send
    private String sendTitle;

    // The trade handlers
    protected final Set<MerchantTradeListener> handlers = Sets.newHashSet();

    // Internal use only
    protected SMerchantOffer onTrade;

    public SMerchant(String title, boolean jsonTitle) {
        this.setTitle(title, jsonTitle);
    }

    @Override
    public void setTitle(String title, boolean jsonTitle) {
        checkNotNull(title, "title");

        // The old title
        String oldTitle = this.sendTitle;
        String newTitle;

        if (jsonTitle) {
            try {
                newTitle = SUtil.fromJson(title);
            } catch (ParseException e) {
                throw new IllegalArgumentException("invalid json format (" + title + ")", e);
            }
        } else {
            newTitle = title;
        }

        if (title.length() > 32) {
            title = title.substring(0, 32);
        }

        this.sendTitle = newTitle;
        this.jsonTitle = jsonTitle;
        this.title = title;

        // Send a update
        if (!this.sendTitle.equals(oldTitle)) {
            this.sendTitleUpdate();
        }
    }

    @Override
    public void setTitle(String title) {
        this.setTitle(title, false);
    }

    @Override
    public String getTitle() {
        return this.title;
    }

    @Override
    public boolean isTitleJson() {
        return this.jsonTitle;
    }

    @Override
    public boolean addListener(MerchantTradeListener listener) {
        checkNotNull(listener, "listener");
        return this.handlers.add(listener);
    }

    @Override
    public boolean removeListener(MerchantTradeListener listener) {
        checkNotNull(listener, "listener");
        return this.handlers.remove(listener);
    }

    @Override
    public Collection<MerchantTradeListener> getListeners() {
        return Lists.newArrayList(this.handlers);
    }

    @Override
    public int getOffersCount() {
        return this.offers.size();
    }

    @Override
    public MerchantOffer getOfferAt(int index) {
        if (index < 0 || index >= this.offers.size()) {
            throw new IndexOutOfBoundsException(
                    "index (" + index + ") out of bounds min (0) and max (" + this.offers.size() + ")");
        }

        return (MerchantOffer) this.offers.get(index);
    }

    @Override
    public void setOfferAt(int index, MerchantOffer offer) {
        checkNotNull(offer, "offer");

        if (index < 0 || index >= this.offers.size()) {
            throw new IndexOutOfBoundsException(
                    "index (" + index + ") out of bounds min (0) and max (" + this.offers.size() + ")");
        }

        SMerchantOffer old = (SMerchantOffer) this.offers.set(index, offer);
        old.remove(this);

        // Send the new offer list
        this.sendUpdate();
    }

    @Override
    public void insetOfferAt(int index, MerchantOffer offer) {
        checkNotNull(offer, "offer");

        if (index < 0 || index >= this.offers.size()) {
            throw new IndexOutOfBoundsException(
                    "index (" + index + ") out of bounds min (0) and max (" + this.offers.size() + ")");
        }

        this.offers.add(index, offer);
    }

    @Override
    public void removeOffer(MerchantOffer offer) {
        checkNotNull(offer, "offer");

        if (this.offers.remove(offer)) {
            // Unlink the offer
            ((SMerchantOffer) offer).remove(this);

            // Send the new offer list
            this.sendUpdate();
        }
    }

    @Override
    public void removeOffers(Iterable<MerchantOffer> offers) {
        checkNotNull(offers, "offers");

        // Only update if necessary
        if (!offers.iterator().hasNext()) {
            return;
        }

        if (this.offers.removeAll(Lists.newArrayList(offers))) {
            // Unlink the offers
            for (MerchantOffer offer : offers) {
                ((SMerchantOffer) offer).remove(this);
            }

            // Send the new offer list
            this.sendUpdate();
        }
    }

    @Override
    public void addOffer(MerchantOffer offer) {
        checkNotNull(offer, "offer");

        if (this.offers.contains(offer)) {
            return;
        }

        // Add the offer
        this.offers.add(offer);

        // Link the offer
        ((SMerchantOffer) offer).add(this);

        // Send the new offer list
        this.sendUpdate();
    }

    @Override
    public void addOffers(Iterable<MerchantOffer> offers) {
        checkNotNull(offers, "offers");

        // Only update if necessary
        if (!offers.iterator().hasNext()) {
            return;
        }

        // Add and link the offers
        for (MerchantOffer offer : offers) {
            if (this.offers.contains(offer)) {
                continue;
            }
            this.offers.add(offer);
            ((SMerchantOffer) offer).add(this);
        }

        // Send the new offer list
        this.sendUpdate();
    }

    @Override
    public void sortOffers(Comparator<MerchantOffer> comparator) {
        checkNotNull(comparator, "comparator");

        // Only sort if necessary
        if (this.offers.size() <= 1) {
            return;
        }

        // Sort the offers
        Collections.sort(this.offers, comparator);

        // Send the new offer list
        this.sendUpdate();
    }

    @Override
    public List<MerchantOffer> getOffers() {
        return Lists.newArrayList(this.offers);
    }

    @Override
    public boolean addCustomer(Player player) {
        checkNotNull(player, "player");

        if (this.customers.add(player)) {
            EntityPlayer player0 = ((CraftPlayer) player).getHandle();
            Container container0 = null;

            try {
                container0 = new SContainerMerchant(player0, this);
                container0 = CraftEventFactory.callInventoryOpenEvent(player0, container0);
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (container0 == null) {
                this.customers.remove(player);
                return false;
            }

            int window = player0.nextContainerCounter();

            player0.activeContainer = container0;
            player0.activeContainer.windowId = window;
            player0.activeContainer.addSlotListener(player0);

            // Open the window
            player0.playerConnection.sendPacket(new Packet100OpenWindow(window, 6, this.sendTitle, 3, true));

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(baos);

            try {
                // Write the window id
                dos.writeInt(window);
                // Write the offers
                this.offers.a(dos);
                // Flush and close data stream
                dos.flush();
                dos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            // Send the offers
            player0.playerConnection.sendPacket(new Packet250CustomPayload("MC|TrList", baos.toByteArray()));
            return true;
        }

        return false;
    }

    @Override
    public boolean removeCustomer(Player player) {
        checkNotNull(player, "player");

        if (this.customers.remove(player)) {
            player.closeInventory();
            return true;
        }

        return false;
    }

    @Override
    public boolean hasCustomer(Player player) {
        checkNotNull(player, "player");
        return this.customers.contains(player);
    }

    @Override
    public Collection<Player> getCustomers() {
        return Lists.newArrayList(this.customers);
    }

    @Override
    public MerchantRecipeList getOffers(EntityHuman human) {
        return this.offers;
    }

    @Override
    public void a(MerchantRecipe recipe) {
        // Increment uses
        recipe.f();

        // Used by the custom merchant result slot
        this.onTrade = (SMerchantOffer) recipe;
    }

    @Override
    public void a_(EntityHuman arg0) {
        // Not used
    }

    @Override
    public void a_(ItemStack arg0) {
        // Not used
    }

    @Override
    public EntityHuman m_() {
        // Not used
        return null;
    }

    protected void sendTitleUpdate() {
        // Re-send the open window message to update the window name
        Iterator<Player> it = this.customers.iterator();
        while (it.hasNext()) {
            EntityPlayer player0 = ((CraftPlayer) it.next()).getHandle();
            player0.playerConnection.sendPacket(
                    new Packet100OpenWindow(player0.activeContainer.windowId, 6, this.sendTitle, 3, true));
            player0.updateInventory(player0.activeContainer);
        }
    }

    // Called when the merchant requires a update
    protected void sendUpdate() {
        if (this.customers.isEmpty()) {
            return;
        }

        ByteArrayOutputStream baos0 = new ByteArrayOutputStream();
        DataOutputStream dos0 = new DataOutputStream(baos0);

        // Write the recipe list
        this.offers.a(dos0);

        try {
            dos0.flush();
            dos0.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Get the bytes
        byte[] data = baos0.toByteArray();

        // Send a packet to all the players
        Iterator<Player> it = this.customers.iterator();
        while (it.hasNext()) {
            EntityPlayer player0 = ((CraftPlayer) it.next()).getHandle();

            // Every player has a different window id
            ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
            DataOutputStream dos1 = new DataOutputStream(baos1);

            try {
                dos1.writeInt(player0.activeContainer.windowId);
                dos1.write(data);
                dos1.flush();
                dos1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            player0.playerConnection.sendPacket(new Packet250CustomPayload("MC|TrList", baos1.toByteArray()));
        }
    }
}