Merge remote-tracking branch 'origin/master' into server-language-processing

This commit is contained in:
rtm516 2020-04-09 13:58:45 +01:00
commit c51a48221b
21 changed files with 569 additions and 45 deletions

View file

@ -49,6 +49,8 @@ import java.net.InetSocketAddress;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -61,7 +63,7 @@ public class GeyserConnector {
public static final String NAME = "Geyser";
public static final String VERSION = "1.0-SNAPSHOT";
private final Map<Object, GeyserSession> players = new HashMap<>();
private final Map<UUID, GeyserSession> players = new HashMap<>();
private static GeyserConnector instance;
@ -141,6 +143,40 @@ public class GeyserConnector {
bootstrap.getGeyserLogger().info("Shutting down Geyser.");
shuttingDown = true;
if (players.size() >= 1) {
bootstrap.getGeyserLogger().info("Kicking " + players.size() + " player(s)");
for (GeyserSession playerSession : players.values()) {
playerSession.disconnect("Geyser Proxy shutting down.");
}
CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {
@Override
public void run() {
// Simulate a long-running Job
try {
while (true) {
if (players.size() == 0) {
return;
}
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
});
// Block and wait for the future to complete
try {
future.get();
bootstrap.getGeyserLogger().info("Kicked all players");
} catch (Exception e) {
// Quietly fail
}
}
generalThreadPool.shutdown();
bedrockServer.close();
players.clear();
@ -148,18 +184,16 @@ public class GeyserConnector {
authType = null;
commandMap.getCommands().clear();
commandMap = null;
bootstrap.getGeyserLogger().info("Geyser shutdown successfully.");
}
public void addPlayer(GeyserSession player) {
players.put(player.getAuthData().getName(), player);
players.put(player.getAuthData().getUUID(), player);
players.put(player.getSocketAddress(), player);
}
public void removePlayer(GeyserSession player) {
players.remove(player.getAuthData().getName());
players.remove(player.getAuthData().getUUID());
players.remove(player.getSocketAddress());
}
public static GeyserConnector start(PlatformType platformType, IGeyserBootstrap bootstrap) {

View file

@ -48,6 +48,11 @@ public class StopCommand extends GeyserCommand {
if (!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE) {
return;
}
connector.shutdown();
if (connector.getPlatformType() == PlatformType.STANDALONE) {
System.exit(0);
}
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.EntityData;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.translators.block.BlockTranslator;
public class FallingBlockEntity extends Entity {
public FallingBlockEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, int javaId) {
super(entityId, geyserId, entityType, position, motion, rotation);
this.metadata.put(EntityData.VARIANT, BlockTranslator.getBedrockBlockId(javaId));
}
}

View file

@ -42,6 +42,8 @@ public class BeeEntity extends AnimalEntity {
if (entityMetadata.getId() == 16) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02);
// If the bee has nectar or not
metadata.getFlags().setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08);
}
super.updateBedrockMetadata(entityMetadata, session);
}

View file

@ -25,12 +25,52 @@
package org.geysermc.connector.entity.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.EntityData;
import com.nukkitx.protocol.bedrock.data.ItemData;
import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.block.BlockTranslator;
public class LlamaEntity extends ChestedHorseEntity {
public LlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Strength
if (entityMetadata.getId() == 19) {
metadata.put(EntityData.STRENGTH, entityMetadata.getValue());
}
// Color equipped on the llama
if (entityMetadata.getId() == 20) {
// Bedrock treats llama decoration as armor
MobArmorEquipmentPacket equipmentPacket = new MobArmorEquipmentPacket();
equipmentPacket.setRuntimeEntityId(getGeyserId());
// -1 means no armor
if ((int) entityMetadata.getValue() != -1) {
// The damage value is the dye color that Java sends us
// Always going to be a carpet so we can hardcode 171 in BlockTranslator
// The int then short conversion is required or we get a ClassCastException
equipmentPacket.setChestplate(ItemData.of(BlockTranslator.CARPET, (short)((int) entityMetadata.getValue()), 1));
} else {
equipmentPacket.setChestplate(ItemData.AIR);
}
// Required to fill out the rest of the equipment or Bedrock ignores it, including above else statement if removing armor
equipmentPacket.setBoots(ItemData.AIR);
equipmentPacket.setHelmet(ItemData.AIR);
equipmentPacket.setLeggings(ItemData.AIR);
session.getUpstream().sendPacket(equipmentPacket);
}
// Color of the llama
if (entityMetadata.getId() == 21) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.entity.living.animal.horse;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.EntityData;
import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
public class TraderLlamaEntity extends LlamaEntity {
public TraderLlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
}
@Override
public void spawnEntity(GeyserSession session) {
// The trader llama is a separate entity from the llama in Java but a normal llama with extra metadata in Bedrock.
AddEntityPacket addEntityPacket = new AddEntityPacket();
addEntityPacket.setIdentifier("minecraft:llama");
addEntityPacket.setRuntimeEntityId(geyserId);
addEntityPacket.setUniqueEntityId(geyserId);
addEntityPacket.setPosition(position);
addEntityPacket.setMotion(motion);
addEntityPacket.setRotation(getBedrockRotation());
addEntityPacket.setEntityType(entityType.getType());
addEntityPacket.getMetadata().putAll(metadata);
// Here's the difference
addEntityPacket.getMetadata().put(EntityData.MARK_VARIANT, 1);
valid = true;
session.getUpstream().sendPacket(addEntityPacket);
session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
}
}

View file

@ -31,10 +31,7 @@ import org.geysermc.connector.entity.living.*;
import org.geysermc.connector.entity.living.animal.*;
import org.geysermc.connector.entity.living.animal.tameable.CatEntity;
import org.geysermc.connector.entity.living.animal.tameable.TameableEntity;
import org.geysermc.connector.entity.living.animal.horse.AbstractHorseEntity;
import org.geysermc.connector.entity.living.animal.horse.ChestedHorseEntity;
import org.geysermc.connector.entity.living.animal.horse.HorseEntity;
import org.geysermc.connector.entity.living.animal.horse.LlamaEntity;
import org.geysermc.connector.entity.living.animal.horse.*;
import org.geysermc.connector.entity.living.animal.tameable.WolfEntity;
import org.geysermc.connector.entity.living.monster.*;
import org.geysermc.connector.entity.living.monster.raid.AbstractIllagerEntity;
@ -64,7 +61,7 @@ public enum EntityType {
ZOMBIE_HORSE(AbstractHorseEntity.class, 27, 1.6f, 1.3965f),
POLAR_BEAR(PolarBearEntity.class, 28, 1.4f, 1.3f),
LLAMA(LlamaEntity.class, 29, 1.87f, 0.9f),
TRADER_LLAMA(LlamaEntity.class, 29, 1.187f, 0.9f),
TRADER_LLAMA(TraderLlamaEntity.class, 29, 1.187f, 0.9f),
PARROT(TameableEntity.class, 30, 0.9f, 0.5f),
DOLPHIN(WaterEntity.class, 31, 0.6f, 0.9f),
ZOMBIE(ZombieEntity.class, 32, 1.8f, 0.6f, 0.6f, 1.62f),
@ -103,7 +100,7 @@ public enum EntityType {
PLAYER(PlayerEntity.class, 63, 1.8f, 0.6f, 0.6f, 1.62f),
ITEM(ItemEntity.class, 64, 0.25f, 0.25f),
TNT(Entity.class, 65, 0.98f, 0.98f),
FALLING_BLOCK(Entity.class, 66, 0.98f, 0.98f),
FALLING_BLOCK(FallingBlockEntity.class, 66, 0.98f, 0.98f),
MOVING_BLOCK(Entity.class, 67, 0f),
EXPERIENCE_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f),
EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f),

View file

@ -26,6 +26,7 @@
package org.geysermc.connector.network.session;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsException;
import com.github.steveice10.mc.auth.exception.request.RequestException;
import com.github.steveice10.mc.protocol.MinecraftProtocol;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
@ -285,6 +286,9 @@ public class GeyserSession implements CommandSender {
downstream.getSession().connect();
connector.addPlayer(this);
} catch (InvalidCredentialsException e) {
connector.getLogger().info("User '" + username + "' entered invalid login info, kicking.");
disconnect("Invalid/incorrect login info");
} catch (RequestException ex) {
ex.printStackTrace();
}

View file

@ -41,6 +41,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
import org.geysermc.connector.network.translators.block.BlockTranslator;
@Translator(packet = InventoryTransactionPacket.class)
public class BedrockInventoryTransactionTranslator extends PacketTranslator<InventoryTransactionPacket> {
@ -61,11 +62,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
break;
case ITEM_RELEASE:
if (packet.getActionType() == 0) {
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(
packet.getBlockPosition().getX(),
packet.getBlockPosition().getY(),
packet.getBlockPosition().getZ()
), BlockFace.values()[packet.getFace()]);
// Followed to the Minecraft Protocol specification outlined at wiki.vg
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0,0,0),
BlockFace.DOWN);
session.getDownstream().getSession().send(releaseItemPacket);
}
break;

