DEFENSE · RAMPART ACCESS CONTROL

How to Change Rampart Access Without Treating Public as an Ally List

Lock a one-time setPublic() request to Rampart ID, room, coordinates, target boolean and target-bound confirmation, verify ownership and current state, disable before the call, save the result, and re-read isPublic later.

Verification statusChinese source article: Reviewed in full · Official docs: Checked — StructureRampart.setPublic(), isPublic, ownership and return codes · Access boundary: Public permits other players' Creeps to pass; it is not a per-player allow-list or intent check

VERIFICATION

Evidence and test status

Chinese source article
Reviewed in full
Official docs
Checked — StructureRampart.setPublic(), isPublic, ownership and return codes
Access boundary
Public permits other players' Creeps to pass; it is not a per-player allow-list or intent check
Execution boundary
OK schedules the change; the current Rampart must be recovered and isPublic observed later
JavaScript syntax
Passed
Offline access review
Passed — request, confirmation, ownership, type, room, position, matching state and ready states
Screeps Console test
Pending
Live public/private passage, object replacement, ownership and next-tick state test
Pending
Last verified
July 26, 2026

Quick answer

Inspect the Rampart first, then create one request containing its exact ID, expected room, X, Y, desired boolean state, and a confirmation generated from that state and position. Recover the current object, verify it is your Rampart and all identity fields match, stop if isPublic already equals the requested value, disable the request before setPublic(), save the return code, and re-read the Rampart later.

Understand what public means

rampart.setPublic(true);

Public access permits other players' Creeps to pass through the Rampart. The method does not implement an alliance list, player-specific access, a visitor schedule, hostile-body filtering, or intent detection.

rampart.setPublic(false);

Setting the value to false restores private passage behavior. It does not transfer ownership, change other Ramparts, activate Safe Mode, or run Tower logic.

Inspect Ramparts read-only first

function inspectOwnedRamparts(roomName) {
  const room = Game.rooms[roomName];
  if (!room) {
    return [];
  }

  return room.find(FIND_MY_STRUCTURES, {
    filter: structure =>
      structure.structureType === STRUCTURE_RAMPART
  }).map(rampart => ({
    id: rampart.id,
    roomName: rampart.pos.roomName,
    x: rampart.pos.x,
    y: rampart.pos.y,
    isPublic: rampart.isPublic,
    hits: rampart.hits,
    hitsMax: rampart.hitsMax
  }));
}

Review the ID, coordinate, current state and defensive context before creating a mutation request.

Bind confirmation to target state and position

function buildRampartConfirmation(
  roomName,
  x,
  y,
  shouldBePublic
) {
  const state = shouldBePublic
    ? 'PUBLIC'
    : 'PRIVATE';

  return 'SET_RAMPART_' + state + '_' + roomName + '_' + x + '_' + y;
}
Memory.rampartPublicRequest = {
  enabled: true,
  rampartId: 'replace-with-owned-rampart-id',
  roomName: 'W1N1',
  x: 20,
  y: 20,
  public: true,
  confirmation: 'SET_RAMPART_PUBLIC_W1N1_20_20'
};

Changing public to private, moving the expected coordinate, or copying the request to another room invalidates the old phrase.

Build a testable access plan

function evaluateRampartRequest(input) {
  const request = input.request;
  const rampart = input.rampart;

  if (!request || request.enabled !== true) {
    return { ready: false, reason: 'disabled' };
  }

  if (
    typeof request.rampartId !== 'string'
    || typeof request.roomName !== 'string'
    || !Number.isInteger(request.x)
    || !Number.isInteger(request.y)
    || request.x < 0
    || request.x > 49
    || request.y < 0
    || request.y > 49
    || typeof request.public !== 'boolean'
  ) {
    return { ready: false, reason: 'invalid-request' };
  }

  const expected = buildRampartConfirmation(
    request.roomName,
    request.x,
    request.y,
    request.public
  );
  if (request.confirmation !== expected) {
    return { ready: false, reason: 'confirmation-mismatch' };
  }

  if (!rampart) {
    return { ready: false, reason: 'rampart-missing' };
  }

  if (input.owned !== true) {
    return { ready: false, reason: 'not-owner' };
  }

  if (rampart.structureType !== STRUCTURE_RAMPART) {
    return { ready: false, reason: 'type-mismatch' };
  }

  if (rampart.pos.roomName !== request.roomName) {
    return { ready: false, reason: 'room-mismatch' };
  }

  if (
    rampart.pos.x !== request.x
    || rampart.pos.y !== request.y
  ) {
    return { ready: false, reason: 'position-mismatch' };
  }

  if (rampart.isPublic === request.public) {
    return { ready: false, reason: 'state-already-matches' };
  }

  return { ready: true, reason: 'ready' };
}

