diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index e029650c0ced525f3bfc56fc9863d9816f6ebb63..545f9c144c3ba798c96609e4bcb0e6ca22f1f79e 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -24,12 +24,14 @@
 #include "../byteptr.h"
 #include "../lua_script.h"
 #include "../m_misc.h"
+#include "../i_time.h"
 
 
 #define IO_INPUT	1
 #define IO_OUTPUT	2
 
-#define FILELIMIT (1024 * 1024) // Size limit for reading/writing files
+#define MAXBYTESPERMINUTE (10 * 1024 * 1024) // Rate limit for writing files
+#define MAXOPENSPERMINUTE 50 // Rate limit for opening new files
 
 #define FMT_FILECALLBACKID "file_callback_%d"
 
@@ -46,6 +48,10 @@ static const char *whitelist[] = {
 };
 
 
+static INT64 numwrittenbytes = 0;
+static INT64 numopenedfiles = 0;
+
+
 static int pushresult (lua_State *L, int i, const char *filename) {
   int en = errno;  /* calls to Lua API may change this value */
   if (i) {
@@ -252,6 +258,17 @@ static int io_openlocal (lua_State *L) {
 			        "Files can't be opened while being downloaded\n",
 			        filename);
 
+  // Reading not restricted
+  if (client && (strchr(mode, 'w') || strchr(mode, 'a') || strchr(mode, '+')))
+  {
+    if (numopenedfiles >= (I_GetTime() / (60*TICRATE) + 1) * MAXOPENSPERMINUTE)
+      I_Error("Access denied to %s\n"
+              "File opening rate exceeded\n",
+              filename);
+
+    numopenedfiles++;
+  }
+
 	MakePathDirs(realfilename);
 
 	// Open and return the file
@@ -527,9 +544,12 @@ static int g_write (lua_State *L, FILE *f, int arg) {
     else {
       size_t l;
       const char *s = luaL_checklstring(L, arg, &l);
-      if (ftell(f) + l > FILELIMIT) {
-          luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
-          break;
+      if (client) {
+        if (numwrittenbytes + l > (I_GetTime() / (60*TICRATE) + 1) * MAXBYTESPERMINUTE) {
+            luaL_error(L,"file write rate limit exceeded; changes have been discarded");
+            break;
+        }
+        numwrittenbytes += l;
       }
       status = status && (fwrite(s, sizeof(char), l, f) == l);
     }