Medieval Dreams

Started by William, July 12, 2023, 20:29:04

Previous topic - Next topic

William

#30
I thought about using Input("Command>:") from the brl.standardio, i tried that but it freezes main thread until an input is entered.. blitzmax needs to have this different so that it may still process during input, is this meant to be multithreaded for use in these cases? i also wish to print at the same time as waiting for input, for commands like shutdown/close/exit/stop

meanwhile, gnet error still occurs and i do not know why.
im still interested in oldschool app/gamedev

Derron

the error happens because of either server or client behaved differently to how they should - maybe you block communication (using input...) and thus host disconnects you and similar stuff.


next to "input()" you can always use your own way of reading key strokes/hits ... with "KeyHit()" and "KeyDown()" ... 
KeyHit means "was down and is now up" while KeyDown is true as long as you keep a key down.
It is up to you to implement "repeated" keys (keeping "b" down and each second a new "b" is registered...)

To read "commands" you simply add all the keys to a "currentInput:string" until KeyHit(KEY_ENTER) is true ... or whatever your "send command" key will be. Then interpret whatever is stored in "currentInput" and do not forget to clear it afterwards (currentInput = "").

There surely exist solutions for this in the internet or "code archives".


PS: checking "i=0 to 255 KeyHit(i)" is not the best performing approach as you would poll the system for each check 
brl.mod/polledinput.mod has "keyHits[]"  but it is private.
But a long while ago NG (not vanilla) added "SetAutoPoll()".

Before checking a lot of KeyHit or KeyDown you could do
PollSystem() 'refreshes all key states
SetAutoPoll(False)
For local i:int = 0 until 255
  If KeyHit(i) ...
Next
SetAutoPoll(True)
And thus saving 254 PollSystem() calls.


While checking that polledinput.bmx-source you might also find
Rem
bbdoc: Get next character
returns: The character code of the next character.
about:
As the user hits keys on the keyboard, BlitzMax records the character codes of these
keystrokes into an internal 'character queue'.

#GetChar removes the next character code from this queue and returns it the application.

If the character queue is empty, 0 is returned.
End Rem
Function GetChar()
If autoPoll PollSystem
If charGet=charPut Return 0
Local n=charQueue[charGet & 255]
charGet:+1
Return n
End Function

Which is another way to retrieve "currently down" keys (DOWN! not HIT!). It would be up to you then to identify "nothing pressed" (Getchar() returns 0 if the queue is empty). And there also the SetAutoPoll-optimization can be applied.


bye
Ron

Midimaster

Delay returns the performance back to the OS! Without it your app has 100% performance and the OS cannot work anymore. This leads to 100.000 loops. In a single CORE CPU now the OS cannot process what you told it. (Nowadays it is better, because all computers have multi-COREs.). In a multi-CORE-CPU another CORE is blocked with working these 100.000 GNET-Sync calls. If you do this the same way with more than 4 BlitzMax-apps you will get a big problem.

With a simple DELAY 1 your loop cannot work more than 1000 times a second, which is still enough. But now 99% of the performance is avaible for the OS. Typicall I woud use a DELAY 16, which equals to the speed a FLIP 1 produces.

Your app is far away from needing Multi-Treads. Do not add this to your app. But... A Delay 1 is helpful for multi-treading
...back from Egypt

Derron

Quote from: Midimaster on August 15, 2023, 09:25:50With a simple DELAY 1 your loop cannot work more than 1000 times a second, which is still enough. But now 99% of the performance is avaible for the OS. Typicall I woud use a DELAY 16, which equals to the speed a FLIP 1 produces.
only if you are on a 60hz display - which is less and less common amongst nowadays users.

You'd better only delay(x) if you can afford it (means ... measuring the time since "last tick"). Which you might already know from deltatiming, tweening, ...


bye
Ron

William

#34
@Derron it is a linux machine with no gpu just visual console no mouse only keyboard. for whatever reason, i believe due to that, importing brl.polledinput the console app will segment fault and not run. both options are out. standardio should not stall the app, can it be multithreaded is that the intended idea? which area may be multithreaded. i'll look at the docs at some time and try it myself, that would seem to be the optimal method for these purposes.

edit: yup, input can be threaded, feels good. i just have to read the docs more for it to be asynchronous with printing but it seems to be working.
im still interested in oldschool app/gamedev

Derron

#35
Why does polledinput not work in a console? Is it because of the x-Server? (the x-server is the one sending out events which the brl modules like polledinput use to fetch keypresses, mouse button clicks etc - on Windows).

If you do not have an x-Server installed you might indeed have to use something like stdio to receive input.
For this you open the input stream and in your loop you check for available new content. append as usual until you find an "~n" and interpret whatever you have read till then.
This should not be blocking your rest of the code.



BTW I did not think about it yet - but if you really want to use threading you might consider running the "server" in a sub thread and do the user interaction (input ...) in the main thread. so to say the server without "communication" is one program, and the "control" is another program. Your complete program is then 2 threads: control + server.
If they were 2 programmes the "server" would listen on its input stream for commands and send results to the output (communication could also be done with sockets, files ...). The control software could then run on such a terminal - or even on your local computer with a nice graphical gui. So to say ... remote control. You might have tried MySQL workbench, phpmyadmin, dashboard software ... they all work this way (communicating via some API, sockets, ...)

Anyways - it should be doable in a single threaded app already as long as we do not talk about megabytes of input per second :)

bye
Ron

William

#36
small question - why does
CloseGNetHost(host)
If host
Print "server still running after loop shutdown"
Else Print "Server closed" EndIf
return host, as in server is still running.

that bit of code is at the bottom after the loop main has stopped.

update, network has been optimized by syncing Game Net after players have moved or somebody made changes to gnet itself but the remote server clients do not appear laggy/missing positions skipping around.. still, further changes are necessary for higher latency to gradually position other players from their last coordinate to their latest coordinate for overseas players or poor connections. i need to learn what the function move entity really does, if it moves incrementally. for this purpose i need to find the most efficient method for high latency/network efficiency performance. that may be later.  for now i believe gameplay is next like object entities ingame and player combat, the fun stuff.
im still interested in oldschool app/gamedev

Derron

Quote from: William on August 19, 2023, 02:30:07small question - why does
CloseGNetHost(host)
If host
Print "server still running after loop shutdown"
Else Print "Server closed" EndIf
return host, as in server is still running.

that bit of code is at the bottom after the loop main has stopped.

That code is rather useless ... because "CloseGNetHost(host)" only calls "host.close()" - which surely closes "enet" internally etc ... but it does not remove "host".


bye
Ron 

William

i am still interested in this project, i am still working on it. i wish i had posted in a clearer manner, openb3d seems to be the modeled to my game it is as if.. idk what history of blitz3d the aspiration were from in that contemporary time.

i have been putting animation and modeling for later, looking to develop combat and point systems next. had some inspiration the way to design neural networks "learning requires a feedback loop, where the network is given additional information about the consequences of an action". developing gameplay first.
im still interested in oldschool app/gamedev

William

decided to load test. to my discovery each time an entity is copied, on my machine, it loads the next time slower. no performance cost ingame without all 100 entities moving at (seemingly) the same time and animated and of this that i have not tested performance.

so, ideally, i would like combat to be up to 100 player bots at a time, animated, moving and may involve linepicking or may not? registering fps sword fights. other games have accomplished that with multithreading i believe openb3d could not be multithreaded via blitzmax threads. there were a minib3d bmx module that threaded animation and model loading called cal3d? i may still have the files though uncertain and also out of date.

i can scale though. what can we conceptualize here? midimaster suggested developing for like 3 players, that is true it is for 3 to 5 players but then i wish to have medieval fantasy game servers as well even if only 2 or 3 users were playing with kingdom actor bot character players, equaling between 100 to 300 bots? that seems reasonable. 20 to forage, woodcut and mine, 20 to farm and build, 20 to fight, 20 to guard, more to trade between kingdoms? the list goes on. minecraft were able to support hundreds of players as it were simple game actions. economy.

We're going to have some fun. 5 kingdoms, 100 player bots per kingdom, 5 players and or some more depending on what kind of role the player servers game players may have so after strategic kingdoms fantasy rpg too? i come from the game runescape and it had some of the best medieval fantasy. im not ruling out medieval fantasy but i think strategic kingdoms with some fantasy is at the heart of my dream of creating a game.

so.. zone instancing, and zone tiling systems.. i took some notes from discord gwron and midimaster were talking about player network scaling i can read later for network performance.

what is your vision? part of the challange in oldschool games was games working with the limitations they had, part of what made games unique was how the developers designed with that.
im still interested in oldschool app/gamedev

William

what kind of vision of the scope of the game do any of you have of the scale/instancing/tiles, any unique ideas for gameplay/world scaling?
im still interested in oldschool app/gamedev

William

#41
sheeks,midimaster your suggestion on hiding entities until they need to be visible worth considering, idk it might become too complex for me regarding pathfinding, i were going to use a lib but like even if a userplayer does not see them they need to be doing their thing

i felt relieved my project might not be feasible that i may be done with this. when i begin working a job i might work on this  project during spare time. i were going to use astar pathfinding from the code archives thinking the performance costs may be too great. i will have to work something out.
im still interested in oldschool app/gamedev

William

#42
worklog: just some thoughts. october 01, 2023.

i dont know if time on this project is worth it. it does look cool on linux. just that perhaps those years on the computer why i had problems later in life. when im working.

