add readme's, remove testing prints
This commit is contained in:
parent
b44d3e03ca
commit
36579a0784
|
@ -1,2 +1,4 @@
|
||||||
# mmo-project
|
# mmo-project
|
||||||
|
|
||||||
|
A programming chrestonomy project where various mmo systems are compared
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -1,7 +1,8 @@
|
||||||
# Programming Language Project Fortran Implementation or, a Fortran CGI program abuses a sqlite3 database to implement a game server
|
# Fortran MMO Project Implementation or, a Frankensteins moster of a Fortran program abuses a sqlite3 database to implement a game server.
|
||||||
|
|
||||||
[fortran-µhttpd (game website & webserver)](./www/README.md)
|
[fortran-µhttpd (game website & webserver)](./www/README.md)
|
||||||
|
|
||||||
server (game backend)
|
[fortran-mmo-server (game backend)](./server/README.md)
|
||||||
|
|
||||||
|
[fortran-mmo-client (game frontend / UI)](./client/README.md)
|
||||||
|
|
||||||
client (game frontend / UI)
|
|
||||||
|
|
|
@ -1,5 +1,31 @@
|
||||||
# fortran mmo-project client
|
# fortran mmo-project client
|
||||||
|
|
||||||
pipes suck and dont work, try wrapping the libdill library instead.
|
The client uses the same mod_dill library from the [tcp-client-server demo](https://github.com/modern-fortran/tcp-client-server)
|
||||||
|
|
||||||
|
Also the [raylib library](https://www.raylib.com/). I have generated a fortran interface for the functions neccisary for a minimal client. The module is using the new C interop interface implemented in the 2018 spec which makes it fairly easy to create a interface between a C library and Fortran.
|
||||||
|
|
||||||
|
One thing to note in here is that Fortran does not actually have unsigned values, so you have to use normal integers and use the `-fno-range-check` flag to tell the compiler that you know what you are doing. Otherwise the colors would not look correct.
|
||||||
|
|
||||||
|
For simplicity I have made it so that the login credentials are passed in through the command line instead of a GUI interface.
|
||||||
|
|
||||||
|
Fortran has the ability to use the OOP paradigm so I wanted to show that off here with the player module.
|
||||||
|
|
||||||
|
The player is able to store their own name, position, and color. There is an interface to allow the client to sync the camera and send the position to the server.
|
||||||
|
|
||||||
|
You can also see the json library shine with this implementation. It made it trivial to process the json array that was built and sent from the server.
|
||||||
|
|
||||||
|
The only other thing to note is the weird modulo chunk here:
|
||||||
|
|
||||||
|
``` fortran
|
||||||
|
time = get_time()
|
||||||
|
if (modulo(time, 1.0) .ge. 0.58_c_double) then
|
||||||
|
if (player_updated) then
|
||||||
|
players = me%move()
|
||||||
|
else
|
||||||
|
players = me%ping()
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
```
|
||||||
|
|
||||||
|
This is because there is not a good way to asyncronously send a call to the server, so I have this hack which uses the current tick time from raylib and run the update/ping function every 500 milliseconds or so.
|
||||||
|
|
||||||
libdill library from https://github.com/modern-fortran/tcp-client-server
|
|
||||||
|
|
|
@ -18,13 +18,6 @@ program main
|
||||||
logical :: player_updated, exist
|
logical :: player_updated, exist
|
||||||
real(c_double) :: time
|
real(c_double) :: time
|
||||||
|
|
||||||
inquire (file="debug.log", exist=exist)
|
|
||||||
if (exist) then
|
|
||||||
open (12, file="debug.log", status="old", position="append", action="write")
|
|
||||||
else
|
|
||||||
open (12, file="debug.log", status="new", action="write")
|
|
||||||
end if
|
|
||||||
|
|
||||||
call getarg(1, username)
|
call getarg(1, username)
|
||||||
call getarg(2, password)
|
call getarg(2, password)
|
||||||
|
|
||||||
|
@ -60,7 +53,7 @@ program main
|
||||||
call me%sync_camera(camera)
|
call me%sync_camera(camera)
|
||||||
|
|
||||||
time = get_time()
|
time = get_time()
|
||||||
if (modulo(time, 1.0) .ge. 0.98_c_double) then
|
if (modulo(time, 1.0) .ge. 0.58_c_double) then
|
||||||
if (player_updated) then
|
if (player_updated) then
|
||||||
players = me%move()
|
players = me%move()
|
||||||
else
|
else
|
||||||
|
@ -89,6 +82,5 @@ program main
|
||||||
deallocate (players)
|
deallocate (players)
|
||||||
end if
|
end if
|
||||||
call close_window() !Close window and OpenGL context
|
call close_window() !Close window and OpenGL context
|
||||||
close (12)
|
|
||||||
|
|
||||||
end program main
|
end program main
|
||||||
|
|
|
@ -36,8 +36,6 @@ contains
|
||||||
character(24) :: password
|
character(24) :: password
|
||||||
type(player), dimension(:), allocatable :: players
|
type(player), dimension(:), allocatable :: players
|
||||||
|
|
||||||
print *, password
|
|
||||||
|
|
||||||
players = send_packet(this, 1)
|
players = send_packet(this, 1)
|
||||||
end function login
|
end function login
|
||||||
|
|
||||||
|
@ -115,7 +113,7 @@ contains
|
||||||
call json%add(root, user)
|
call json%add(root, user)
|
||||||
call json%serialize(root, str)
|
call json%serialize(root, str)
|
||||||
|
|
||||||
call json%print(root)
|
! call json%print(root)
|
||||||
|
|
||||||
connection = suffix_attach(connection, TCP_SUFFIX, 2_c_size_t)
|
connection = suffix_attach(connection, TCP_SUFFIX, 2_c_size_t)
|
||||||
|
|
||||||
|
@ -128,7 +126,7 @@ contains
|
||||||
|
|
||||||
message_size = mrecv(connection, message, msglen, -1_c_int64_t)
|
message_size = mrecv(connection, message, msglen, -1_c_int64_t)
|
||||||
|
|
||||||
print *, 'message=', message
|
! print *, 'message=', message
|
||||||
|
|
||||||
call c_f_string(message, jsn_string)
|
call c_f_string(message, jsn_string)
|
||||||
|
|
||||||
|
|
|
@ -20,31 +20,7 @@ module raylib
|
||||||
integer(c_int8_t) :: a
|
integer(c_int8_t) :: a
|
||||||
end type
|
end type
|
||||||
|
|
||||||
type(color) :: LIGHTGRAY = color(200, 200, 200, 255)
|
|
||||||
type(color) :: GRAY = color(130, 130, 130, 255)
|
|
||||||
type(color) :: DARKGRAY = color(80, 80, 80, 255)
|
|
||||||
type(color) :: YELLOW = color(253, 249, 0, 255)
|
|
||||||
type(color) :: GOLD = color(255, 203, 0, 255)
|
|
||||||
type(color) :: ORANGE = color(255, 161, 0, 255)
|
|
||||||
type(color) :: PINK = color(255, 109, 194, 255)
|
|
||||||
type(color) :: RED = color(230, 41, 55, 255)
|
|
||||||
type(color) :: MAROON = color(190, 33, 55, 255)
|
|
||||||
type(color) :: GREEN = color(0, 228, 48, 255)
|
|
||||||
type(color) :: LIME = color(0, 158, 47, 255)
|
|
||||||
type(color) :: DARKGREEN = color(0, 117, 44, 255)
|
|
||||||
type(color) :: SKYBLUE = color(102, 191, 255, 255)
|
|
||||||
type(color) :: BLUE = color(0, 121, 241, 255)
|
|
||||||
type(color) :: DARKBLUE = color(0, 82, 172, 255)
|
|
||||||
type(color) :: PURPLE = color(200, 122, 255, 255)
|
type(color) :: PURPLE = color(200, 122, 255, 255)
|
||||||
type(color) :: VIOLET = color(135, 60, 190, 255)
|
|
||||||
type(color) :: DARKPURPLE = color(112, 31, 126, 255)
|
|
||||||
type(color) :: BEIGE = color(211, 176, 131, 255)
|
|
||||||
type(color) :: BROWN = color(127, 106, 79, 255)
|
|
||||||
type(color) :: DARKBROWN = color(76, 63, 47, 255)
|
|
||||||
type(color) :: WHITE = color(255, 255, 255, 255)
|
|
||||||
type(color) :: BLACK = color(0, 0, 0, 255)
|
|
||||||
type(color) :: BLANK = color(0, 0, 0, 0)
|
|
||||||
type(color) :: MAGENTA = color(255, 0, 255, 255)
|
|
||||||
type(color) :: RAYWHITE = color(245, 245, 245, 255)
|
type(color) :: RAYWHITE = color(245, 245, 245, 255)
|
||||||
|
|
||||||
type, bind(c) :: camera3d
|
type, bind(c) :: camera3d
|
||||||
|
@ -55,297 +31,12 @@ module raylib
|
||||||
integer(c_int) :: projection
|
integer(c_int) :: projection
|
||||||
end type
|
end type
|
||||||
|
|
||||||
! Keyboard keys
|
|
||||||
integer(c_int) :: KEY_NULL = 0
|
|
||||||
! Alphanumeric keys
|
|
||||||
integer(c_int) :: KEY_APOSTROPHE = 39
|
|
||||||
integer(c_int) :: KEY_COMMA = 44
|
|
||||||
integer(c_int) :: KEY_MINUS = 45
|
|
||||||
integer(c_int) :: KEY_PERIOD = 46
|
|
||||||
integer(c_int) :: KEY_SLASH = 47
|
|
||||||
integer(c_int) :: KEY_ZERO = 48
|
|
||||||
integer(c_int) :: KEY_ONE = 49
|
|
||||||
integer(c_int) :: KEY_TWO = 50
|
|
||||||
integer(c_int) :: KEY_THREE = 51
|
|
||||||
integer(c_int) :: KEY_FOUR = 52
|
|
||||||
integer(c_int) :: KEY_FIVE = 53
|
|
||||||
integer(c_int) :: KEY_SIX = 54
|
|
||||||
integer(c_int) :: KEY_SEVEN = 55
|
|
||||||
integer(c_int) :: KEY_EIGHT = 56
|
|
||||||
integer(c_int) :: KEY_NINE = 57
|
|
||||||
integer(c_int) :: KEY_SEMICOLON = 59
|
|
||||||
integer(c_int) :: KEY_EQUAL = 61
|
|
||||||
integer(c_int) :: KEY_A = 65
|
|
||||||
integer(c_int) :: KEY_B = 66
|
|
||||||
integer(c_int) :: KEY_C = 67
|
|
||||||
integer(c_int) :: KEY_D = 68
|
|
||||||
integer(c_int) :: KEY_E = 69
|
|
||||||
integer(c_int) :: KEY_F = 70
|
|
||||||
integer(c_int) :: KEY_G = 71
|
|
||||||
integer(c_int) :: KEY_H = 72
|
|
||||||
integer(c_int) :: KEY_I = 73
|
|
||||||
integer(c_int) :: KEY_J = 74
|
|
||||||
integer(c_int) :: KEY_K = 75
|
|
||||||
integer(c_int) :: KEY_L = 76
|
|
||||||
integer(c_int) :: KEY_M = 77
|
|
||||||
integer(c_int) :: KEY_N = 78
|
|
||||||
integer(c_int) :: KEY_O = 79
|
|
||||||
integer(c_int) :: KEY_P = 80
|
|
||||||
integer(c_int) :: KEY_Q = 81
|
|
||||||
integer(c_int) :: KEY_R = 82
|
|
||||||
integer(c_int) :: KEY_S = 83
|
|
||||||
integer(c_int) :: KEY_T = 84
|
|
||||||
integer(c_int) :: KEY_U = 85
|
|
||||||
integer(c_int) :: KEY_V = 86
|
|
||||||
integer(c_int) :: KEY_W = 87
|
|
||||||
integer(c_int) :: KEY_X = 88
|
|
||||||
integer(c_int) :: KEY_Y = 89
|
|
||||||
integer(c_int) :: KEY_Z = 90
|
|
||||||
! Function keys
|
|
||||||
integer(c_int) :: KEY_SPACE = 32
|
|
||||||
integer(c_int) :: KEY_ESCAPE = 256
|
|
||||||
integer(c_int) :: KEY_ENTER = 257
|
|
||||||
integer(c_int) :: KEY_TAB = 258
|
|
||||||
integer(c_int) :: KEY_BACKSPACE = 259
|
|
||||||
integer(c_int) :: KEY_INSERT = 260
|
|
||||||
integer(c_int) :: KEY_DELETE = 261
|
|
||||||
integer(c_int) :: KEY_RIGHT = 262
|
integer(c_int) :: KEY_RIGHT = 262
|
||||||
integer(c_int) :: KEY_LEFT = 263
|
integer(c_int) :: KEY_LEFT = 263
|
||||||
integer(c_int) :: KEY_DOWN = 264
|
integer(c_int) :: KEY_DOWN = 264
|
||||||
integer(c_int) :: KEY_UP = 265
|
integer(c_int) :: KEY_UP = 265
|
||||||
integer(c_int) :: KEY_PAGE_UP = 266
|
|
||||||
integer(c_int) :: KEY_PAGE_DOWN = 267
|
|
||||||
integer(c_int) :: KEY_HOME = 268
|
|
||||||
integer(c_int) :: KEY_END = 269
|
|
||||||
integer(c_int) :: KEY_CAPS_LOCK = 280
|
|
||||||
integer(c_int) :: KEY_SCROLL_LOCK = 281
|
|
||||||
integer(c_int) :: KEY_NUM_LOCK = 282
|
|
||||||
integer(c_int) :: KEY_PRINT_SCREEN = 283
|
|
||||||
integer(c_int) :: KEY_PAUSE = 284
|
|
||||||
integer(c_int) :: KEY_F1 = 290
|
|
||||||
integer(c_int) :: KEY_F2 = 291
|
|
||||||
integer(c_int) :: KEY_F3 = 292
|
|
||||||
integer(c_int) :: KEY_F4 = 293
|
|
||||||
integer(c_int) :: KEY_F5 = 294
|
|
||||||
integer(c_int) :: KEY_F6 = 295
|
|
||||||
integer(c_int) :: KEY_F7 = 296
|
|
||||||
integer(c_int) :: KEY_F8 = 297
|
|
||||||
integer(c_int) :: KEY_F9 = 298
|
|
||||||
integer(c_int) :: KEY_F10 = 299
|
|
||||||
integer(c_int) :: KEY_F11 = 300
|
|
||||||
integer(c_int) :: KEY_F12 = 301
|
|
||||||
integer(c_int) :: KEY_LEFT_SHIFT = 340
|
|
||||||
integer(c_int) :: KEY_LEFT_CONTROL = 341
|
|
||||||
integer(c_int) :: KEY_LEFT_ALT = 342
|
|
||||||
integer(c_int) :: KEY_LEFT_SUPER = 343
|
|
||||||
integer(c_int) :: KEY_RIGHT_SHIFT = 344
|
|
||||||
integer(c_int) :: KEY_RIGHT_CONTROL = 345
|
|
||||||
integer(c_int) :: KEY_RIGHT_ALT = 346
|
|
||||||
integer(c_int) :: KEY_RIGHT_SUPER = 347
|
|
||||||
integer(c_int) :: KEY_KB_MENU = 348
|
|
||||||
integer(c_int) :: KEY_LEFT_BRACKET = 91
|
|
||||||
integer(c_int) :: KEY_BACKSLASH = 92
|
|
||||||
integer(c_int) :: KEY_RIGHT_BRACKET = 93
|
|
||||||
integer(c_int) :: KEY_GRAVE = 96
|
|
||||||
! Keypad keys
|
|
||||||
integer(c_int) :: KEY_KP_0 = 320
|
|
||||||
integer(c_int) :: KEY_KP_1 = 321
|
|
||||||
integer(c_int) :: KEY_KP_2 = 322
|
|
||||||
integer(c_int) :: KEY_KP_3 = 323
|
|
||||||
integer(c_int) :: KEY_KP_4 = 324
|
|
||||||
integer(c_int) :: KEY_KP_5 = 325
|
|
||||||
integer(c_int) :: KEY_KP_6 = 326
|
|
||||||
integer(c_int) :: KEY_KP_7 = 327
|
|
||||||
integer(c_int) :: KEY_KP_8 = 328
|
|
||||||
integer(c_int) :: KEY_KP_9 = 329
|
|
||||||
integer(c_int) :: KEY_KP_DECIMAL = 330
|
|
||||||
integer(c_int) :: KEY_KP_DIVIDE = 331
|
|
||||||
integer(c_int) :: KEY_KP_MULTIPLY = 332
|
|
||||||
integer(c_int) :: KEY_KP_SUBTRACT = 333
|
|
||||||
integer(c_int) :: KEY_KP_ADD = 334
|
|
||||||
integer(c_int) :: KEY_KP_ENTER = 335
|
|
||||||
integer(c_int) :: KEY_KP_EQUAL = 336
|
|
||||||
! Android key buttons
|
|
||||||
integer(c_int) :: KEY_BACK = 4
|
|
||||||
integer(c_int) :: KEY_MENU = 82
|
|
||||||
integer(c_int) :: KEY_VOLUME_UP = 24
|
|
||||||
integer(c_int) :: KEY_VOLUME_DOWN = 25
|
|
||||||
! Mouse buttons
|
|
||||||
integer(c_int) :: MOUSE_LEFT_BUTTON = 0
|
|
||||||
integer(c_int) :: MOUSE_RIGHT_BUTTON = 1
|
|
||||||
integer(c_int) :: MOUSE_MIDDLE_BUTTON = 2
|
|
||||||
! Mouse cursor
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_DEFAULT = 0
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_ARROW = 1
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_IBEAM = 2
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_CROSSHAIR = 3
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_POINTING_HAND = 4
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_RESIZE_EW = 5
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_RESIZE_NS = 6
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_RESIZE_NWSE = 7
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_RESIZE_NESW = 8
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_RESIZE_ALL = 9
|
|
||||||
integer(c_int) :: MOUSE_CURSOR_NOT_ALLOWED = 10
|
|
||||||
! Gamepad buttons
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_UNKNOWN = 0
|
|
||||||
! This is normally a DPAD
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_LEFT_FACE_UP = 1
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_LEFT_FACE_RIGHT = 2
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_LEFT_FACE_DOWN = 3
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_LEFT_FACE_LEFT = 4
|
|
||||||
! This normally corresponds with PlayStation and Xbox controllers
|
|
||||||
! XBOX: [Y,X,A,B]
|
|
||||||
! PS3: [Triangle,Square,Cross,Circle]
|
|
||||||
! No support for 6 button controllers though..
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_RIGHT_FACE_UP = 5
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_RIGHT_FACE_RIGHT = 6
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_RIGHT_FACE_DOWN = 7
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_RIGHT_FACE_LEFT = 8
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_LEFT_TRIGGER_1 = 9
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_LEFT_TRIGGER_2 = 10
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_RIGHT_TRIGGER_1 = 11
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_RIGHT_TRIGGER_2 = 12
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_MIDDLE_LEFT = 13 ! PS3 Select
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_MIDDLE = 14 ! PS Button/XBOX Button
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_MIDDLE_RIGHT = 15 ! PS3 Start
|
|
||||||
! These are the joystick press in buttons
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_LEFT_THUMB = 16
|
|
||||||
integer(c_int) :: GAMEPAD_BUTTON_RIGHT_THUMB = 17
|
|
||||||
! Gamepad axis
|
|
||||||
integer(c_int) :: GAMEPAD_AXIS_LEFT_X = 0
|
|
||||||
integer(c_int) :: GAMEPAD_AXIS_LEFT_Y = 1
|
|
||||||
integer(c_int) :: GAMEPAD_AXIS_RIGHT_X = 2
|
|
||||||
integer(c_int) :: GAMEPAD_AXIS_RIGHT_Y = 3
|
|
||||||
integer(c_int) :: GAMEPAD_AXIS_LEFT_TRIGGER = 4 ! [1..-1] (pressure-level)
|
|
||||||
integer(c_int) :: GAMEPAD_AXIS_RIGHT_TRIGGER = 5 ! [1..-1] (pressure-level)
|
|
||||||
! Material map index
|
|
||||||
integer(c_int) :: MATERIAL_MAP_ALBEDO = 0
|
|
||||||
integer(c_int) :: MATERIAL_MAP_DIFFUSE = 0 ! same as MATERIAL_MAP_ALBEDO
|
|
||||||
integer(c_int) :: MATERIAL_MAP_METALNESS = 1
|
|
||||||
integer(c_int) :: MATERIAL_MAP_SPECULAR = 1 ! same as MATERIAL_MAP_METALNESS
|
|
||||||
integer(c_int) :: MATERIAL_MAP_NORMAL = 2
|
|
||||||
integer(c_int) :: MATERIAL_MAP_ROUGHNESS = 3
|
|
||||||
integer(c_int) :: MATERIAL_MAP_OCCLUSION = 4
|
|
||||||
integer(c_int) :: MATERIAL_MAP_EMISSION = 5
|
|
||||||
integer(c_int) :: MATERIAL_MAP_HEIGHT = 6
|
|
||||||
integer(c_int) :: MATERIAL_MAP_BRDG = 7
|
|
||||||
integer(c_int) :: MATERIAL_MAP_CUBEMAP = 8 ! NOTE: Uses GL_TEXTURE_CUBE_MAP
|
|
||||||
integer(c_int) :: MATERIAL_MAP_IRRADIANCE = 9 ! NOTE: Uses GL_TEXTURE_CUBE_MAP
|
|
||||||
integer(c_int) :: MATERIAL_MAP_PREFILTER = 10 ! NOTE: Uses GL_TEXTURE_CUBE_MAP
|
|
||||||
! Shader location index
|
|
||||||
integer(c_int) :: SHADER_LOC_VERTEX_POSITION = 0
|
|
||||||
integer(c_int) :: SHADER_LOC_VERTEX_TEXCOORD01 = 1
|
|
||||||
integer(c_int) :: SHADER_LOC_VERTEX_TEXCOORD02 = 2
|
|
||||||
integer(c_int) :: SHADER_LOC_VERTEX_NORMAL = 3
|
|
||||||
integer(c_int) :: SHADER_LOC_VERTEX_TANGENT = 4
|
|
||||||
integer(c_int) :: SHADER_LOC_VERTEX_COLOR = 5
|
|
||||||
integer(c_int) :: SHADER_LOC_MATRIX_MVP = 6
|
|
||||||
integer(c_int) :: SHADER_LOC_MATRIX_VIEW = 7
|
|
||||||
integer(c_int) :: SHADER_LOC_MATRIX_PROJECTION = 8
|
|
||||||
integer(c_int) :: SHADER_LOC_MATRIX_MODEL = 9
|
|
||||||
integer(c_int) :: SHADER_LOC_MATRIX_NORMAL = 10
|
|
||||||
integer(c_int) :: SHADER_LOC_VECTOR_VIEW = 11
|
|
||||||
integer(c_int) :: SHADER_LOC_COLOR_DIFFUSE = 12
|
|
||||||
integer(c_int) :: SHADER_LOC_COLOR_SPECULAR = 13
|
|
||||||
integer(c_int) :: SHADER_LOC_COLOR_AMBIENT = 14
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_ALBEDO = 15
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_DIFFUSE = 15 ! same as SHADER_LOC_MAP_ALBEDO
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_METALNESS = 16
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_SPECULAR = 16 ! same as SHADER_LOC_MAP_METALNESS
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_NORMAL = 17
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_ROUGHNESS = 18
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_OCCLUSION = 19
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_EMISSION = 20
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_HEIGHT = 21
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_CUBEMAP = 22
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_IRRADIANCE = 23
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_PREFILTER = 24
|
|
||||||
integer(c_int) :: SHADER_LOC_MAP_BRDF = 25
|
|
||||||
! Shader uniform data type
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_FLOAT = 0
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_VEC2 = 1
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_VEC3 = 2
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_VEC4 = 3
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_INT = 4
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_IVEC2 = 5
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_IVEC3 = 6
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_IVEC4 = 7
|
|
||||||
integer(c_int) :: SHADER_UNIFORM_SAMPLER2D = 8
|
|
||||||
! Pixel formats
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1 ! 8 bit per pixel (no alpha)
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA = 2 ! 8*2 bpp (2 channels)
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R5G6B5 = 3 ! 16 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R8G8B8 = 4 ! 24 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R5G5B5A1 = 5 ! 16 bpp (1 bit alpha)
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R4G4B4A4 = 6 ! 16 bpp (4 bit alpha)
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 = 7 ! 32 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R32 = 8 ! 32 bpp (1 channel - float)
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R32G32B32 = 9 ! 32*3 bpp (3 channels - float)
|
|
||||||
integer(c_int) :: PIXELFORMAT_UNCOMPRESSED_R32G32B32A32 = 10 ! 32*4 bpp (4 channels - float)
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_DXT1_RGB = 11 ! 4 bpp (no alpha)
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_DXT1_RGBA = 12 ! 4 bpp (1 bit alpha)
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_DXT3_RGBA = 13 ! 8 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_DXT5_RGBA = 14 ! 8 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_ETC1_RGB = 15 ! 4 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_ETC2_RGB = 16 ! 4 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA = 17 ! 8 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_PVRT_RGB = 18 ! 4 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_PVRT_RGBA = 19 ! 4 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA = 20 ! 8 bpp
|
|
||||||
integer(c_int) :: PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA = 21 ! 2 bpp
|
|
||||||
! Texture parameters: filter mode
|
|
||||||
integer(c_int) :: TEXTURE_FILTER_POINT = 0 ! No filter, just pixel aproximation
|
|
||||||
integer(c_int) :: TEXTURE_FILTER_BILINEAR = 1 ! Linear filtering
|
|
||||||
integer(c_int) :: TEXTURE_FILTER_TRILINEAR = 2 ! Trilinear filtering (linear with mipmaps)
|
|
||||||
integer(c_int) :: TEXTURE_FILTER_ANISOTROPIC_4X = 3 ! Anisotropic filtering 4x
|
|
||||||
integer(c_int) :: TEXTURE_FILTER_ANISOTROPIC_8X = 4 ! Anisotropic filtering 8x
|
|
||||||
integer(c_int) :: TEXTURE_FILTER_ANISOTROPIC_16X = 5 ! Anisotropic filtering 16x
|
|
||||||
! Texture parameters: wrap mode
|
|
||||||
integer(c_int) :: TEXTURE_WRAP_REPEAT = 0 ! Repeats texture in tiled mode
|
|
||||||
integer(c_int) :: TEXTURE_WRAP_CLAMP = 1 ! Clamps texture to edge pixel in tiled mode
|
|
||||||
integer(c_int) :: TEXTURE_WRAP_MIRROR_REPEAT = 2 ! Mirrors and repeats the texture in tiled mode
|
|
||||||
integer(c_int) :: TEXTURE_WRAP_MIRROR_CLAMP = 3 ! Mirrors and clamps to border the texture in tiled mode
|
|
||||||
! Cubemap layouts
|
|
||||||
integer(c_int) :: CUBEMAP_LAYOUT_AUTO_DETECT = 0 ! Automatically detect layout type
|
|
||||||
integer(c_int) :: CUBEMAP_LAYOUT_LINE_VERTICAL = 1 ! Layout is defined by a vertical line with faces
|
|
||||||
integer(c_int) :: CUBEMAP_LAYOUT_LINE_HORIZONTAL = 2 ! Layout is defined by an horizontal line with faces
|
|
||||||
integer(c_int) :: CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR = 3 ! Layout is defined by a 3x4 cross with cubemap faces
|
|
||||||
integer(c_int) :: CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE = 4 ! Layout is defined by a 4x3 cross with cubemap faces
|
|
||||||
integer(c_int) :: CUBEMAP_LAYOUT_PANORAMA = 5 ! Layout is defined by a panorama image (equirectangular map)
|
|
||||||
! Font type, defines generation method
|
|
||||||
integer(c_int) :: FONT_DEFAULT = 0 ! Default font generation, anti-aliased
|
|
||||||
integer(c_int) :: FONT_BITMAP = 1 ! Bitmap font generation, no anti-aliasing
|
|
||||||
integer(c_int) :: FONT_SDF = 2 ! SDF font generation, requires external shader
|
|
||||||
! Color blending modes (pre-defined)
|
|
||||||
integer(c_int) :: BLEND_ALPHA = 0 ! Blend textures considering alpha (default)
|
|
||||||
integer(c_int) :: BLEND_ADDITIVE = 1 ! Blend textures adding colors
|
|
||||||
integer(c_int) :: BLEND_MULTIPLIED = 2 ! Blend textures multiplying colors
|
|
||||||
integer(c_int) :: BLEND_ADD_COLORS = 3 ! Blend textures adding colors (alternative)
|
|
||||||
integer(c_int) :: BLEND_SUBTRACT_COLORS = 4 ! Blend textures subtracting colors (alternative)
|
|
||||||
integer(c_int) :: BLEND_CUSTOM = 5 ! Belnd textures using custom src/dst factors (use rlSetBlendMode())
|
|
||||||
! Gestures
|
|
||||||
integer(c_int) :: GESTURE_NONE = 0
|
|
||||||
integer(c_int) :: GESTURE_TAP = 1
|
|
||||||
integer(c_int) :: GESTURE_DOUBLETAP = 2
|
|
||||||
integer(c_int) :: GESTURE_HOLD = 4
|
|
||||||
integer(c_int) :: GESTURE_DRAG = 8
|
|
||||||
integer(c_int) :: GESTURE_SWIPE_RIGHT = 16
|
|
||||||
integer(c_int) :: GESTURE_SWIPE_LEFT = 32
|
|
||||||
integer(c_int) :: GESTURE_SWIPE_UP = 64
|
|
||||||
integer(c_int) :: GESTURE_SWIPE_DOWN = 128
|
|
||||||
integer(c_int) :: GESTURE_PINCH_IN = 256
|
|
||||||
integer(c_int) :: GESTURE_PINCH_OUT = 512
|
|
||||||
|
|
||||||
!Camera system modes
|
|
||||||
integer(c_int) :: CAMERA_CUSTOM = 0
|
|
||||||
integer(c_int) :: CAMERA_FREE = 1
|
|
||||||
integer(c_int) :: CAMERA_ORBITAL = 2
|
|
||||||
integer(c_int) :: CAMERA_FIRST_PERSON = 3
|
|
||||||
integer(c_int) :: CAMERA_THIRD_PERSON = 4
|
|
||||||
|
|
||||||
!Camera projection
|
|
||||||
integer(c_int) :: CAMERA_PERSPECTIVE = 0
|
integer(c_int) :: CAMERA_PERSPECTIVE = 0
|
||||||
integer(c_int) :: CAMERA_ORTHOGRAPHIC = 1
|
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
@ -389,31 +80,6 @@ module raylib
|
||||||
integer(c_int), intent(in), value :: fps
|
integer(c_int), intent(in), value :: fps
|
||||||
end subroutine
|
end subroutine
|
||||||
|
|
||||||
subroutine update_camera(camera_ptr, mode) bind(c, name="UpdateCamera")
|
|
||||||
import :: c_ptr, c_int
|
|
||||||
type(c_ptr) :: camera_ptr
|
|
||||||
integer(c_int):: mode
|
|
||||||
end subroutine update_camera
|
|
||||||
|
|
||||||
subroutine show_cursor() bind(c, name="ShowCursor")
|
|
||||||
end subroutine show_cursor
|
|
||||||
|
|
||||||
subroutine hide_cursor() bind(c, name="HideCursor")
|
|
||||||
end subroutine hide_cursor
|
|
||||||
|
|
||||||
subroutine EnableCursor() bind(c, name="EnableCursor")
|
|
||||||
end subroutine EnableCursor
|
|
||||||
|
|
||||||
subroutine disable_cursor() bind(c, name="DisableCursor")
|
|
||||||
end subroutine disable_cursor
|
|
||||||
|
|
||||||
function is_key_pressed(key) result(res) bind(c, name="IsKeyPressed")
|
|
||||||
import :: c_int
|
|
||||||
import :: c_bool
|
|
||||||
logical(c_bool) :: res
|
|
||||||
integer(c_int), intent(in), value :: key
|
|
||||||
end function is_key_pressed
|
|
||||||
|
|
||||||
function is_key_down(key) result(res) bind(c, name="IsKeyDown")
|
function is_key_down(key) result(res) bind(c, name="IsKeyDown")
|
||||||
import :: c_int
|
import :: c_int
|
||||||
import :: c_bool
|
import :: c_bool
|
||||||
|
@ -421,20 +87,6 @@ module raylib
|
||||||
integer(c_int), intent(in), value :: key
|
integer(c_int), intent(in), value :: key
|
||||||
end function is_key_down
|
end function is_key_down
|
||||||
|
|
||||||
function is_key_released(key) result(res) bind(c, name="IsKeyReleased")
|
|
||||||
import :: c_int
|
|
||||||
import :: c_bool
|
|
||||||
logical(c_bool) :: res
|
|
||||||
integer(c_int), intent(in), value :: key
|
|
||||||
end function is_key_released
|
|
||||||
|
|
||||||
function is_key_up(key) result(res) bind(c, name="IsKeyUp")
|
|
||||||
import :: c_int
|
|
||||||
import :: c_bool
|
|
||||||
logical(c_bool) :: res
|
|
||||||
integer(c_int), intent(in), value :: key
|
|
||||||
end function is_key_up
|
|
||||||
|
|
||||||
subroutine draw_grid(slices, spacing) bind(c, name="DrawGrid")
|
subroutine draw_grid(slices, spacing) bind(c, name="DrawGrid")
|
||||||
import :: c_int
|
import :: c_int
|
||||||
import :: c_float
|
import :: c_float
|
||||||
|
@ -442,17 +94,6 @@ module raylib
|
||||||
real(c_float), intent(in), value :: spacing
|
real(c_float), intent(in), value :: spacing
|
||||||
end subroutine draw_grid
|
end subroutine draw_grid
|
||||||
|
|
||||||
subroutine draw_text(text, posX, posY, fontSize, col) bind(c, name="DrawText")
|
|
||||||
import :: c_int
|
|
||||||
import :: color
|
|
||||||
import :: c_char
|
|
||||||
character(c_char), dimension(*), intent(in) :: text
|
|
||||||
integer(c_int), intent(in), value :: posX
|
|
||||||
integer(c_int), intent(in), value :: posY
|
|
||||||
integer(c_int), intent(in), value :: fontSize
|
|
||||||
type(color), intent(in), value :: col
|
|
||||||
end subroutine draw_text
|
|
||||||
|
|
||||||
subroutine draw_cube(position, width, height, length, col) bind(c, name="DrawCube")
|
subroutine draw_cube(position, width, height, length, col) bind(c, name="DrawCube")
|
||||||
import :: vector3
|
import :: vector3
|
||||||
import :: c_float
|
import :: c_float
|
||||||
|
@ -464,26 +105,6 @@ module raylib
|
||||||
type(color), intent(in), value :: col
|
type(color), intent(in), value :: col
|
||||||
end subroutine draw_cube
|
end subroutine draw_cube
|
||||||
|
|
||||||
subroutine draw_cube_wires(position, width, height, length, col) bind(c, name="DrawCubeWires")
|
|
||||||
import :: vector3
|
|
||||||
import :: c_float
|
|
||||||
import :: color
|
|
||||||
type(vector3), intent(in), value :: position
|
|
||||||
real(c_float), intent(in), value :: width
|
|
||||||
real(c_float), intent(in), value :: height
|
|
||||||
real(c_float), intent(in), value :: length
|
|
||||||
type(color), intent(in), value :: col
|
|
||||||
end subroutine draw_cube_wires
|
|
||||||
|
|
||||||
subroutine draw_plane(centerPos, size, col) bind(c, name="DrawPlane")
|
|
||||||
import vector3
|
|
||||||
import vector2
|
|
||||||
import color
|
|
||||||
type(vector3), intent(in), value :: centerPos
|
|
||||||
type(vector2), intent(in), value :: size
|
|
||||||
type(color), intent(in), value :: col
|
|
||||||
end subroutine draw_plane
|
|
||||||
|
|
||||||
function get_time() result(res) bind(c, name="GetTime")
|
function get_time() result(res) bind(c, name="GetTime")
|
||||||
import :: c_double
|
import :: c_double
|
||||||
real(c_double) :: res
|
real(c_double) :: res
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
# server
|
# server
|
||||||
|
|
||||||
- request
|
The server implementation is as simple as I could make it.
|
||||||
|
|
||||||
|
I found a library called mod_dill from the [tcp-client-server demo code](https://github.com/modern-fortran/tcp-client-server) from a book on modern fortran. This gave me a simple TCP interface to send and recieve "messages".
|
||||||
|
|
||||||
|
Originally I had tried saving formatted fortran data into a string and trying to send that, but when you convert the fortran string to a c-string it oftend became garbled and unusable when sent through the tcp connection so I stopped using that method.
|
||||||
|
|
||||||
|
I found in [fpm](https://fpm.fortran-lang.org/index.html) [official registry](https://registry-frontend.vercel.app/) a json library which would make it *much* easier to deal with data transfer.
|
||||||
|
|
||||||
|
The simplest way to implement the communcation between the server and clients would be a series of tcp requests and responses.
|
||||||
|
|
||||||
|
- request
|
||||||
- int :: request_type
|
- int :: request_type
|
||||||
- ping # 0
|
- ping # 0
|
||||||
- login # 1
|
- login # 1
|
||||||
|
@ -12,10 +21,23 @@
|
||||||
- double :: y_pos
|
- double :: y_pos
|
||||||
|
|
||||||
- response
|
- response
|
||||||
- int :: response_type
|
|
||||||
- int :: number_of_records
|
|
||||||
- array :: records
|
- array :: records
|
||||||
- str(24) :: username
|
- str(24) :: username
|
||||||
- str(24) :: color
|
- str(24) :: color
|
||||||
- double :: x_pos
|
- double :: x_pos
|
||||||
- double :: y_pos
|
- double :: y_pos
|
||||||
|
|
||||||
|
For each request, the same response is returned with is a list of the logged in users.
|
||||||
|
|
||||||
|
The commands that can be sent to the server are logging in, logging out, moving, and the default "ping" which is essentially a noop from the servers pov.
|
||||||
|
|
||||||
|
The server uses the same sqlite library as the [www implementation](../www/README.md).
|
||||||
|
|
||||||
|
The server loop is:
|
||||||
|
1. listen for connection
|
||||||
|
2. read message from client
|
||||||
|
3. convert c string to fortran string
|
||||||
|
4. convert the fortran string to a json object
|
||||||
|
5. run the command from the json object
|
||||||
|
6. create a json array of the logged in users and send to client.
|
||||||
|
|
||||||
|
|
|
@ -52,17 +52,17 @@ program main
|
||||||
|
|
||||||
connection = tcp_accept(socket, addr_remote, -1_c_int64_t)
|
connection = tcp_accept(socket, addr_remote, -1_c_int64_t)
|
||||||
call ipaddr_str(addr, address_string)
|
call ipaddr_str(addr, address_string)
|
||||||
print *, 'New connection from '//trim(address_string)
|
! print *, 'New connection from '//trim(address_string)
|
||||||
connection = suffix_attach(connection, TCP_SUFFIX, 2_c_size_t)
|
connection = suffix_attach(connection, TCP_SUFFIX, 2_c_size_t)
|
||||||
print *, 'connected'
|
! print *, 'connected'
|
||||||
message_size = mrecv(connection, message, msglen, -1_c_int64_t)
|
message_size = mrecv(connection, message, msglen, -1_c_int64_t)
|
||||||
print *, message_size
|
! print *, message_size
|
||||||
|
|
||||||
call c_f_string(message, jsn_string)
|
call c_f_string(message, jsn_string)
|
||||||
|
|
||||||
call json%initialize()
|
call json%initialize()
|
||||||
call json%deserialize(jsn_string(:Len_Trim(jsn_string)))
|
call json%deserialize(jsn_string(:Len_Trim(jsn_string)))
|
||||||
call json%print()
|
! call json%print()
|
||||||
|
|
||||||
call json%get('user.username', username, found)
|
call json%get('user.username', username, found)
|
||||||
if (.not. found) print *, 'cant find username!'
|
if (.not. found) print *, 'cant find username!'
|
||||||
|
|
|
@ -198,8 +198,8 @@ contains
|
||||||
call json%add(root, users)
|
call json%add(root, users)
|
||||||
call json%serialize(root, str)
|
call json%serialize(root, str)
|
||||||
|
|
||||||
print *, 'sending users'
|
! print *, 'sending users'
|
||||||
call json%print(root)
|
! call json%print(root)
|
||||||
|
|
||||||
rc = msend(connection, f_c_string(str, .true.), &
|
rc = msend(connection, f_c_string(str, .true.), &
|
||||||
transfer(Len_Trim(f_c_string(str, .true.)), 0_c_size_t), -1_c_int64_t)
|
transfer(Len_Trim(f_c_string(str, .true.)), 0_c_size_t), -1_c_int64_t)
|
||||||
|
|
|
@ -29,9 +29,7 @@ I next implemented the post handling. In www.f90, it checks to see if the header
|
||||||
|
|
||||||
I found a library to interface with the sqlite library I will store the username, password, and other information about.
|
I found a library to interface with the sqlite library I will store the username, password, and other information about.
|
||||||
|
|
||||||
The issue is that fortran does not have a built in cryptographic hash library nor is it in the stdlib, I did find a implementation of the [SM3](https://github.com/zoziha/SM3-Fortran/tree/main) hash which is cryptographically sound, and have used that.
|
The issue is that fortran does not have a built in cryptographic hash library nor is it in the stdlib. So it has been ommited for this implementation, although it should not be in a real world situation.
|
||||||
|
|
||||||
If this were to be used in the real world I would prefer to use [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) as it is the most common password hashing algorithm.
|
|
||||||
|
|
||||||
The implementation does not work well with existing systems since you have to convert from fortran strings to c strings and it returns an integer array of c strings which has to be converted back into fortran strings.
|
The implementation does not work well with existing systems since you have to convert from fortran strings to c strings and it returns an integer array of c strings which has to be converted back into fortran strings.
|
||||||
|
|
||||||
|
@ -172,4 +170,21 @@ On a `POST` request it will parse the body and insert the user data into the dat
|
||||||
|
|
||||||
This is probably the longest I have had to take for the smallest amount of actual features for anything I have created yet.
|
This is probably the longest I have had to take for the smallest amount of actual features for anything I have created yet.
|
||||||
|
|
||||||
Also the hex to integer just doesnt work at all so I had to implement one myself....
|
Also the hex to integer just doesnt work at all so I had to implement one myself...
|
||||||
|
|
||||||
|
The next issue was SQL. There is no native interface with Fortran and SQLite3 (which is the databse I am using for this project). The only "native" soluition would be to use the `execute_command_line` subroutine and then read the output from a temp file in order to do sql operations.
|
||||||
|
|
||||||
|
So I looked around on the internet for a different solution.
|
||||||
|
|
||||||
|
To my supprise I found a project that aims to add a package manager to Fortran called [fpm](https://fpm.fortran-lang.org/index.html)
|
||||||
|
|
||||||
|
One of the libraries that was available was a sqlite implementation. So I decided that since I was already a month behind schedule I would stop being so strict with my rule of wanting to use "100% vanilla Fortran" and start using this package manager.
|
||||||
|
|
||||||
|
The Fortran package manger is actually pretty fantastic. It has a similar feel to [npm](https://www.npmjs.com) if you have expereince with that.
|
||||||
|
|
||||||
|
Creating a new project is as easy as `fpm new Project_Name` and adding libraries can be done by editing the .toml file and running `fpm build`
|
||||||
|
|
||||||
|
The specific library I found for sqlite is [fortran-sqlite3](https://github.com/interkosmos/fortran-sqlite3).
|
||||||
|
|
||||||
|
So I finished up the last few things in the implementation and called it complete.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue