Roblox/Minecraft server link: Difference between revisions
No edit summary |
No edit summary |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
I once created a very simple link between a Roblox and Minecraft Java game server. It only reported positions from the Minecraft world to Roblox. Later I made something that could return chunks from the world but the code for that is buried somewhere. | I once created a very simple link between a Roblox and Minecraft Java game server. It only reported positions from the Minecraft world to Roblox. Later I made something that could return chunks from the Minecraft world and recreate it in Roblox but the code for that is buried somewhere. (Maybe it would be more efficient these days due to parallel Luau!) | ||
The Minecraft side uses the [https://methodscript.com/ CommandHelper] plugin, which uses the MethodScript language. | The Minecraft side uses the [https://methodscript.com/ CommandHelper] plugin, which uses the MethodScript language. | ||
This does NOT work on a live Roblox server since it expects there to be little to no latency (it doesn't deal with this well). And Roblox may not like the high volume of HTTP requests going out. | This does NOT work on a live Roblox server since it expects there to be little to no latency (it doesn't deal with this well). And Roblox may not like the high volume of HTTP requests going out. It also does not filter Minecraft usernames, which would not work that well anyway. | ||
* [https://www.youtube.com/watch?v=9LZulfFOEvA Video on YouTube] | * [https://www.youtube.com/watch?v=9LZulfFOEvA Video on YouTube] | ||
Line 39: | Line 39: | ||
* Workspace | * Workspace | ||
** MCCurrentPlayers (Folder) | ** MCCurrentPlayers (Folder) | ||
* | * ServerScriptService | ||
** MCServerLink (Folder) | ** MCServerLink (Folder) | ||
*** HttpHandler (Script) | *** HttpHandler (Script) | ||
*** PlayerHandler (Script) | *** PlayerHandler (Script) | ||
* ServerStorage | |||
** MCServerLink (Folder) | |||
*** MakeRequest (BindableEvent) | *** MakeRequest (BindableEvent) | ||
*** PlayerAdded (BindableEvent) | *** PlayerAdded (BindableEvent) | ||
Line 50: | Line 52: | ||
=== ServerScriptService.MCServerLink.HttpHandler === | === ServerScriptService.MCServerLink.HttpHandler === | ||
Makes a request to the server roughly every 1/6th of a second, making up to 360 requests per minute. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
local HttpService = game:GetService('HttpService') | local HttpService = game:GetService('HttpService') |
Latest revision as of 18:01, 23 December 2020
I once created a very simple link between a Roblox and Minecraft Java game server. It only reported positions from the Minecraft world to Roblox. Later I made something that could return chunks from the Minecraft world and recreate it in Roblox but the code for that is buried somewhere. (Maybe it would be more efficient these days due to parallel Luau!)
The Minecraft side uses the CommandHelper plugin, which uses the MethodScript language.
This does NOT work on a live Roblox server since it expects there to be little to no latency (it doesn't deal with this well). And Roblox may not like the high volume of HTTP requests going out. It also does not filter Minecraft usernames, which would not work that well anyway.
CommandHelper main.ms
<!
strict;
author: Ian Burgwin (ihaveahax)
created: 2020-03-17
description: Return player positions. (Eventually will handle Roblox player positions.)
>
httpd_listen(29295) #-- 0x726F (ro)
bind('http_request', null, null, @event) {
modify_event('code', 200);
httpd_set_header('Content-Type', 'application/json');
array @positions = array();
array @smaller_ploc;
array @c; # current position
foreach(all_players(), @player) {
@c = location_shift(ploc(@player), 'UP', 1);
@smaller_ploc = array('x': @c['x'], 'y': @c['y'], 'z': @c['z'], 'pitch': @c['pitch'], 'yaw': @c['yaw']);
@positions[@player] = @smaller_ploc;
}
modify_event('body', json_encode(@positions));
}
Roblox object hierarchy
- Workspace
- MCCurrentPlayers (Folder)
- ServerScriptService
- MCServerLink (Folder)
- HttpHandler (Script)
- PlayerHandler (Script)
- MCServerLink (Folder)
- ServerStorage
- MCServerLink (Folder)
- MakeRequest (BindableEvent)
- PlayerAdded (BindableEvent)
- PlayerMove (BindableEvent)
- PlayerRemoving (BindableEvent)
- Base (Model)
- MCServerLink (Folder)
ServerScriptService.MCServerLink.HttpHandler
Makes a request to the server roughly every 1/6th of a second, making up to 360 requests per minute.
local HttpService = game:GetService('HttpService')
local ServerStorage = game:GetService('ServerStorage')
local Storage = ServerStorage.MCServerLink
local MakeRequest = Storage.MakeRequest
local PlayerAdded = Storage.PlayerAdded
local PlayerRemoving = Storage.PlayerRemoving
local PlayerMove = Storage.PlayerMove
local Url = 'http://localhost:29295'
-- key is the username, value is always true
-- this loses order, but is faster than an ordered table
local CurrentPlayers = {}
local function HandleMakeRequest()
print('Requesting...')
local Positions = HttpService:JSONDecode(HttpService:GetAsync(Url))
print('Got data')
for Username, _ in pairs(CurrentPlayers) do
if not Positions[Username] then
print('Player removed: '..Username)
PlayerRemoving:Fire(Username)
end
end
for Username, PositionData in pairs(Positions) do
local Position = Vector3.new(PositionData['x'], PositionData['y'], PositionData['z'])
local Orientation = Vector3.new(0, PositionData['yaw'], -PositionData['pitch'])
if not CurrentPlayers[Username] then
print('Player added: '..Username)
PlayerAdded:Fire(Username, Position, Orientation)
CurrentPlayers[Username] = true
else
print('Player moved: '..Username)
PlayerMove:Fire(Username, Position, Orientation)
end
end
end
MakeRequest.Event:Connect(HandleMakeRequest)
print('HttpHandler ready')
while wait(1/6) do
MakeRequest:Fire()
end
ServerScriptService.MCServerLink.PlayerHandler
local HttpService = game:GetService('HttpService')
local ServerStorage = game:GetService('ServerStorage')
local TextService = game:GetService('TextService')
local TweenService = game:GetService('TweenService')
local Storage = ServerStorage.MCServerLink
local PlayerAdded = Storage.PlayerAdded
local PlayerRemoving = Storage.PlayerRemoving
local PlayerMove = Storage.PlayerMove
local BaseModel = Storage.Base
local CurrentPlayersFolder = workspace.MCCurrentPlayers
local TInfo = TweenInfo.new(1/6, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 0, false)
local function GetPlayerModel(Username)
local Model = CurrentPlayersFolder:FindFirstChild(Username)
if not Model then
Model = BaseModel:Clone()
Model.Name = Username
Model.Head.NameGui.NameLabel.Text = Username
-- not depending on the label here
local TextSize = TextService:GetTextSize(Username, 100, Enum.Font.Gotham, Vector2.new(2000, 100))
Model.Head.NameGui.Background.Size = UDim2.new((TextSize.X / 2000) + 0.01, 0, 1, 0)
Model.Parent = CurrentPlayersFolder
end
return Model
end
local function MovePlayer(Model, Position, Orientation)
local CF = CFrame.Angles(0, -math.rad(Orientation.Y + 180), 0)
CF = CF:ToWorldSpace(CFrame.new())
local Goal = {['CFrame'] = CF + (Position * 4)}
local Tween = TweenService:Create(Model.PrimaryPart, TInfo, Goal)
Tween:Play()
end
local function HandlePlayerChange(Username, Position, Orientation)
local Model = GetPlayerModel(Username)
MovePlayer(Model, Position, Orientation)
end
local function HandlePlayerRemove(Username)
local Model = CurrentPlayersFolder:FindFirstChild(Username)
if Model then
Model:Destroy()
end
end
PlayerAdded.Event:Connect(HandlePlayerChange)
PlayerMove.Event:Connect(HandlePlayerChange)
PlayerRemoving.Event:Connect(HandlePlayerRemove)