View file

@ -34,7 +34,7 @@ import org.geysermc.connector.utils.SkinUtils;
import com.nukkitx.protocol.bedrock.packet.SetLocalPlayerAsInitializedPacket;
@Translator(packet = SetLocalPlayerAsInitializedPacket.class)
public class BedrockPlayerInitializedTranslator extends PacketTranslator<SetLocalPlayerAsInitializedPacket> {
public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslator<SetLocalPlayerAsInitializedPacket> {
@Override
public void translate(SetLocalPlayerAsInitializedPacket packet, GeyserSession session) {
if (session.getPlayerEntity().getGeyserId() == packet.getRuntimeEntityId()) {

View file

@ -55,6 +55,9 @@ public class BlockTranslator {
private static final Int2ObjectMap<BlockState> BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>();
private static final IntSet WATERLOGGED = new IntOpenHashSet();
// Bedrock carpet ID, used in LlamaEntity.java for decoration
public static final int CARPET = 171;
private static final int BLOCK_STATE_VERSION = 17760256;
static {
@ -177,6 +180,10 @@ public class BlockTranslator {
return JAVA_TO_BEDROCK_BLOCK_MAP.get(state.getId());
}
public static int getBedrockBlockId(int javaId) {
return JAVA_TO_BEDROCK_BLOCK_MAP.get(javaId);
}
public static BlockState getJavaBlockState(int bedrockId) {
return BEDROCK_TO_JAVA_BLOCK_MAP.get(bedrockId);
}

View file

@ -72,7 +72,16 @@ public class ItemTranslator {
if (stack.getNbt() == null) {
return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount());
}
return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount(), translateToBedrockNBT(stack.getNbt()));
// TODO: Create proper transformers instead of shoving everything here
CompoundTag tag = stack.getNbt();
IntTag mapId = tag.get("map");
if (mapId != null)
tag.put(new StringTag("map_uuid", mapId.getValue().toString()));
return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount(), translateToBedrockNBT(tag));
}
public ItemEntry getItem(ItemStack stack) {

View file

@ -28,7 +28,9 @@ package org.geysermc.connector.network.translators.java.entity.spawn;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import com.github.steveice10.mc.protocol.data.game.entity.type.object.FallingBlockData;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.FallingBlockEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
@ -59,12 +61,18 @@ public class JavaSpawnObjectTranslator extends PacketTranslator<ServerSpawnObjec
Class<? extends Entity> entityClass = type.getEntityClass();
try {
Constructor<? extends Entity> entityConstructor = entityClass.getConstructor(long.class, long.class, EntityType.class,
Vector3f.class, Vector3f.class, Vector3f.class);
Entity entity;
if (packet.getType() == ObjectType.FALLING_BLOCK) {
entity = new FallingBlockEntity(packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
type, position, motion, rotation, ((FallingBlockData) packet.getData()).getId());
} else {
Constructor<? extends Entity> entityConstructor = entityClass.getConstructor(long.class, long.class, EntityType.class,
Vector3f.class, Vector3f.class, Vector3f.class);
Entity entity = entityConstructor.newInstance(packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
type, position, motion, rotation
);
entity = entityConstructor.newInstance(packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
type, position, motion, rotation
);
}
session.getEntityCache().spawnEntity(entity);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.network.translators.java.world;
import com.github.steveice10.mc.protocol.data.game.world.map.MapData;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerMapDataPacket;
import com.nukkitx.protocol.bedrock.packet.ClientboundMapItemDataPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.utils.MapColor;
@Translator(packet = ServerMapDataPacket.class)
public class JavaMapDataTranslator extends PacketTranslator<ServerMapDataPacket> {
@Override
public void translate(ServerMapDataPacket packet, GeyserSession session) {
ClientboundMapItemDataPacket mapItemDataPacket = new ClientboundMapItemDataPacket();
mapItemDataPacket.setUniqueMapId(packet.getMapId());
mapItemDataPacket.setDimensionId(session.getPlayerEntity().getDimension());
mapItemDataPacket.setLocked(packet.isLocked());
mapItemDataPacket.setScale(packet.getScale());
MapData data = packet.getData();
if (data != null) {
mapItemDataPacket.setXOffset(data.getX());
mapItemDataPacket.setYOffset(data.getY());
mapItemDataPacket.setWidth(data.getColumns());
mapItemDataPacket.setHeight(data.getRows());
// Every int entry is an ARGB color
int[] colors = new int[data.getData().length];
int idx = 0;
for (byte colorId : data.getData()) {
colors[idx] = MapColor.fromId(colorId).toARGB();
idx++;
}
mapItemDataPacket.setColors(colors);
}
session.getUpstream().getSession().sendPacket(mapItemDataPacket);
}
}

View file

@ -0,0 +1,244 @@
package org.geysermc.connector.utils;
import java.util.Arrays;
public enum MapColor {
COLOR_0(-1, -1, -1),
COLOR_1(-1, -1, -1),
COLOR_2(-1, -1, -1),
COLOR_3(-1, -1, -1),
COLOR_4(89, 125, 39),
COLOR_5(109, 153, 48),
COLOR_6(127, 178, 56),
COLOR_7(67, 94, 29),
COLOR_8(174, 164, 115),
COLOR_9(213, 201, 140),
COLOR_10(247, 233, 163),
COLOR_11(130, 123, 86),
COLOR_12(140, 140, 140),
COLOR_13(171, 171, 171),
COLOR_14(199, 199, 199),
COLOR_15(105, 105, 105),
COLOR_16(180, 0, 0),
COLOR_17(220, 0, 0),
COLOR_18(255, 0, 0),
COLOR_19(135, 0, 0),
COLOR_20(112, 112, 180),
COLOR_21(138, 138, 220),
COLOR_22(160, 160, 255),
COLOR_23(84, 84, 135),
COLOR_24(117, 117, 117),
COLOR_25(144, 144, 144),
COLOR_26(167, 167, 167),
COLOR_27(88, 88, 88),
COLOR_28(0, 87, 0),
COLOR_29(0, 106, 0),
COLOR_30(0, 124, 0),
COLOR_31(0, 65, 0),
COLOR_32(180, 180, 180),
COLOR_33(220, 220, 220),
COLOR_34(255, 255, 255),
COLOR_35(135, 135, 135),
COLOR_36(115, 118, 129),
COLOR_37(141, 144, 158),
COLOR_38(164, 168, 184),
COLOR_39(86, 88, 97),
COLOR_40(106, 76, 54),
COLOR_41(130, 94, 66),
COLOR_42(151, 109, 77),
COLOR_43(79, 57, 40),
COLOR_44(79, 79, 79),
COLOR_45(96, 96, 96),
COLOR_46(112, 112, 112),
COLOR_47(59, 59, 59),
COLOR_48(45, 45, 180),
COLOR_49(55, 55, 220),
COLOR_50(64, 64, 255),
COLOR_51(33, 33, 135),
COLOR_52(100, 84, 50),
COLOR_53(123, 102, 62),
COLOR_54(143, 119, 72),
COLOR_55(75, 63, 38),
COLOR_56(180, 177, 172),
COLOR_57(220, 217, 211),
COLOR_58(255, 252, 245),
COLOR_59(135, 133, 129),
COLOR_60(152, 89, 36),
COLOR_61(186, 109, 44),
COLOR_62(216, 127, 51),
COLOR_63(114, 67, 27),
COLOR_64(125, 53, 152),
COLOR_65(153, 65, 186),
COLOR_66(178, 76, 216),
COLOR_67(94, 40, 114),
COLOR_68(72, 108, 152),
COLOR_69(88, 132, 186),
COLOR_70(102, 153, 216),
COLOR_71(54, 81, 114),
COLOR_72(161, 161, 36),
COLOR_73(197, 197, 44),
COLOR_74(229, 229, 51),
COLOR_75(121, 121, 27),
COLOR_76(89, 144, 17),
COLOR_77(109, 176, 21),
COLOR_78(127, 204, 25),
COLOR_79(67, 108, 13),
COLOR_80(170, 89, 116),
COLOR_81(208, 109, 142),
COLOR_82(242, 127, 165),
COLOR_83(128, 67, 87),
COLOR_84(53, 53, 53),
COLOR_85(65, 65, 65),
COLOR_86(76, 76, 76),
COLOR_87(40, 40, 40),
COLOR_88(108, 108, 108),
COLOR_89(132, 132, 132),
COLOR_90(153, 153, 153),
COLOR_91(81, 81, 81),
COLOR_92(53, 89, 108),
COLOR_93(65, 109, 132),
COLOR_94(76, 127, 153),
COLOR_95(40, 67, 81),
COLOR_96(89, 44, 125),
COLOR_97(109, 54, 153),
COLOR_98(127, 63, 178),
COLOR_99(67, 33, 94),
COLOR_100(36, 53, 125),
COLOR_101(44, 65, 153),
COLOR_102(51, 76, 178),
COLOR_103(27, 40, 94),
COLOR_104(72, 53, 36),
COLOR_105(88, 65, 44),
COLOR_106(102, 76, 51),
COLOR_107(54, 40, 27),
COLOR_108(72, 89, 36),
COLOR_109(88, 109, 44),
COLOR_110(102, 127, 51),
COLOR_111(54, 67, 27),
COLOR_112(108, 36, 36),
COLOR_113(132, 44, 44),
COLOR_114(153, 51, 51),
COLOR_115(81, 27, 27),
COLOR_116(17, 17, 17),
COLOR_117(21, 21, 21),
COLOR_118(25, 25, 25),
COLOR_119(13, 13, 13),
COLOR_120(176, 168, 54),
COLOR_121(215, 205, 66),
COLOR_122(250, 238, 77),
COLOR_123(132, 126, 40),
COLOR_124(64, 154, 150),
COLOR_125(79, 188, 183),
COLOR_126(92, 219, 213),
COLOR_127(48, 115, 112),
COLOR_128(52, 90, 180),
COLOR_129(63, 110, 220),
COLOR_130(74, 128, 255),
COLOR_131(39, 67, 135),
COLOR_132(0, 153, 40),
COLOR_133(0, 187, 50),
COLOR_134(0, 217, 58),
COLOR_135(0, 114, 30),
COLOR_136(91, 60, 34),
COLOR_137(111, 74, 42),
COLOR_138(129, 86, 49),
COLOR_139(68, 45, 25),
COLOR_140(79, 1, 0),
COLOR_141(96, 1, 0),
COLOR_142(112, 2, 0),
COLOR_143(59, 1, 0),
COLOR_144(147, 124, 113),
COLOR_145(180, 152, 138),
COLOR_146(209, 177, 161),
COLOR_147(110, 93, 85),
COLOR_148(112, 57, 25),
COLOR_149(137, 70, 31),
COLOR_150(159, 82, 36),
COLOR_151(84, 43, 19),
COLOR_152(105, 61, 76),
COLOR_153(128, 75, 93),
COLOR_154(149, 87, 108),
COLOR_155(78, 46, 57),
COLOR_156(79, 76, 97),
COLOR_157(96, 93, 119),
COLOR_158(112, 108, 138),
COLOR_159(59, 57, 73),
COLOR_160(131, 93, 25),
COLOR_161(160, 114, 31),
COLOR_162(186, 133, 36),
COLOR_163(98, 70, 19),
COLOR_164(72, 82, 37),
COLOR_165(88, 100, 45),
COLOR_166(103, 117, 53),
COLOR_167(54, 61, 28),
COLOR_168(112, 54, 55),
COLOR_169(138, 66, 67),
COLOR_170(160, 77, 78),
COLOR_171(84, 40, 41),
COLOR_172(40, 28, 24),
COLOR_173(49, 35, 30),
COLOR_174(57, 41, 35),
COLOR_175(30, 21, 18),
COLOR_176(95, 75, 69),
COLOR_177(116, 92, 84),
COLOR_178(135, 107, 98),
COLOR_179(71, 56, 51),
COLOR_180(61, 64, 64),
COLOR_181(75, 79, 79),
COLOR_182(87, 92, 92),
COLOR_183(46, 48, 48),
COLOR_184(86, 51, 62),
COLOR_185(105, 62, 75),
COLOR_186(122, 73, 88),
COLOR_187(64, 38, 46),
COLOR_188(53, 43, 64),
COLOR_189(65, 53, 79),
COLOR_190(76, 62, 92),
COLOR_191(40, 32, 48),
COLOR_192(53, 35, 24),
COLOR_193(65, 43, 30),
COLOR_194(76, 50, 35),
COLOR_195(40, 26, 18),
COLOR_196(53, 57, 29),
COLOR_197(65, 70, 36),
COLOR_198(76, 82, 42),
COLOR_199(40, 43, 22),
COLOR_200(100, 42, 32),
COLOR_201(122, 51, 39),
COLOR_202(142, 60, 46),
COLOR_203(75, 31, 24),
COLOR_204(26, 15, 11),
COLOR_205(31, 18, 13),
COLOR_206(37, 22, 16),
COLOR_207(19, 11, 8);
private final int red;
private final int green;
private final int blue;
MapColor(int red, int green, int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
int getId() {
return ordinal();
}
public static MapColor fromId(int id) {
return Arrays.stream(values()).filter(color -> color.getId() == id).findFirst().get();
}
public int toARGB() {
int alpha = 255;
if (red == -1 && green == -1 && blue == -1)
alpha = 0; // transparent
long result = red & 0xff;
result |= (green & 0xff) << 8;
result |= (blue & 0xff) << 16;
result |= (alpha & 0xff) << 24;
return (int) (result & 0xFFFFFFFFL);
}
}