Complete setPublic() handler

function handleRampartPublicRequest() {
  const request = Memory.rampartPublicRequest;

  if (!request || request.enabled !== true) {
    return { status: 'disabled' };
  }

  const rampart = typeof request.rampartId === 'string'
    ? Game.getObjectById(request.rampartId)
    : null;
  const owned = Boolean(
    rampart
    && Game.structures[rampart.id]
  );
  const plan = evaluateRampartRequest({
    request,
    rampart,
    owned
  });

  request.checkedAt = Game.time;
  request.status = plan.reason;

  if (!plan.ready) {
    request.enabled = false;
    return { status: plan.reason };
  }

  request.enabled = false;
  request.status = 'submitted';
  request.submittedAt = Game.time;
  request.before = {
    rampartId: rampart.id,
    roomName: rampart.pos.roomName,
    x: rampart.pos.x,
    y: rampart.pos.y,
    beforePublic: rampart.isPublic,
    requestedPublic: request.public
  };

  const result = rampart.setPublic(request.public);

  request.result = result;
  request.resultAt = Game.time;
  request.status = result === OK
    ? 'accepted'
    : 'failed-review-required';

  return {
    status: request.status,
    result,
    before: request.before
  };
}
module.exports.loop = function () {
  const outcome = handleRampartPublicRequest();

  if (
    outcome.status === 'accepted'
    || outcome.status === 'failed-review-required'
  ) {
    console.log(JSON.stringify({
      type: 'rampart-public-result',
      ...outcome
    }));
  }
};

Stop when the state already matches

A matching state can mean the request is stale or another module already handled it. Close the request, record state-already-matches, and avoid a permanent per-tick no-op loop.

Disable before the call

request.enabled = false;
const result = rampart.setPublic(request.public);

Opening a Rampart can change real room access. A rejected request must be reviewed and explicitly resubmitted instead of retrying automatically.

Verify the next tick

function verifyRampartPublicRequest(request) {
  const rampart = typeof request?.rampartId === 'string'
    ? Game.getObjectById(request.rampartId)
    : null;

  if (!rampart) {
    return {
      verified: false,
      reason: 'rampart-not-visible'
    };
  }

  return {
    verified: rampart.isPublic === request.public,
    rampartId: rampart.id,
    isPublic: rampart.isPublic,
    requestedPublic: request.public
  };
}

Recover the current object. Do not reuse a previous-tick Rampart reference.

Public is not a visitor whitelist

One boolean cannot represent allowed usernames, permitted body parts, time windows, room-specific access, or automatic closure after hostile behavior. Those policies need a higher-level dispatcher, and the safest default remains private unless a reviewed operation requires public passage.

Handle return codes

CodeMeaningReview
OKState change scheduledRe-read isPublic later
ERR_NOT_OWNERRampart is not yoursID, Game.structures and ownership

Do not copy Creep range or Energy return codes into this method.

Debugging checklist

  • Inspect Ramparts read-only first.
  • Use the exact Rampart ID.
  • Lock room, X, Y and target boolean.
  • Bind the confirmation to state and position.
  • Verify ownership through current objects.
  • Stop on type, room or position mismatch.
  • Close a matching-state request.
  • Disable before the call.
  • Save the return code and before snapshot.
  • Re-read isPublic later.

Scope and next steps

This guide does not implement alliances, scheduled gates, body-part access, automatic threat response, Safe Mode coordination, or multi-Rampart batches. Continue with staged fortification maintenance.

Frequently asked questions

Can I pass a username array to setPublic()?

No. The method accepts a boolean, not a player list.

Why not make every road Rampart public automatically?

Layout alone does not prove access intent. A copied rule can expose protected interior paths or critical Structures.

Should public Ramparts automatically return to private?

That can be a separate reviewed task, but this one-time handler does not invent a timeout or silently reverse another request.

Official documentation

SOURCE AND SCOPE

Review the source, evidence, or next system

This English guide is rewritten for a focused search intent while preserving the technical scope and verification boundaries of its Chinese source. Live-room evidence is claimed only when the verification record says it exists.