diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..50f7651
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) [2023] [Jiří Apjár]
+Copyright (c) [2023] [Filip Zeman]
+
+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.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..924a9fd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,158 @@
+# ForestChannelAPI
+![badge](https://img.shields.io/github/v/release/ForestTechMC/ForestChannelAPI)
+[![badge](https://jitpack.io/v/ForestTechMC/ForestChannelAPI.svg)](https://jitpack.io/#ForestTechMC/ForestChannelAPI)
+![badge](https://img.shields.io/github/downloads/ForestTechMC/ForestChannelAPI/total)
+![badge](https://img.shields.io/github/last-commit/ForestTechMC/ForestChannelAPI)
+![badge](https://img.shields.io/badge/platform-spigot%20%7C%20bungeecord-lightgrey)
+[![badge](https://img.shields.io/discord/896466173166747650?label=discord)](https://discord.gg/2PpdrfxhD4)
+[![badge](https://img.shields.io/github/license/ForestTechMC/ForestChannelAPI)](https://github.com/ForestTechMC/ForestChannelAPI/blob/master/LICENSE.txt)
+
+**[JavaDoc 1.0](https://foresttechmc.github.io/ForestChannelAPI/1.1/)**
+
+Have you ever had a problem with channels in plugins? (I had)
+That's why I want to introduce you ForestChannelAPI.
+For usage on larger projects, we recommend more using Redis together with our [ForestRedisAPI](https://github.com/ForestTechMC/ForestRedisAPI) instead.
+
+## Table of contents
+
+* [Getting started](#getting-started)
+* [Example of events](#example-of-events)
+* [Example of manager](#using-color-api)
+* [Example in project](#using-color-api)
+* [License](#license)
+
+## Getting started
+
+Make sure you reloaded maven or gradle in your project.
+
+### We recommend more using Redis API
+
+The problem in channels at all is
+we need some online player to send information to Bungee x Spigot or Spigot x Bungee
+Our API for Redis [ForestRedisAPI](https://github.com/ForestTechMC/ForestRedisAPI)
+
+### Add ForestChannelAPI to your project
+
+[![badge](https://jitpack.io/v/ForestTechMC/ForestChannelAPI.svg)](https://jitpack.io/#ForestTechMC/ForestChannelAPI)
+
+You need to add this dependency into your plugin, then look at under the dependencies example
+
+
+ Maven
+
+```xml
+
+
+ jitpack.io
+ https://jitpack.io
+
+
+
+
+
+ com.github.ForestTechMC
+ ForestChannelAPI
+ VERSION
+ provided
+
+
+```
+
+
+
+ Gradle
+
+```gradle
+allprojects {
+ repositories {
+ ...
+ maven { url 'https://jitpack.io' }
+ }
+}
+
+dependencies {
+ implementation 'com.github.ForestTechMC:ForestChannelAPI:VERSION'
+}
+```
+
+
+### Example of events
+
+
+ Example of events
+
+```java
+ // Bungee custom event
+ @EventHandler
+ public void onChannel(ChannelEvent event) {
+ ProxiedPlayer player = event.getSender();
+ String channel = event.getChannel();
+ String message = event.getMessage();
+
+ System.out.println("Our first sender: " + player.getName()); // The person we send from that information
+ System.out.println("Our first channel name: " + channel); // Channel name :
+ System.out.println("Our first message from that channel: " + message); // Message "Omg its working!"
+ }
+
+ // Spigot custom event
+ @EventHandler
+ public void onChannel(ChannelEvent event) {
+ Player player = event.getPlayer();
+ String channel = event.getChannel();
+ String message = event.getMessage();
+
+ System.out.println("Our first sender: " + player.getName()); // The person we send from that information
+ System.out.println("Our first channel name: " + channel); // Channel name :
+ System.out.println("Our first message from that channel: " + message); // Message "Omg its working!"
+ }
+```
+
+
+### Using Channel API
+
+
+ Using API
+
+```java
+ // Import for Bungee
+ import cz.foresttech.api.bungee.taker.ChannelAPI;
+ // Spigot instance
+ private static Bungee instance;
+
+ private ChannelAPI channelAPI;
+
+ @Override
+ public void onEnable() {
+ instance = this;
+
+ channelAPI = new ChannelAPI(this);
+ channelAPI.register("");
+
+ }
+
+ // Import for Spigot
+ import cz.foresttech.api.spigot.taker.ChannelAPI;
+
+ // Bungee instance
+ private static Spigot instance;
+
+ private ChannelAPI channelAPI;
+
+ @Override
+ public void onEnable() {
+ instance = this;
+
+ channelAPI = new ChannelAPI(this);
+ channelAPI.register("");
+ }
+
+ // GLOBAL (Bungee & Spigot)
+
+ // Send method
+ getChannelAPI().send(player, "", "");
+ getChannelAPI().registerEvent(this, new SuperEvent());
+```
+
+
+## License
+ForestChannelAPI is licensed under the permissive MIT license. Please see [`LICENSE.txt`](https://github.com/ForestTechMC/ForestChannelAPI/blob/master/LICENSE.txt) for more information.
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..799ff0e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+ cz.foresttech
+ ForestChannelAPI
+ 1.0.0
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ jitpack.io
+ https://jitpack.io
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+ bungeecord-repo
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+
+
+
+ net.md-5
+ bungeecord-api
+ 1.19-R0.1-SNAPSHOT
+ jar
+ provided
+
+
+ org.projectlombok
+ lombok
+ 1.18.22
+ compile
+
+
+ org.spigotmc
+ spigot-api
+ 1.19-R0.1-SNAPSHOT
+ provided
+
+
+
\ No newline at end of file
diff --git a/src/main/java/cz/foresttech/api/bungee/events/ChannelEvent.java b/src/main/java/cz/foresttech/api/bungee/events/ChannelEvent.java
new file mode 100644
index 0000000..61affe3
--- /dev/null
+++ b/src/main/java/cz/foresttech/api/bungee/events/ChannelEvent.java
@@ -0,0 +1,42 @@
+package cz.foresttech.api.bungee.events;
+
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Event;
+
+public class ChannelEvent extends Event{
+ private final String channel;
+ private final String message;
+ private final ProxiedPlayer sender;
+ private final Connection senderCon;
+ private final Connection receiverCon;
+
+ public ChannelEvent(String channel, String message, ProxiedPlayer sender, Connection senderCon, Connection receiverCon) {
+ this.channel = channel;
+ this.message = message;
+ this.sender = sender;
+ this.senderCon = senderCon;
+ this.receiverCon = receiverCon;
+ }
+
+ public ProxiedPlayer getSender() {
+ return sender;
+ }
+
+ public Connection getSenderCon() {
+ return senderCon;
+ }
+
+ public Connection getReceiverCon() {
+ return receiverCon;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/src/main/java/cz/foresttech/api/bungee/events/ChannelHandler.java b/src/main/java/cz/foresttech/api/bungee/events/ChannelHandler.java
new file mode 100644
index 0000000..d2a91e1
--- /dev/null
+++ b/src/main/java/cz/foresttech/api/bungee/events/ChannelHandler.java
@@ -0,0 +1,56 @@
+package cz.foresttech.api.bungee.events;
+
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.PluginMessageEvent;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.api.plugin.Plugin;
+import net.md_5.bungee.event.EventHandler;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Collection;
+
+
+public class ChannelHandler implements Listener {
+
+ private Plugin plugin;
+
+ public ChannelHandler(Plugin plugin) {
+ this.plugin = plugin;
+ }
+
+ /**
+ *
+ * This is our caller for custom event
+ * We did this for better manipulation with content
+ *
+ * @param event Official plugin message event
+ */
+ @EventHandler
+ public void onPluginMessageEvent(PluginMessageEvent event) {
+ if (event.getTag().startsWith("minecraft")) {
+ return;
+ }
+
+ DataInputStream stream = new DataInputStream(new ByteArrayInputStream(event.getData()));
+
+ String message;
+ String playerName;
+ try {
+ stream.readUTF();
+ playerName = stream.readUTF();
+ message = stream.readUTF();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ ProxiedPlayer player = ProxyServer.getInstance().getPlayer(playerName);
+ if (player == null && !player.isConnected()) {
+ Collection players = ProxyServer.getInstance().getPlayers();
+ player = players.stream().findFirst().get();
+ }
+ plugin.getProxy().getPluginManager().callEvent(new ChannelEvent(event.getTag(), message, player, event.getSender(), event.getReceiver()));
+ }
+
+}
diff --git a/src/main/java/cz/foresttech/api/bungee/taker/ChannelAPI.java b/src/main/java/cz/foresttech/api/bungee/taker/ChannelAPI.java
new file mode 100644
index 0000000..43b58c3
--- /dev/null
+++ b/src/main/java/cz/foresttech/api/bungee/taker/ChannelAPI.java
@@ -0,0 +1,114 @@
+package cz.foresttech.api.bungee.taker;
+
+import com.google.common.io.ByteArrayDataOutput;
+import com.google.common.io.ByteStreams;
+import cz.foresttech.api.bungee.events.ChannelHandler;
+import cz.foresttech.api.shared.ChannelTaker;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.api.plugin.Plugin;
+
+import java.util.Collection;
+
+public class ChannelAPI implements ChannelTaker {
+
+ private Plugin plugin;
+
+ public ChannelAPI(Plugin plugin) {
+ this.plugin = plugin;
+ registerEvent(plugin, new ChannelHandler(plugin));
+ }
+
+ /**
+ *
+ * Send method for Bungee -> Spigot
+ *
+ * @param player sender
+ * @param channel channel for
+ * @param message content
+ */
+ @Override
+ public void send(Object player, String channel, String message) {
+ ProxiedPlayer sender = (ProxiedPlayer) player;
+
+ ByteArrayDataOutput output = ByteStreams.newDataOutput();
+
+ output.writeUTF("Message");
+ output.writeUTF(message);
+ sender.getServer().getInfo().sendData(getChannel(channel), output.toByteArray());
+ }
+
+ /**
+ *
+ * This returns channel with prefix of plugin
+ * This is important part
+ *
+ */
+ @Override
+ public String getChannel(String channelName) {
+ return (plugin.getDescription().getName() + ":" + channelName).toLowerCase();
+ }
+
+ /**
+ *
+ * This remove prefix of plugin
+ *
+ */
+ @Override
+ public String removeTag(String channelWithTag) {
+ channelWithTag = channelWithTag.replace(plugin.getDescription().getName().toLowerCase() + ":", "");
+ return channelWithTag;
+ }
+
+ /**
+ *
+ * This register messenger for spigot
+ *
+ */
+ @Override
+ public void register(String channel) {
+ channel = getChannel(channel);
+
+ if (plugin.getProxy().getChannels().contains(channel)) {
+ return;
+ }
+
+ plugin.getProxy().registerChannel(channel);
+ }
+
+ /**
+ *
+ * This unregister messenger for spigot
+ *
+ */
+ @Override
+ public void unregister(String channel) {
+ channel = getChannel(channel);
+
+ if (!plugin.getProxy().getChannels().contains(channel)) {
+ return;
+ }
+
+ plugin.getProxy().unregisterChannel(channel);
+ }
+
+ /**
+ *
+ * Method only for register event
+ *
+ */
+ @Override
+ public void registerEvent(Object plugin, Object listener) {
+ this.plugin.getProxy().getPluginManager().registerListener((Plugin) plugin, (Listener) listener);
+ }
+
+ /**
+ *
+ * This only returns channels from out list
+ *
+ */
+ @Override
+ public Collection getChannels() {
+ return plugin.getProxy().getChannels();
+ }
+}
diff --git a/src/main/java/cz/foresttech/api/shared/ChannelTaker.java b/src/main/java/cz/foresttech/api/shared/ChannelTaker.java
new file mode 100644
index 0000000..67f527c
--- /dev/null
+++ b/src/main/java/cz/foresttech/api/shared/ChannelTaker.java
@@ -0,0 +1,28 @@
+package cz.foresttech.api.shared;
+
+import java.util.Collection;
+
+/**
+ *
+ * Typical interface
+ *
+ */
+public interface ChannelTaker {
+
+ void send(Object player, String channel, String message);
+
+ void register(String name);
+
+ void unregister(String name);
+
+ void registerEvent(Object plugin, Object listener);
+
+ String getChannel(String channelName);
+
+ String removeTag(String channelWithTag);
+
+ Collection getChannels();
+
+
+
+}
diff --git a/src/main/java/cz/foresttech/api/spigot/events/ChannelEvent.java b/src/main/java/cz/foresttech/api/spigot/events/ChannelEvent.java
new file mode 100644
index 0000000..ddd0bb5
--- /dev/null
+++ b/src/main/java/cz/foresttech/api/spigot/events/ChannelEvent.java
@@ -0,0 +1,40 @@
+package cz.foresttech.api.spigot.events;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class ChannelEvent extends Event {
+
+ private static final HandlerList HANDLERS = new HandlerList();
+ private final Player player;
+ private final String channel;
+ private final String message;
+
+ public ChannelEvent(Player player, String channel, String message) {
+ this.player = player;
+ this.channel = channel;
+ this.message = message;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+}
diff --git a/src/main/java/cz/foresttech/api/spigot/events/ChannelHandler.java b/src/main/java/cz/foresttech/api/spigot/events/ChannelHandler.java
new file mode 100644
index 0000000..23608a4
--- /dev/null
+++ b/src/main/java/cz/foresttech/api/spigot/events/ChannelHandler.java
@@ -0,0 +1,37 @@
+package cz.foresttech.api.spigot.events;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.messaging.PluginMessageListener;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+public class ChannelHandler implements PluginMessageListener {
+
+ /**
+ *
+ * Universal Plugin listener for messages
+ *
+ * @param channel from
+ * @param player sender
+ * @param bytes message
+ */
+ @Override
+ public void onPluginMessageReceived(String channel, Player player, byte[] bytes) {
+ DataInputStream stream = new DataInputStream(new ByteArrayInputStream(bytes));
+ String message;
+ try {
+ stream.readUTF();
+ message = stream.readUTF();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ ChannelEvent channelEvent = new ChannelEvent(player, channel, message);
+ Bukkit.getPluginManager().callEvent(channelEvent);
+
+ }
+
+}
diff --git a/src/main/java/cz/foresttech/api/spigot/taker/ChannelAPI.java b/src/main/java/cz/foresttech/api/spigot/taker/ChannelAPI.java
new file mode 100644
index 0000000..111a297
--- /dev/null
+++ b/src/main/java/cz/foresttech/api/spigot/taker/ChannelAPI.java
@@ -0,0 +1,123 @@
+package cz.foresttech.api.spigot.taker;
+
+import cz.foresttech.api.shared.ChannelTaker;
+import cz.foresttech.api.spigot.events.ChannelHandler;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Listener;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+
+public class ChannelAPI implements ChannelTaker {
+
+ private JavaPlugin plugin;
+
+ public ChannelAPI(JavaPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ /**
+ *
+ * Send method for Spigot -> Bungee
+ *
+ * @param player sender
+ * @param channel channel for
+ * @param message content
+ */
+ @Override
+ public void send(Object player, String channel, String message) {
+ Player sender = (Player) player;
+
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ DataOutputStream output = new DataOutputStream(stream);
+
+ try {
+ output.writeUTF("Message");
+ output.writeUTF(sender.getName());
+ output.writeUTF(message);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ sender.sendPluginMessage(plugin, getChannel(channel), stream.toByteArray());
+ }
+
+ /**
+ *
+ * This returns channel with prefix of plugin
+ * This is important part
+ *
+ */
+ @Override
+ public String getChannel(String channelName) {
+ return (plugin.getDescription().getName() + ":" + channelName).toLowerCase();
+ }
+
+ /**
+ *
+ * This remove prefix of plugin
+ *
+ */
+ @Override
+ public String removeTag(String channelWithTag) {
+ channelWithTag = channelWithTag.replace(plugin.getDescription().getName().toLowerCase() + ":", "");
+ return channelWithTag;
+ }
+
+ /**
+ *
+ * Method only for register event
+ *
+ */
+ @Override
+ public void registerEvent(Object plugin, Object listener) {
+ Bukkit.getServer().getPluginManager().registerEvents((Listener) listener, (JavaPlugin) plugin);
+ }
+
+ /**
+ *
+ * This register messenger for spigot
+ *
+ */
+ @Override
+ public void register(String channelName) {
+ String channel = getChannel(channelName);
+
+ if (Bukkit.getMessenger().getOutgoingChannels().contains(channel)) {
+ return;
+ }
+
+ Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, channel);
+ Bukkit.getMessenger().registerIncomingPluginChannel(plugin, channel, new ChannelHandler());
+ }
+
+ /**
+ *
+ * This unregister messenger for spigot
+ *
+ */
+ @Override
+ public void unregister(String channelName) {
+ String channel = getChannel(channelName);
+
+ if (Bukkit.getMessenger().getOutgoingChannels().contains(channel)) {
+ return;
+ }
+
+ Bukkit.getMessenger().unregisterOutgoingPluginChannel(plugin, channel);
+ Bukkit.getMessenger().unregisterIncomingPluginChannel(plugin, channel, new ChannelHandler());
+ }
+
+ /**
+ *
+ * This only returns channels from out list
+ *
+ */
+ @Override
+ public Collection getChannels() {
+ return Bukkit.getMessenger().getOutgoingChannels();
+ }
+}