well, i figure i need to tell clients of nearby players only when in range.. i don't know how many players gnet can network at a time, each player requires a gnet object to be networked. also i need to design a user login interface before loading the game zone and player. its a behemoth already to do this. if i can have a perspective vision of how, then i can do it. some kind of name structure is needed to know which entity has been selected? even if it can return specific entities, i have no way of identifying them without a player ID and even then it requires sorting through all players each pick to reference that specific player.
im still interested in oldschool app/gamedev

Midimaster

#43
You already have a "name" feature in your code. At the moment all clients are named "client". but you can give them individual names. It is not necessary to do that at the very beginning. You can open an input box and send this name via GNET at any time to the other clients. So also PlayerEntity can fetch this name to name the Entity.

Open a input box is a little bit tricky when you are in3D. So here is a tutorial


Here is a demo that shows how to add an input box to a running 3D game. you can add BlitzMax-2D-Graphic-Stuff when you use the commands StartMax2d() and EndMax2D():
Repeat
    RenderWorld
    cube.TurnEntity .1,.1,.1
    BeginMax2D
        InputBox.Show()
        ...
    EndMax2D
    If KeyHit(KEY_N) InputBox.Open
    Flip 1
Until AppTerminate()

Press <N> to start a rectangle input box. From now on the InputBox gets all KEYs.

The InputBox cares about three things: Display the BOX and the TEXT, Blinking the CURSOR and Combining the KEYs to a TEXT

   
Function Show:Int()
    DrawRect 300,250,204,104
    DrawText Text + ShowCursor(), 320,300
    Return  CheckKeys()
End Function

Function ShowCursor:String()
    If Cursor=" " Then Cursor="_" Else Cursor=" "
    Return Cursor
End Function

Function CheckKeys:Int()
    Local Key:Int=GetChar()
    Select Key
        Case 13
            Return True
        Default
            Text = Text + Upper(Chr(key))
    End Select
    Return False
End Function



When the user presses RETURN (=13) the function returns TRUE into the main loop and we can fetch the input string:

Function GetInput:String ()
    Return Text
End Function

This all is encapsuled in a TYPE not to get in conflict with external variable names:


runable demo-app:

Import openb3d.B3dglgraphics
Graphics3D 800,600,0,2

' a 3D scene:
Global Cube:TEntity = CreateCube()
Cube.MoveEntity 0,0,5
Global Light:TLight = CreateLight(1)
Light.MoveEntity -13,5,0
Global Camera:TCamera = CreateCamera()
Camera.MoveEntity -1,1,0


' user name press <n> to open InputBox
Global UserName:String


Repeat
    RenderWorld
    cube.TurnEntity .1,.1,.1
    BeginMax2D
        If InputBox.Show()=True
            UserName = InputBox.GetInput()
            Print "USERNAME " + Username
        EndIf
    EndMax2D
    If KeyHit(KEY_N) InputBox.Open
    Flip 1
Until AppTerminate()


Type InputBox
    ' opens a input box for text
    ' keeps open until RETURN is pressed
    Global Text:String, Blink:Int, Cursor:String


' ** P U B L I C  ***

    ' use this command to start the inputbox:
    Function Open()
        Print "open"
        Text  = ""
        Blink = MilliSecs()
        FlushKeys
    End Function


    ' call this function all the time in main loop:
    Function Show:Int()
        ' function returns FALSE when invisible or not finished
        ' function returns TRUE  when Input$ is finished, ready to fetch
        If Blink = 0 Return False
        SetColor 255,0,0
        DrawRect 300,250,204,104
        SetColor 111,111,111
        DrawRect 302,252,200,100
       
        SetScale 2,2
        SetColor 1,1,1
        DrawText Text + ShowCursor(), 320,300
        Return  CheckKeys()
    End Function


    ' call this function to receive the input$ and close the box:
    Function GetInput:String ()
            Blink = 0
            Return Text
    End Function
   
   
' ** P R I V A T ***
    'internal use
    Function ShowCursor:String()
        If Blink<MilliSecs()
            Blink=MilliSecs()+500
            If     Cursor=" " Then Cursor="_" Else Cursor=" "
        EndIf
        Return Cursor
    End Function

   
    'internal use
    Function CheckKeys:Int()
        Local Key:Int=GetChar()
        If Key=0 Then Return False
        Print key
        Select Key
            Case 13
                Return True
            Case 8
                Text=Text[..Text.length-1]
            Default
                Text = Text + Upper(Chr(key))
        End Select
        Return False
    End Function
End Type



Finding the right one is very easy and also with 500 players no problem:

   local Who:TPlayer = TPlayer.FindPicked(PickedEntity)
Print Who.Name
...
Type TPlayer
    ....
   Function FindPicked:TPlayer(SearchEntity:TEntity)
      For local Player:TPlayer=EachIn All
         If Player.Entity = SearchEntity
         Return player
      Next
   End function
...back from Egypt

William

#44
do you know are there functions for 3d text or dialogue for messages and names in openb3d or bmx?
im still interested in oldschool app/gamedev