diff --git a/src/main/java/net/minecraft/entity/Entity.java b/src/main/java/net/minecraft/entity/Entity.java
index e7834dd..e0165d1 100644
--- a/src/main/java/net/minecraft/entity/Entity.java
+++ b/src/main/java/net/minecraft/entity/Entity.java
@@ -29,6 +29,7 @@
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.item.EntityPainting;
import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
@@ -792,7 +793,8 @@
f = 1.0F;
}
- this.playSound(this.getSwimSound(), f, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
+ if(!isEntityPlayerMP() || !((EntityPlayerMP)this).isHidden())
+ this.playSound(this.getSwimSound(), f, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
}
this.func_145780_a(j1, k, l, block);
@@ -886,6 +888,8 @@
protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_)
{
+ if(isEntityPlayerMP() && ((EntityPlayerMP)this).isHidden())
+ return;
Block.SoundType soundtype = p_145780_4_.stepSound;
if (this.worldObj.getBlock(p_145780_1_, p_145780_2_ + 1, p_145780_3_) == Blocks.snow_layer)
diff --git a/src/main/java/net/minecraft/entity/EntityLivingBase.java b/src/main/java/net/minecraft/entity/EntityLivingBase.java
index 2d2e3cb..afff0d2 100644
--- a/src/main/java/net/minecraft/entity/EntityLivingBase.java
+++ b/src/main/java/net/minecraft/entity/EntityLivingBase.java
@@ -171,7 +171,7 @@
block = this.worldObj.getBlock(i, j - 1, k);
}
}
- else if (!this.worldObj.isRemote && this.fallDistance > 3.0F)
+ else if (!this.worldObj.isRemote && this.fallDistance > 3.0F && (!isEntityPlayerMP() || !((EntityPlayerMP)this).isHidden()))
{
this.worldObj.playAuxSFX(2006, i, j, k, MathHelper.ceiling_float_int(this.fallDistance - 3.0F));
}
diff --git a/src/main/java/net/minecraft/entity/EntityTracker.java b/src/main/java/net/minecraft/entity/EntityTracker.java
index d5ba1b7..c58b4b3 100644
--- a/src/main/java/net/minecraft/entity/EntityTracker.java
+++ b/src/main/java/net/minecraft/entity/EntityTracker.java
@@ -38,6 +38,7 @@
import net.minecraft.world.chunk.Chunk;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.ultramine.permission.MinecraftPermissions;
import cpw.mods.fml.common.registry.EntityRegistry;
@@ -339,6 +340,55 @@
}
}
+ /*===================================== ULTRAMINE START =====================================*/
+
+ public EntityTrackerEntry findPlayerTracker(EntityPlayerMP player)
+ {
+ for(Object o : trackedEntities)
+ {
+ EntityTrackerEntry ent = (EntityTrackerEntry)o;
+ if(ent.myEntity == player)
+ return ent;
+ }
+
+ return null;
+ }
+
+ public void hidePlayer(EntityPlayerMP player)
+ {
+ EntityTrackerEntry playerTracker = findPlayerTracker(player);
+ if(playerTracker != null)
+ {
+ for(Object o : trackedEntities)
+ {
+ EntityTrackerEntry ent = (EntityTrackerEntry)o;
+ if(ent.myEntity.isEntityPlayerMP())
+ {
+ EntityPlayerMP watcher = (EntityPlayerMP)ent.myEntity;
+ if(!watcher.hasPermission(MinecraftPermissions.SEE_INVISIBLE_PLAYERS))
+ playerTracker.removePlayerFromTracker(watcher);
+ }
+ }
+ }
+ }
+
+ public void showPlayer(EntityPlayerMP player)
+ {
+ EntityTrackerEntry playerTracker = findPlayerTracker(player);
+ if(playerTracker != null)
+ {
+ for(Object o : trackedEntities)
+ {
+ EntityTrackerEntry ent = (EntityTrackerEntry)o;
+ if(ent.myEntity.isEntityPlayerMP())
+ {
+ EntityPlayerMP watcher = (EntityPlayerMP)ent.myEntity;
+ playerTracker.tryStartWachingThis(watcher);
+ }
+ }
+ }
+ }
+
/* ======================================== FORGE START =====================================*/
// don't expose the EntityTrackerEntry directly so mods can't mess with the data in there as easily
diff --git a/src/main/java/net/minecraft/entity/EntityTrackerEntry.java b/src/main/java/net/minecraft/entity/EntityTrackerEntry.java
index 6c6e723..4dc72ae 100644
--- a/src/main/java/net/minecraft/entity/EntityTrackerEntry.java
+++ b/src/main/java/net/minecraft/entity/EntityTrackerEntry.java
@@ -56,6 +56,7 @@
import net.minecraft.world.storage.MapData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.ultramine.permission.MinecraftPermissions;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
@@ -355,6 +356,8 @@
{
if (!this.trackingPlayers.contains(p_73117_1_) && (this.isPlayerWatchingThisChunk(p_73117_1_) || this.myEntity.forceSpawn))
{
+ if(myEntity.isEntityPlayerMP() && ((EntityPlayerMP)myEntity).isHidden() && !p_73117_1_.hasPermission(MinecraftPermissions.SEE_INVISIBLE_PLAYERS))
+ return;
this.trackingPlayers.add(p_73117_1_);
Packet packet = this.func_151260_c();
p_73117_1_.playerNetServerHandler.sendPacket(packet);
diff --git a/src/main/java/net/minecraft/entity/player/EntityPlayerMP.java b/src/main/java/net/minecraft/entity/player/EntityPlayerMP.java
index 1118689..16a2890 100644
--- a/src/main/java/net/minecraft/entity/player/EntityPlayerMP.java
+++ b/src/main/java/net/minecraft/entity/player/EntityPlayerMP.java
@@ -65,6 +65,7 @@
import net.minecraft.network.play.server.S30PacketWindowItems;
import net.minecraft.network.play.server.S31PacketWindowProperty;
import net.minecraft.network.play.server.S36PacketSignEditorOpen;
+import net.minecraft.network.play.server.S38PacketPlayerListItem;
import net.minecraft.network.play.server.S39PacketPlayerAbilities;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
import net.minecraft.potion.PotionEffect;
@@ -1039,7 +1040,7 @@
/**
* Переносит игрока в другой мир без использования порталов. Обратите
* внимение: сначала нужно установить координаты назначения
- * setPlayerLocation()
, а потом уже переносить в другой мир.
+ * setPosition()
, а потом уже переносить в другой мир.
*/
public void transferToDimension(int dim)
{
@@ -1053,4 +1054,29 @@
{
this.field_147103_bO = stats;
}
+
+ public void hide()
+ {
+ if(!isHidden())
+ {
+ getData().core().setHidden(true);
+ ((WorldServer)worldObj).getEntityTracker().hidePlayer(this);
+ mcServer.getConfigurationManager().sendPacketToAllPlayers(new S38PacketPlayerListItem(getTabListName(), false, 9999));
+ }
+ }
+
+ public void show()
+ {
+ if(isHidden())
+ {
+ getData().core().setHidden(false);
+ ((WorldServer)worldObj).getEntityTracker().showPlayer(this);
+ mcServer.getConfigurationManager().sendPacketToAllPlayers(new S38PacketPlayerListItem(getTabListName(), true, ping));
+ }
+ }
+
+ public boolean isHidden()
+ {
+ return getData().core().isHidden();
+ }
}
diff --git a/src/main/java/net/minecraft/inventory/ContainerChest.java b/src/main/java/net/minecraft/inventory/ContainerChest.java
index a069884..1c98542 100644
--- a/src/main/java/net/minecraft/inventory/ContainerChest.java
+++ b/src/main/java/net/minecraft/inventory/ContainerChest.java
@@ -1,6 +1,8 @@
package net.minecraft.inventory;
import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
public class ContainerChest extends Container
@@ -8,12 +10,16 @@
private IInventory lowerChestInventory;
private int numRows;
private static final String __OBFID = "CL_00001742";
+
+ private final boolean notifyInventory;
public ContainerChest(IInventory p_i1806_1_, IInventory p_i1806_2_)
{
this.lowerChestInventory = p_i1806_2_;
this.numRows = p_i1806_2_.getSizeInventory() / 9;
- p_i1806_2_.openInventory();
+ notifyInventory = !(p_i1806_1_ instanceof InventoryPlayer && ((InventoryPlayer)p_i1806_1_).player.isEntityPlayerMP() && ((EntityPlayerMP)((InventoryPlayer)p_i1806_1_).player).isHidden());
+ if(notifyInventory)
+ p_i1806_2_.openInventory();
int i = (this.numRows - 4) * 18;
int j;
int k;
@@ -83,7 +89,8 @@
public void onContainerClosed(EntityPlayer p_75134_1_)
{
super.onContainerClosed(p_75134_1_);
- this.lowerChestInventory.closeInventory();
+ if(notifyInventory)
+ this.lowerChestInventory.closeInventory();
}
public IInventory getLowerChestInventory()
diff --git a/src/main/java/net/minecraft/network/NetHandlerPlayServer.java b/src/main/java/net/minecraft/network/NetHandlerPlayServer.java
index 678e0f7..8148da2 100644
--- a/src/main/java/net/minecraft/network/NetHandlerPlayServer.java
+++ b/src/main/java/net/minecraft/network/NetHandlerPlayServer.java
@@ -642,7 +642,8 @@
this.serverController.func_147132_au();
ChatComponentTranslation chatcomponenttranslation = new ChatComponentTranslation("multiplayer.player.left", new Object[] {this.playerEntity.func_145748_c_()});
chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.YELLOW);
- this.serverController.getConfigurationManager().sendPacketToAllPlayers(new S02PacketChat(chatcomponenttranslation, true));
+ if(!playerEntity.isHidden() && !playerEntity.hasPermission(MinecraftPermissions.HIDE_JOIN_MESSAGE))
+ this.serverController.getConfigurationManager().sendPacketToAllPlayers(new S02PacketChat(chatcomponenttranslation, true));
this.playerEntity.mountEntityAndWakeUp();
this.serverController.getConfigurationManager().playerLoggedOut(this.playerEntity);
diff --git a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java
index 412f421..cf62f0d 100644
--- a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java
+++ b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java
@@ -22,6 +22,7 @@
import java.util.UUID;
import java.util.Map.Entry;
+import net.minecraft.command.CommandBase;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayer;
@@ -176,7 +177,8 @@
}
chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.YELLOW);
- sendPacketToAllPlayers(new S02PacketChat(chatcomponenttranslation, true));
+ if(!p_72355_2_.isHidden() && !p_72355_2_.hasPermission(MinecraftPermissions.HIDE_JOIN_MESSAGE))
+ sendPacketToAllPlayers(new S02PacketChat(chatcomponenttranslation, true));
this.playerLoggedIn(p_72355_2_);
nethandlerplayserver.setPlayerLocation(p_72355_2_.posX, p_72355_2_.posY, p_72355_2_.posZ, p_72355_2_.rotationYaw, p_72355_2_.rotationPitch);
this.updateTimeAndWeatherForPlayer(p_72355_2_, worldserver);
@@ -314,7 +316,17 @@
public void playerLoggedIn(final EntityPlayerMP par1EntityPlayerMP)
{
- this.sendPacketToAllPlayers(new S38PacketPlayerListItem(par1EntityPlayerMP.getTabListName(), true, 1000));
+ if(!par1EntityPlayerMP.isHidden())
+ this.sendPacketToAllPlayers(new S38PacketPlayerListItem(par1EntityPlayerMP.getTabListName(), true, 1000));
+ else
+ {
+ for(Object o : playerEntityList)
+ {
+ EntityPlayerMP p = (EntityPlayerMP)o;
+ if(p.hasPermission(MinecraftPermissions.SEE_INVISIBLE_PLAYERS))
+ p.playerNetServerHandler.sendPacket(new S38PacketPlayerListItem(par1EntityPlayerMP.getTabListName(), true, 1000));
+ }
+ }
this.playerEntityList.add(par1EntityPlayerMP);
usernameToPlayerMap.put(par1EntityPlayerMP.getGameProfile().getName().toLowerCase(), par1EntityPlayerMP);
final WorldServer worldserver = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
@@ -325,11 +337,16 @@
worldserver.spawnEntityInWorld(par1EntityPlayerMP);
func_72375_a(par1EntityPlayerMP, (WorldServer)null);
+ boolean seeInvisible = par1EntityPlayerMP.hasPermission(MinecraftPermissions.SEE_INVISIBLE_PLAYERS);
for (int i = 0; i < this.playerEntityList.size(); ++i)
{
EntityPlayerMP entityplayermp1 = (EntityPlayerMP)this.playerEntityList.get(i);
- par1EntityPlayerMP.playerNetServerHandler.sendPacket(new S38PacketPlayerListItem(entityplayermp1.getTabListName(), true, entityplayermp1.ping));
+ if(!entityplayermp1.isHidden() || seeInvisible)
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new S38PacketPlayerListItem(entityplayermp1.getTabListName(), true, entityplayermp1.ping));
}
+
+ if(par1EntityPlayerMP.isHidden())
+ CommandBase.func_152374_a(par1EntityPlayerMP, null, 1, "ultramine.notify.loggedhidden");
}
public void updatePlayerPertinentChunks(EntityPlayerMP p_72358_1_)
@@ -680,7 +697,17 @@
if (this.playerPingIndex < this.playerEntityList.size())
{
EntityPlayerMP entityplayermp = (EntityPlayerMP)this.playerEntityList.get(this.playerPingIndex);
- this.sendPacketToAllPlayers(new S38PacketPlayerListItem(entityplayermp.getTabListName(), true, entityplayermp.ping));
+ if(!entityplayermp.isHidden())
+ this.sendPacketToAllPlayers(new S38PacketPlayerListItem(entityplayermp.getTabListName(), true, entityplayermp.ping));
+ else
+ {
+ for(Object o : playerEntityList)
+ {
+ EntityPlayerMP p = (EntityPlayerMP)o;
+ if(p.hasPermission(MinecraftPermissions.SEE_INVISIBLE_PLAYERS))
+ p.playerNetServerHandler.sendPacket(new S38PacketPlayerListItem(entityplayermp.getTabListName(), true, entityplayermp.ping));
+ }
+ }
}
}
@@ -707,25 +734,28 @@
public String func_152609_b(boolean p_152609_1_)
{
- String s = "";
- ArrayList arraylist = Lists.newArrayList(this.playerEntityList);
+ StringBuilder sb = new StringBuilder(512);
- for (int i = 0; i < arraylist.size(); ++i)
+ for (int i = 0; i < playerEntityList.size(); ++i)
{
- if (i > 0)
+ EntityPlayerMP player = (EntityPlayerMP)playerEntityList.get(i);
+ if(!player.isHidden())
{
- s = s + ", ";
- }
+ if (i > 0)
+ {
+ sb.append(", ");
+ }
- s = s + ((EntityPlayerMP)arraylist.get(i)).getCommandSenderName();
+ sb.append(player.getCommandSenderName());
- if (p_152609_1_)
- {
- s = s + " (" + ((EntityPlayerMP)arraylist.get(i)).getUniqueID().toString() + ")";
+ if (p_152609_1_)
+ {
+ sb.append(" (").append(player.getUniqueID().toString()).append(")");
+ }
}
}
- return s;
+ return sb.toString();
}
public String[] getAllUsernames()
diff --git a/src/main/java/org/ultramine/commands/CommandContext.java b/src/main/java/org/ultramine/commands/CommandContext.java
index 3c408c1..73df0e7 100644
--- a/src/main/java/org/ultramine/commands/CommandContext.java
+++ b/src/main/java/org/ultramine/commands/CommandContext.java
@@ -117,6 +117,11 @@
{
CommandBase.func_152373_a(sender, null, messageKey, messageArgs);
}
+
+ public void notifyOtherAdmins(String messageKey, Object... messageArgs)
+ {
+ CommandBase.func_152374_a(sender, null, 1, messageKey, messageArgs);
+ }
public void checkSenderPermission(String permission)
{
diff --git a/src/main/java/org/ultramine/commands/basic/BasicCommands.java b/src/main/java/org/ultramine/commands/basic/BasicCommands.java
index 0dfe268..3e88d1e 100644
--- a/src/main/java/org/ultramine/commands/basic/BasicCommands.java
+++ b/src/main/java/org/ultramine/commands/basic/BasicCommands.java
@@ -426,4 +426,28 @@
ctx.get("player").asOfflinePlayer().sendMessage(GREEN, GREEN, "command.unmute.notify");
ctx.sendMessage("command.unmute.success", data.getProfile().getName());
}
+
+ @Command(
+ name = "vanish",
+ group = "admin",
+ aliases = {"hide"},
+ permissions = {"command.admin.vanish"},
+ syntax = {""}
+ )
+ public static void vanish(CommandContext ctx)
+ {
+ EntityPlayerMP player = ctx.getSenderAsPlayer();
+ if(player.isHidden())
+ {
+ player.show();
+ ctx.sendMessage("command.unmute.success.show");
+ ctx.notifyOtherAdmins("command.unmute.notify.show");
+ }
+ else
+ {
+ player.hide();
+ ctx.sendMessage("command.unmute.success.hide");
+ ctx.notifyOtherAdmins("command.unmute.notify.hide");
+ }
+ }
}
diff --git a/src/main/java/org/ultramine/permission/MinecraftPermissions.java b/src/main/java/org/ultramine/permission/MinecraftPermissions.java
index 22305a5..c3a074a 100644
--- a/src/main/java/org/ultramine/permission/MinecraftPermissions.java
+++ b/src/main/java/org/ultramine/permission/MinecraftPermissions.java
@@ -7,4 +7,7 @@
public static final String ALLOW_SPAM = "minecraft.allow_spam";
public static final String IGNORE_SPAWN_PROTECTION = "minecraft.ignore_spawn_prot";
public static final String IGNORE_WHITE_LIST = "minecraft.ignore_white_list";
+
+ public static final String SEE_INVISIBLE_PLAYERS = "ability.admin.seeinvisibleplayers";
+ public static final String HIDE_JOIN_MESSAGE = "ability.admin.hidejoinmessage";
}
diff --git a/src/main/java/org/ultramine/server/UMEventHandler.java b/src/main/java/org/ultramine/server/UMEventHandler.java
index f85d83f..d9aa270 100644
--- a/src/main/java/org/ultramine/server/UMEventHandler.java
+++ b/src/main/java/org/ultramine/server/UMEventHandler.java
@@ -66,6 +66,11 @@
e.player.addChatMessage(new ChatComponentTranslation("ultramine.ability.chat.muted.forever").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)));
}
}
+ else if(e.player.isHidden())
+ {
+ e.setCanceled(true);
+ e.player.addChatMessage(new ChatComponentTranslation("ultramine.hidden.chat").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)));
+ }
}
@SubscribeEvent
diff --git a/src/main/java/org/ultramine/server/UltramineServerModContainer.java b/src/main/java/org/ultramine/server/UltramineServerModContainer.java
index 7fcbc11..18707fc 100644
--- a/src/main/java/org/ultramine/server/UltramineServerModContainer.java
+++ b/src/main/java/org/ultramine/server/UltramineServerModContainer.java
@@ -18,6 +18,7 @@
import org.ultramine.commands.syntax.DefaultCompleters;
import org.ultramine.economy.EconomyCommands;
import org.ultramine.permission.IPermissionManager;
+import org.ultramine.permission.MinecraftPermissions;
import org.ultramine.permission.commands.BasicPermissionCommands;
import org.ultramine.server.chunk.ChunkProfiler;
import org.ultramine.server.data.Databases;
@@ -154,7 +155,9 @@
}
e.getPermissionHandler().setGroupMeta(IPermissionManager.DEFAULT_GROUP_NAME, IPermissionManager.GLOBAL_WORLD, "color", "7");
e.getPermissionHandler().addToGroup("admin", IPermissionManager.GLOBAL_WORLD, "*");
+ e.getPermissionHandler().addToGroup("admin", IPermissionManager.GLOBAL_WORLD, "^"+MinecraftPermissions.HIDE_JOIN_MESSAGE);
e.getPermissionHandler().setGroupMeta("admin", IPermissionManager.GLOBAL_WORLD, "color", "c");
+ e.getPermissionHandler().setGroupMeta("admin", IPermissionManager.GLOBAL_WORLD, "tablistcolor", "c");
e.getPermissionHandler().setGroupMeta("admin", IPermissionManager.GLOBAL_WORLD, "prefix", "&4[admin] ");
if(e.getSide().isServer())
diff --git a/src/main/java/org/ultramine/server/data/player/PlayerCoreData.java b/src/main/java/org/ultramine/server/data/player/PlayerCoreData.java
index eeed0c2..b575c02 100644
--- a/src/main/java/org/ultramine/server/data/player/PlayerCoreData.java
+++ b/src/main/java/org/ultramine/server/data/player/PlayerCoreData.java
@@ -17,6 +17,7 @@
private final PlayerAccount account;
private long unmuteTime;
private boolean commandsMuted;
+ private boolean hidden;
//undatabased
private Teleporter teleporter;
@@ -136,6 +137,16 @@
return isMuted() && commandsMuted;
}
+ public boolean isHidden()
+ {
+ return hidden;
+ }
+
+ public void setHidden(boolean hidden)
+ {
+ this.hidden = hidden;
+ }
+
@Override
public void writeToNBT(NBTTagCompound nbt)
{
@@ -154,6 +165,7 @@
nbt.setTag("acc", accnbt);
nbt.setLong("m", unmuteTime);
nbt.setBoolean("mc", commandsMuted);
+ nbt.setBoolean("h", hidden);
}
@Override
@@ -169,5 +181,6 @@
account.readFromNBT(nbt.getCompoundTag("acc"));
unmuteTime = nbt.getLong("m");
commandsMuted = nbt.getBoolean("mc");
+ hidden = nbt.getBoolean("h");
}
}
diff --git a/src/main/resources/assets/ultramine/lang/en_US.lang b/src/main/resources/assets/ultramine/lang/en_US.lang
index 0ade4ed..cfaa800 100644
--- a/src/main/resources/assets/ultramine/lang/en_US.lang
+++ b/src/main/resources/assets/ultramine/lang/en_US.lang
@@ -17,6 +17,9 @@
ultramine.ability.attack=You don't have permissions to damage entities
ultramine.ability.chat=You don't have permissions to chat
+ultramine.notify.loggedhidden=Joined the server in invisibility
+ultramine.hidden.chat=You can't write to chat in invisibility
+
#Command generic
commands.generic.world.invalid=Can't find world '%s'
commands.generic.itemstack.data=Failed to parse item data: %s
@@ -339,3 +342,10 @@
command.unmute.fail=The player is not muted
command.unmute.notify=You has been unmuted
command.unmute.success=Player %s has been unmuted
+
+command.unmute.usage=/vanish
+command.unmute.description=Makes you invisible for other players
+command.unmute.success.hide=Now you're invisible
+command.unmute.success.show=Now you're visible
+command.unmute.notify.hide=became invisible
+command.unmute.notify.show=became visible
diff --git a/src/main/resources/assets/ultramine/lang/ru_RU.lang b/src/main/resources/assets/ultramine/lang/ru_RU.lang
index 5c857c9..15b298b 100644
--- a/src/main/resources/assets/ultramine/lang/ru_RU.lang
+++ b/src/main/resources/assets/ultramine/lang/ru_RU.lang
@@ -17,6 +17,9 @@
ultramine.ability.attack=У вас нет права наносить урон
ultramine.ability.chat=У вас нет прав писать в чате
+ultramine.notify.loggedhidden=Присоединился к игре невидимым
+ultramine.hidden.chat=Вы не можете писать в чат в невидимости
+
#Command generic
commands.generic.world.invalid=Указанный мир не существует или неинициализирован '%s'
commands.generic.itemstack.data=Не удалось разобрать предмет: %s
@@ -339,3 +342,10 @@
command.unmute.fail=Указанный игрок не замьючен
command.unmute.notify=Вам возвращено право писать в чат
command.unmute.success=Игроку %s теперь разрешено писать в чат
+
+command.unmute.usage=/vanish
+command.unmute.description=Делает вас невидимым для других игроков
+command.unmute.success.hide=Вы в невидимости
+command.unmute.success.show=Теперь вас видно
+command.unmute.notify.hide=зашел в невидимость
+command.unmute.notify.show=вышел из невидимости