2019-07-10 06:34:10 +00:00
/ *
2019-07-11 21:30:35 +00:00
* Copyright ( c ) 2019 GeyserMC . http : //geysermc.org
2019-07-10 06:34:10 +00:00
*
2019-07-11 21:30:35 +00:00
* 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 :
2019-07-10 06:34:10 +00:00
*
2019-07-11 21:30:35 +00:00
* 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 .
2019-07-10 06:34:10 +00:00
*
* @author GeyserMC
* @link https : //github.com/GeyserMC/Geyser
* /
package org.geysermc.connector.network.session ;
2019-07-24 06:29:54 +00:00
import com.flowpowered.math.vector.Vector2f ;
import com.flowpowered.math.vector.Vector3f ;
import com.flowpowered.math.vector.Vector3i ;
import com.github.steveice10.mc.auth.exception.request.RequestException ;
2019-07-10 06:34:10 +00:00
import com.github.steveice10.mc.protocol.MinecraftProtocol ;
import com.github.steveice10.packetlib.Client ;
import com.github.steveice10.packetlib.event.session.ConnectedEvent ;
import com.github.steveice10.packetlib.event.session.DisconnectedEvent ;
import com.github.steveice10.packetlib.event.session.PacketReceivedEvent ;
import com.github.steveice10.packetlib.event.session.SessionAdapter ;
2019-08-06 02:09:45 +00:00
import com.github.steveice10.packetlib.packet.Packet ;
2019-07-10 06:34:10 +00:00
import com.github.steveice10.packetlib.tcp.TcpSessionFactory ;
import com.nukkitx.network.util.DisconnectReason ;
import com.nukkitx.protocol.PlayerSession ;
import com.nukkitx.protocol.bedrock.BedrockServerSession ;
2019-07-24 06:29:54 +00:00
import com.nukkitx.protocol.bedrock.data.GamePublishSetting ;
import com.nukkitx.protocol.bedrock.data.GameRule ;
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket ;
import com.nukkitx.protocol.bedrock.packet.StartGamePacket ;
2019-07-22 00:52:20 +00:00
import com.nukkitx.protocol.bedrock.packet.TextPacket ;
2019-07-10 06:34:10 +00:00
import lombok.Getter ;
2019-08-06 02:09:45 +00:00
import lombok.Setter ;
2019-08-06 02:14:41 +00:00
import org.geysermc.api.Geyser ;
2019-07-23 23:16:25 +00:00
import org.geysermc.api.Player ;
import org.geysermc.api.RemoteServer ;
import org.geysermc.api.session.AuthData ;
import org.geysermc.api.window.FormWindow ;
2019-07-10 06:34:10 +00:00
import org.geysermc.connector.GeyserConnector ;
2019-08-06 02:09:45 +00:00
import org.geysermc.connector.entity.PlayerEntity ;
import org.geysermc.connector.entity.type.EntityType ;
import org.geysermc.connector.inventory.PlayerInventory ;
import org.geysermc.connector.network.session.cache.DataCache ;
import org.geysermc.connector.network.session.cache.EntityCache ;
2019-07-29 22:20:48 +00:00
import org.geysermc.connector.network.session.cache.InventoryCache ;
2019-07-30 02:57:43 +00:00
import org.geysermc.connector.network.session.cache.ScoreboardCache ;
2019-07-23 23:16:25 +00:00
import org.geysermc.connector.network.session.cache.WindowCache ;
2019-07-11 22:39:28 +00:00
import org.geysermc.connector.network.translators.Registry ;
2019-07-24 06:29:54 +00:00
import org.geysermc.connector.utils.Toolbox ;
2019-07-10 06:34:10 +00:00
2019-08-06 02:09:45 +00:00
import java.util.UUID ;
@Getter
2019-07-23 23:16:25 +00:00
public class GeyserSession implements PlayerSession , Player {
2019-07-10 06:34:10 +00:00
private GeyserConnector connector ;
2019-07-23 23:16:25 +00:00
private RemoteServer remoteServer ;
2019-07-10 06:34:10 +00:00
private BedrockServerSession upstream ;
private Client downstream ;
2019-07-23 23:16:25 +00:00
private AuthData authenticationData ;
2019-08-06 02:09:45 +00:00
private PlayerEntity playerEntity ;
private PlayerInventory inventory ;
2019-07-29 22:20:48 +00:00
2019-08-06 02:09:45 +00:00
private EntityCache entityCache ;
private InventoryCache inventoryCache ;
2019-07-23 23:16:25 +00:00
private WindowCache windowCache ;
2019-07-30 02:57:43 +00:00
private ScoreboardCache scoreboardCache ;
2019-08-06 02:09:45 +00:00
private DataCache < Packet > javaPacketCache ;
2019-07-24 06:29:54 +00:00
private boolean loggedIn ;
2019-08-06 02:09:45 +00:00
@Setter
private boolean spawned ;
2019-07-10 06:34:10 +00:00
private boolean closed ;
public GeyserSession ( GeyserConnector connector , BedrockServerSession bedrockServerSession ) {
this . connector = connector ;
this . upstream = bedrockServerSession ;
2019-07-23 23:16:25 +00:00
2019-08-06 02:09:45 +00:00
this . entityCache = new EntityCache ( this ) ;
2019-07-29 22:20:48 +00:00
this . inventoryCache = new InventoryCache ( this ) ;
2019-07-23 23:16:25 +00:00
this . windowCache = new WindowCache ( this ) ;
2019-07-30 02:57:43 +00:00
this . scoreboardCache = new ScoreboardCache ( this ) ;
2019-08-06 02:09:45 +00:00
this . playerEntity = new PlayerEntity ( UUID . randomUUID ( ) , 1 , 1 , EntityType . PLAYER , new Vector3f ( 0 , 0 , 0 ) , new Vector3f ( 0 , 0 , 0 ) , new Vector3f ( 0 , 0 , 0 ) ) ;
this . inventory = new PlayerInventory ( ) ;
this . javaPacketCache = new DataCache < Packet > ( ) ;
this . spawned = false ;
2019-07-24 06:29:54 +00:00
this . loggedIn = false ;
2019-08-06 02:09:45 +00:00
this . inventoryCache . getInventories ( ) . put ( 0 , inventory ) ;
2019-07-10 06:34:10 +00:00
}
2019-07-23 23:16:25 +00:00
public void connect ( RemoteServer remoteServer ) {
2019-07-24 06:29:54 +00:00
// This has to be sent first so the player actually joins
startGame ( ) ;
2019-07-10 06:34:10 +00:00
2019-07-24 06:29:54 +00:00
this . remoteServer = remoteServer ;
if ( ! connector . getConfig ( ) . getRemote ( ) . isOnlineMode ( ) ) {
connector . getLogger ( ) . info ( " Attempting to login using offline mode... authentication is disabled. " ) ;
authenticate ( authenticationData . getName ( ) ) ;
}
}
2019-07-10 06:34:10 +00:00
2019-07-24 06:29:54 +00:00
public void authenticate ( String username ) {
authenticate ( username , " " ) ;
2019-08-09 01:42:55 +00:00
connector . addPlayer ( this ) ;
2019-07-24 06:29:54 +00:00
}
public void authenticate ( String username , String password ) {
if ( loggedIn ) {
connector . getLogger ( ) . severe ( username + " is already logged in! " ) ;
return ;
}
2019-07-10 06:34:10 +00:00
2019-07-24 06:29:54 +00:00
try {
MinecraftProtocol protocol ;
if ( password ! = null & & ! password . isEmpty ( ) ) {
protocol = new MinecraftProtocol ( username , password ) ;
} else {
protocol = new MinecraftProtocol ( username ) ;
2019-07-10 06:34:10 +00:00
}
2019-07-24 06:29:54 +00:00
downstream = new Client ( remoteServer . getAddress ( ) , remoteServer . getPort ( ) , protocol , new TcpSessionFactory ( ) ) ;
downstream . getSession ( ) . addListener ( new SessionAdapter ( ) {
@Override
public void connected ( ConnectedEvent event ) {
loggedIn = true ;
connector . getLogger ( ) . info ( authenticationData . getName ( ) + " (logged in as: " + protocol . getProfile ( ) . getName ( ) + " ) " + " has connected to remote java server on address " + remoteServer . getAddress ( ) ) ;
2019-08-06 02:09:45 +00:00
playerEntity . setUuid ( protocol . getProfile ( ) . getId ( ) ) ;
2019-07-24 06:29:54 +00:00
}
@Override
public void disconnected ( DisconnectedEvent event ) {
loggedIn = false ;
connector . getLogger ( ) . info ( authenticationData . getName ( ) + " has disconnected from remote java server on address " + remoteServer . getAddress ( ) + " because of " + event . getReason ( ) ) ;
2019-08-08 23:16:46 +00:00
// upstream.disconnect(event.getReason());
2019-07-24 06:29:54 +00:00
}
@Override
public void packetReceived ( PacketReceivedEvent event ) {
2019-08-06 02:09:45 +00:00
if ( ! closed )
Registry . JAVA . translate ( event . getPacket ( ) . getClass ( ) , event . getPacket ( ) , GeyserSession . this ) ;
2019-07-24 06:29:54 +00:00
}
} ) ;
downstream . getSession ( ) . connect ( ) ;
} catch ( RequestException ex ) {
ex . printStackTrace ( ) ;
}
2019-07-10 06:34:10 +00:00
}
public void disconnect ( String reason ) {
if ( ! closed ) {
2019-07-24 06:29:54 +00:00
loggedIn = false ;
2019-08-02 20:54:40 +00:00
if ( downstream ! = null & & downstream . getSession ( ) ! = null ) {
downstream . getSession ( ) . disconnect ( reason ) ;
}
if ( upstream ! = null ) {
upstream . disconnect ( reason ) ;
}
2019-07-10 06:34:10 +00:00
}
2019-08-06 02:09:45 +00:00
closed = true ;
2019-07-10 06:34:10 +00:00
}
@Override
public boolean isClosed ( ) {
return closed ;
}
@Override
public void close ( ) {
disconnect ( " Server closed. " ) ;
}
@Override
public void onDisconnect ( DisconnectReason disconnectReason ) {
downstream . getSession ( ) . disconnect ( " Disconnected from server. Reason: " + disconnectReason ) ;
}
@Override
public void onDisconnect ( String reason ) {
downstream . getSession ( ) . disconnect ( " Disconnected from server. Reason: " + reason ) ;
2019-08-09 01:42:55 +00:00
connector . removePlayer ( this ) ;
2019-07-10 06:34:10 +00:00
}
2019-07-23 23:16:25 +00:00
public void setAuthenticationData ( AuthData authData ) {
authenticationData = authData ;
2019-07-10 06:34:10 +00:00
}
2019-07-22 00:52:20 +00:00
@Override
public String getName ( ) {
return authenticationData . getName ( ) ;
}
@Override
public void sendMessage ( String message ) {
TextPacket textPacket = new TextPacket ( ) ;
textPacket . setPlatformChatId ( " " ) ;
textPacket . setSourceName ( " " ) ;
textPacket . setXuid ( " " ) ;
textPacket . setType ( TextPacket . Type . CHAT ) ;
textPacket . setNeedsTranslation ( false ) ;
textPacket . setMessage ( message ) ;
upstream . sendPacket ( textPacket ) ;
}
@Override
public void sendMessage ( String [ ] messages ) {
for ( String message : messages ) {
sendMessage ( message ) ;
}
}
2019-07-23 23:16:25 +00:00
public void sendForm ( FormWindow window , int id ) {
windowCache . showWindow ( window , id ) ;
}
2019-07-10 06:34:10 +00:00
2019-07-23 23:16:25 +00:00
public void sendForm ( FormWindow window ) {
windowCache . showWindow ( window ) ;
2019-07-10 06:34:10 +00:00
}
2019-07-24 06:29:54 +00:00
private void startGame ( ) {
StartGamePacket startGamePacket = new StartGamePacket ( ) ;
2019-08-06 02:09:45 +00:00
startGamePacket . setUniqueEntityId ( playerEntity . getGeyserId ( ) ) ;
startGamePacket . setRuntimeEntityId ( playerEntity . getGeyserId ( ) ) ;
2019-07-24 06:29:54 +00:00
startGamePacket . setPlayerGamemode ( 0 ) ;
2019-08-06 02:09:45 +00:00
startGamePacket . setPlayerPosition ( new Vector3f ( 0 , 69 , 0 ) ) ;
2019-07-24 06:29:54 +00:00
startGamePacket . setRotation ( new Vector2f ( 1 , 1 ) ) ;
2019-08-06 02:09:45 +00:00
startGamePacket . setSeed ( 0 ) ;
startGamePacket . setDimensionId ( playerEntity . getDimension ( ) ) ;
startGamePacket . setGeneratorId ( 1 ) ;
2019-07-24 06:29:54 +00:00
startGamePacket . setLevelGamemode ( 0 ) ;
startGamePacket . setDifficulty ( 1 ) ;
startGamePacket . setDefaultSpawn ( new Vector3i ( 0 , 0 , 0 ) ) ;
startGamePacket . setAcheivementsDisabled ( true ) ;
startGamePacket . setTime ( 0 ) ;
startGamePacket . setEduLevel ( false ) ;
startGamePacket . setEduFeaturesEnabled ( false ) ;
startGamePacket . setRainLevel ( 0 ) ;
startGamePacket . setLightningLevel ( 0 ) ;
startGamePacket . setMultiplayerGame ( true ) ;
startGamePacket . setBroadcastingToLan ( true ) ;
startGamePacket . getGamerules ( ) . add ( new GameRule < > ( " showcoordinates " , true ) ) ;
startGamePacket . setPlatformBroadcastMode ( GamePublishSetting . PUBLIC ) ;
startGamePacket . setXblBroadcastMode ( GamePublishSetting . PUBLIC ) ;
startGamePacket . setCommandsEnabled ( true ) ;
startGamePacket . setTexturePacksRequired ( false ) ;
startGamePacket . setBonusChestEnabled ( false ) ;
startGamePacket . setStartingWithMap ( false ) ;
startGamePacket . setTrustingPlayers ( true ) ;
startGamePacket . setDefaultPlayerPermission ( 1 ) ;
startGamePacket . setServerChunkTickRange ( 4 ) ;
startGamePacket . setBehaviorPackLocked ( false ) ;
startGamePacket . setResourcePackLocked ( false ) ;
startGamePacket . setFromLockedWorldTemplate ( false ) ;
startGamePacket . setUsingMsaGamertagsOnly ( false ) ;
startGamePacket . setFromWorldTemplate ( false ) ;
startGamePacket . setWorldTemplateOptionLocked ( false ) ;
2019-08-06 02:09:45 +00:00
startGamePacket . setLevelId ( " world " ) ;
2019-07-24 06:29:54 +00:00
startGamePacket . setWorldName ( " world " ) ;
startGamePacket . setPremiumWorldTemplateId ( " 00000000-0000-0000-0000-000000000000 " ) ;
startGamePacket . setCurrentTick ( 0 ) ;
startGamePacket . setEnchantmentSeed ( 0 ) ;
startGamePacket . setMultiplayerCorrelationId ( " " ) ;
startGamePacket . setCachedPalette ( Toolbox . CACHED_PALLETE ) ;
startGamePacket . setItemEntries ( Toolbox . ITEMS ) ;
upstream . sendPacket ( startGamePacket ) ;
PlayStatusPacket playStatusPacket = new PlayStatusPacket ( ) ;
playStatusPacket . setStatus ( PlayStatusPacket . Status . PLAYER_SPAWN ) ;
upstream . sendPacket ( playStatusPacket ) ;
}
2019-07-10 06:34:10 +00:00
}